@@ -129,20 +129,22 @@ namespace banana {
129
129
return contours;
130
130
}
131
131
132
- auto Analyzer::GetBananaCenterLineCoefficients (Contour const & banana_contour) const -> std::expected<std::tuple<double, double, double>, AnalysisError> {
132
+ auto Analyzer::GetBananaCenterLineCoefficients (Contour const & banana_contour, PCAResult const & pca_result) const -> std::expected<std::tuple<double, double, double>, AnalysisError> {
133
+ // rotate the contour so that it's horizontal
134
+ auto const rotated_contour = this ->RotateContour (banana_contour, pca_result.center , pca_result.angle );
135
+
133
136
auto const to_std_pair_fn = [](auto const & p) -> std::pair<double , double > { return {p.x , p.y }; };
134
- auto const coeffs = polyfit::Fit2DPolynomial (banana_contour | std::views::transform (to_std_pair_fn));
135
- #ifdef SHOW_DEBUG_INFO
136
- if (coeffs) {
137
- std::cout << std::format (" y = {} + {} * x + {} * x^2" , std::get<0 >(*coeffs), std::get<1 >(*coeffs),
138
- std::get<2 >(*coeffs)) << std::endl;
139
- } else {
140
- std::cerr << " couldn't find a solution!" << std::endl;
141
- }
142
- #endif
137
+ auto const coeffs = polyfit::Fit2DPolynomial (rotated_contour | std::views::transform (to_std_pair_fn));
143
138
return coeffs.transform_error ([](auto const & _) -> auto {return AnalysisError::kPolynomialCalcFailure ;});
144
139
}
145
140
141
+ auto Analyzer::RotateContour (Contour const & contour, cv::Point const & center, double const angle) const -> Contour {
142
+ auto const rotation_matrix = cv::getRotationMatrix2D (center, angle * 180 / std::numbers::pi , 1 );
143
+ Contour rotated_contour{contour.size ()};
144
+ cv::transform (contour, rotated_contour, rotation_matrix);
145
+ return rotated_contour;
146
+ }
147
+
146
148
auto Analyzer::GetPCA (const Contour &banana_contour) const -> Analyzer::PCAResult {
147
149
// implementation adapted from https://docs.opencv.org/4.9.0/d1/dee/tutorial_introduction_to_pca.html
148
150
@@ -179,7 +181,7 @@ namespace banana {
179
181
180
182
auto Analyzer::AnalyzeBanana (cv::Mat const & image, Contour const & banana_contour) const -> std::expected<AnalysisResult, AnalysisError> {
181
183
auto const pca = this ->GetPCA (banana_contour);
182
- auto const coeffs = this ->GetBananaCenterLineCoefficients (banana_contour);
184
+ auto const coeffs = this ->GetBananaCenterLineCoefficients (banana_contour, pca );
183
185
if (!coeffs) {
184
186
return std::unexpected{coeffs.error ()};
185
187
}
@@ -193,9 +195,15 @@ namespace banana {
193
195
}
194
196
195
197
void Analyzer::PlotCenterLine (cv::Mat& draw_target, AnalysisResult const & result) const {
198
+ // note that the coefficients for the center line are given in relation to the bananas main axis.
199
+ // accordingly we have to rotate the resulting line to plot it over the banana in the image.
200
+
201
+ // rotate the contour so that it's horizontal (needed to calculate the x-axis points for plotting in the coordinate system of the banana).
202
+ auto const rotated_contour = this ->RotateContour (result.contour , result.estimated_center , result.rotation_angle );
203
+
196
204
auto const & [coeff_0, coeff_1, coeff_2] = result.center_line_coefficients ;
197
205
198
- auto const minmax_x = std::ranges::minmax (result. contour | std::views::transform (&cv::Point ::x));
206
+ auto const minmax_x = std::ranges::minmax (rotated_contour | std::views::transform (&cv::Point ::x));
199
207
200
208
// / Calculate a Point2d for the [x,y] coords based on the provided polynomial and x-values.
201
209
auto const calc_xy = [&coeff_0, &coeff_1, &coeff_2](auto const && x) -> cv::Point2d {
@@ -210,7 +218,10 @@ namespace banana {
210
218
auto const center_line_points = std::views::iota (start, end) | std::views::transform (calc_xy);
211
219
auto const center_line_points2i = center_line_points | std::views::transform (to_point2i) | std::ranges::to<std::vector>();
212
220
213
- cv::polylines (draw_target, center_line_points2i, false , this ->helper_annotation_color_ , 10 );
221
+ // rotate the center line back so that it fits on the image
222
+ auto const rotated_center_line = this ->RotateContour (center_line_points2i, result.estimated_center , -result.rotation_angle );
223
+
224
+ cv::polylines (draw_target, rotated_center_line, false , this ->helper_annotation_color_ , 10 );
214
225
}
215
226
216
227
void Analyzer::PlotPCAResult (cv::Mat& draw_target, AnalysisResult const & result) const {
0 commit comments