Skip to content

Commit a5622f2

Browse files
committed
Calculate RMSE of calibration points and print difference
1 parent 031fce3 commit a5622f2

File tree

5 files changed

+171
-64
lines changed

5 files changed

+171
-64
lines changed

src/app/plugins/plugin_cameracalib.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,11 @@ void PluginCameraCalibration::detectEdgesOnSingleLine(
204204
Sobel::centerOfLine(
205205
*grey_image, start_image.x, end_image.x, start_image.y,
206206
end_image.y, point_image, center_found, kSobelThreshold);
207-
calibration_data.imgPts.push_back(std::make_pair(point_image,center_found));
207+
CameraParameters::CalibrationDataPoint point(point_image, center_found);
208+
calibration_data.points.push_back(point);
208209
calibration_data.alphas.push_back(alpha);
209210
}
210-
if (calibration_data.imgPts.size() > 2) {
211+
if (calibration_data.points.size() > 2) {
211212
// Need at least two points to uniquely define a line segment.
212213
camera_parameters.calibrationSegments.push_back(calibration_data);
213214
}
@@ -271,10 +272,11 @@ void PluginCameraCalibration::detectEdgesOnSingleArc(
271272
Sobel::centerOfLine(
272273
*grey_image, start_image.x, end_image.x, start_image.y,
273274
end_image.y, point_image, center_found, kSobelThreshold);
274-
calibration_data.imgPts.push_back(std::make_pair(point_image,center_found));
275+
CameraParameters::CalibrationDataPoint point(point_image, center_found);
276+
calibration_data.points.push_back(point);
275277
calibration_data.alphas.push_back(alpha);
276278
}
277-
if (calibration_data.imgPts.size() > 3) {
279+
if (calibration_data.points.size() > 3) {
278280
// Need at least three points to uniquely define a circular arc.
279281
camera_parameters.calibrationSegments.push_back(calibration_data);
280282
}

src/app/plugins/plugin_visualize.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,9 +353,10 @@ void PluginVisualize::DrawDetectedEdges(
353353
for (size_t ls = 0; ls < camera_parameters.calibrationSegments.size(); ++ls) {
354354
const CameraParameters::CalibrationData& segment =
355355
camera_parameters.calibrationSegments[ls];
356-
for(unsigned int edge=0; edge<segment.imgPts.size(); ++edge) {
357-
if (!(segment.imgPts[edge].second)) continue;
358-
const GVector::vector2d<double>& image_point = segment.imgPts[edge].first;
356+
for(unsigned int edge=0; edge<segment.points.size(); ++edge) {
357+
if (!(segment.points[edge].detected)) continue;
358+
const GVector::vector2d<double>& image_point = segment.points[edge].img_point;
359+
const GVector::vector2d<double>& image_closest_point = segment.points[edge].img_closestPointToSegment;
359360
vis_frame->data.drawBox(
360361
image_point.x - 5, image_point.y - 5, 11, 11, edge_draw_color);
361362
const double alpha = segment.alphas[edge];
@@ -366,6 +367,13 @@ void PluginVisualize::DrawDetectedEdges(
366367
(segment.p2 - segment.p1).norm();
367368
DrawEdgeTangent(image_point, field_point, field_tangent, vis_frame,
368369
edge_draw_color);
370+
if (image_closest_point.nonzero()) {
371+
vis_frame->data.drawLine((int)image_point.x,
372+
(int)image_point.y,
373+
(int)image_closest_point.x,
374+
(int)image_closest_point.y,
375+
RGB::Pink);
376+
}
369377
} else {
370378
const double angle =
371379
alpha * segment.theta1 + (1.0 - alpha) * segment.theta2;

src/shared/util/camera_calibration.cpp

Lines changed: 123 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -396,10 +396,10 @@ double CameraParameters::calc_chisqr(
396396

397397
int i = 0;
398398
for (; ls_it != calibrationSegments.end(); ls_it++) {
399-
auto imgPts_it = (*ls_it).imgPts.begin();
400-
for (; imgPts_it != (*ls_it).imgPts.end(); imgPts_it++) {
399+
auto imgPts_it = (*ls_it).points.begin();
400+
for (; imgPts_it != (*ls_it).points.end(); imgPts_it++) {
401401
// Integrate only if a valid point on line
402-
if (imgPts_it->second) {
402+
if (imgPts_it->detected) {
403403
GVector::vector2d<double> proj_p;
404404
double alpha = p_alpha(i) + p(STATE_SPACE_DIMENSION + i);
405405

@@ -417,10 +417,10 @@ double CameraParameters::calc_chisqr(
417417
// Project into image plane
418418
field2image(alpha_point, proj_p, p);
419419

420-
chisqr += (proj_p.x-imgPts_it->first.x) *
421-
(proj_p.x-imgPts_it->first.x) * cov_lsx_inv +
422-
(proj_p.y - imgPts_it->first.y) *
423-
(proj_p.y - imgPts_it->first.y) * cov_lsy_inv;
420+
chisqr += (proj_p.x-imgPts_it->img_point.x) *
421+
(proj_p.x-imgPts_it->img_point.x) * cov_lsx_inv +
422+
(proj_p.y - imgPts_it->img_point.y) *
423+
(proj_p.y - imgPts_it->img_point.y) * cov_lsy_inv;
424424
i++;
425425
}
426426
}
@@ -445,14 +445,99 @@ double CameraParameters::do_calibration(int cal_type) {
445445
}
446446

447447
if(use_opencv_model->getBool()) {
448-
return calibrateExtrinsicModel(p_f, p_i, cal_type);
448+
calibrateExtrinsicModel(p_f, p_i, cal_type);
449449
} else {
450-
return calibrate(p_f, p_i, cal_type);
450+
calibrate(p_f, p_i, cal_type);
451451
}
452+
453+
updateCalibrationDataPoints();
454+
if (cal_type & FOUR_POINT_INITIAL) {
455+
return calculateFourPointRmse(p_f, p_i);
456+
}
457+
return calculateCalibrationDataPointsRmse();
452458
}
453459

454-
void CameraParameters::reset() const {
460+
double CameraParameters::calculateFourPointRmse(std::vector<GVector::vector3d<double> > &p_f,
461+
std::vector<GVector::vector2d<double> > &p_i) const {
462+
auto it_p_f = p_f.begin();
463+
auto it_p_i = p_i.begin();
464+
double sum = 0;
465+
for (; it_p_f != p_f.end(); it_p_f++, it_p_i++) {
466+
GVector::vector2d<double> proj_p;
467+
field2image(*it_p_f, proj_p);
468+
GVector::vector3d<double> some_point;
469+
image2field(some_point,proj_p, 0);
455470

471+
double diff_x = proj_p.x - it_p_i->x;
472+
double diff_y = proj_p.y - it_p_i->y;
473+
sum += diff_x * diff_x + diff_y * diff_y;
474+
}
475+
return sqrt(sum / (double) p_f.size());
476+
}
477+
478+
void CameraParameters::updateCalibrationDataPoints() {
479+
for (auto & segment : calibrationSegments) {
480+
if (!segment.straightLine) {
481+
continue;
482+
}
483+
484+
for (auto & imgPt : segment.points) {
485+
if (imgPt.detected) {
486+
image2field(imgPt.world_point, imgPt.img_point, 0.0);
487+
488+
GVector::vector2d<double> line0(segment.p1.x, segment.p1.y);
489+
GVector::vector2d<double> line1(segment.p2.x, segment.p2.y);
490+
GVector::vector2d<double> point(imgPt.world_point.x, imgPt.world_point.y);
491+
GVector::vector2d<double> closestPoint = GVector::closest_point_on_line(line0, line1, point);
492+
imgPt.world_closestPointToSegment.x = closestPoint.x;
493+
imgPt.world_closestPointToSegment.y = closestPoint.y;
494+
field2image(imgPt.world_closestPointToSegment, imgPt.img_closestPointToSegment);
495+
}
496+
}
497+
}
498+
}
499+
500+
double CameraParameters::calculateCalibrationDataPointsRmse() {
501+
double rmse_sum_all = 0;
502+
int rmse_cnt_all = 0;
503+
for (auto & segment : calibrationSegments) {
504+
if (!segment.straightLine) {
505+
continue;
506+
}
507+
508+
double rmse_sum_segment = 0;
509+
int rmse_cnt_segment = 0;
510+
511+
for (auto imgPt : segment.points) {
512+
if (imgPt.detected) {
513+
double distance = (imgPt.img_closestPointToSegment - imgPt.img_point).length();
514+
rmse_sum_segment += distance*distance;
515+
rmse_cnt_segment++;
516+
}
517+
}
518+
std::cout << "segment ["
519+
<< segment.p1.x << "," << segment.p1.y
520+
<< "] -> ["
521+
<< segment.p2.x << "," << segment.p2.y
522+
<< "] RMSE: " << sqrt(rmse_sum_segment / rmse_cnt_segment)
523+
<< std::endl;
524+
rmse_sum_all += rmse_sum_segment;
525+
rmse_cnt_all += rmse_cnt_segment;
526+
}
527+
double rmse = sqrt(rmse_sum_all / rmse_cnt_all);
528+
std::cout << "Calibration segment RMSE: " << rmse << std::endl;
529+
return rmse;
530+
}
531+
532+
CameraParameters::CalibrationDataPoint::CalibrationDataPoint(GVector::vector2d<double> img_point, bool detected)
533+
: detected(detected),
534+
img_point(img_point),
535+
img_closestPointToSegment(0,0),
536+
world_point(0,0,0),
537+
world_closestPointToSegment(0,0,0)
538+
{}
539+
540+
void CameraParameters::reset() const {
456541
focal_length->resetToDefault();
457542
principal_point_x->resetToDefault();
458543
principal_point_y->resetToDefault();
@@ -496,7 +581,7 @@ bool contains(const cv::Rect& rect, const cv::Point2d& pt, double margin) {
496581
&& rect.y - margin <= pt.y && pt.y < rect.y + rect.height + margin * 2;
497582
}
498583

499-
double CameraParameters::calibrateExtrinsicModel(
584+
void CameraParameters::calibrateExtrinsicModel(
500585
std::vector<GVector::vector3d<double>> &p_f,
501586
std::vector<GVector::vector2d<double>> &p_i,
502587
int cal_type) const {
@@ -517,12 +602,12 @@ double CameraParameters::calibrateExtrinsicModel(
517602

518603
if (calib_field_points.size() < 4) {
519604
std::cerr << "Not enough calibration points: " << calib_field_points.size() << std::endl;
520-
return -1;
605+
return;
521606
}
522607

523608
std::vector<std::vector<cv::Point3f>> object_points(1);
524609
std::vector<std::vector<cv::Point2f>> image_points(1);
525-
cv::Size imageSize(2448, 2048);
610+
cv::Size imageSize(0, 0); // should not be required
526611
std::vector<cv::Mat> rvecs;
527612
std::vector<cv::Mat> tvecs;
528613

@@ -581,17 +666,6 @@ double CameraParameters::calibrateExtrinsicModel(
581666
// Update parameters
582667
intrinsic_parameters->updateConfigValues();
583668
extrinsic_parameters->updateConfigValues();
584-
585-
// validate
586-
std::vector<cv::Point2d> imagePoints_out;
587-
cv::projectPoints(calib_field_points, extrinsic_parameters->rvec, extrinsic_parameters->tvec, intrinsic_parameters->camera_mat, intrinsic_parameters->dist_coeffs, imagePoints_out);
588-
double sum = 0;
589-
for(uint i = 0; i < imagePoints_out.size(); i++) {
590-
auto diff = calib_image_points[i] - imagePoints_out[i];
591-
sum += cv::norm(diff) * cv::norm(diff);
592-
}
593-
double rmse = sqrt(sum / (double) calib_field_points.size());
594-
return rmse;
595669
}
596670

597671
void CameraParameters::detectCalibrationCorners() {
@@ -615,10 +689,9 @@ void CameraParameters::detectCalibrationCorners() {
615689

616690
// collect all valid image points
617691
vector<cv::Point2d> points_img;
618-
for (auto imgPt : calibrationData.imgPts) {
619-
bool detected = imgPt.second;
620-
if (detected) {
621-
auto p_img = imgPt.first;
692+
for (auto point : calibrationData.points) {
693+
if (point.detected) {
694+
auto p_img = point.img_point;
622695
points_img.emplace_back(p_img.x, p_img.y);
623696
}
624697
}
@@ -689,7 +762,7 @@ void CameraParameters::detectCalibrationCorners() {
689762
}
690763
}
691764

692-
double CameraParameters::calibrate(
765+
void CameraParameters::calibrate(
693766
std::vector<GVector::vector3d<double> > &p_f,
694767
std::vector<GVector::vector2d<double> > &p_i, int cal_type) {
695768
assert(p_f.size() == p_i.size());
@@ -709,9 +782,9 @@ double CameraParameters::calibrate(
709782
int count_alpha(0); //The number of well detected line segment points
710783
auto ls_it = calibrationSegments.begin();
711784
for (; ls_it != calibrationSegments.end(); ls_it++) {
712-
auto pts_it = (*ls_it).imgPts.begin();
713-
for (; pts_it != (*ls_it).imgPts.end(); pts_it++) {
714-
if (pts_it->second) count_alpha ++;
785+
auto pts_it = (*ls_it).points.begin();
786+
for (; pts_it != (*ls_it).points.end(); pts_it++) {
787+
if (pts_it->detected) count_alpha ++;
715788
}
716789
}
717790

@@ -722,11 +795,11 @@ double CameraParameters::calibrate(
722795
count_alpha = 0;
723796
ls_it = calibrationSegments.begin();
724797
for (; ls_it != calibrationSegments.end(); ls_it++) {
725-
auto pts_it = (*ls_it).imgPts.begin();
798+
auto pts_it = (*ls_it).points.begin();
726799
auto alphas_it = (*ls_it).alphas.begin();
727-
for (; pts_it != (*ls_it).imgPts.end() &&
800+
for (; pts_it != (*ls_it).points.end() &&
728801
alphas_it != (*ls_it).alphas.end(); pts_it++, alphas_it++) {
729-
if (pts_it->second) {
802+
if (pts_it->detected) {
730803
p_alpha(count_alpha++) = (*alphas_it);
731804
}
732805
}
@@ -814,9 +887,9 @@ double CameraParameters::calibrate(
814887

815888
int i = 0;
816889
for (; ls_it != calibrationSegments.end(); ls_it++) {
817-
auto pts_it = (*ls_it).imgPts.begin();
818-
for (; pts_it != (*ls_it).imgPts.end(); pts_it++) {
819-
if (pts_it->second) {
890+
auto pts_it = (*ls_it).points.begin();
891+
for (; pts_it != (*ls_it).points.end(); pts_it++) {
892+
if (pts_it->detected) {
820893
GVector::vector2d<double> proj_p;
821894
GVector::vector3d<double >alpha_point;
822895
if (ls_it->straightLine) {
@@ -826,7 +899,7 @@ double CameraParameters::calibrate(
826899
alpha_point = ls_it->center + ls_it->radius*GVector::vector3d<double>(cos(theta),sin(theta),0.0);
827900
}
828901
field2image(alpha_point, proj_p, p);
829-
proj_p = proj_p - (*pts_it).first;
902+
proj_p = proj_p - (*pts_it).img_point;
830903

831904
J.setZero();
832905

@@ -837,9 +910,9 @@ double CameraParameters::calibrate(
837910
p_diff(j) = p_diff(j) + epsilon;
838911
GVector::vector2d<double> proj_p_diff;
839912
field2image(alpha_point, proj_p_diff, p_diff);
840-
J(0,j) = ((proj_p_diff.x - (*pts_it).first.x) - proj_p.x) /
913+
J(0,j) = ((proj_p_diff.x - (*pts_it).img_point.x) - proj_p.x) /
841914
epsilon;
842-
J(1,j) = ((proj_p_diff.y - (*pts_it).first.y) - proj_p.y) /
915+
J(1,j) = ((proj_p_diff.y - (*pts_it).img_point.y) - proj_p.y) /
843916
epsilon;
844917
}
845918

@@ -859,9 +932,9 @@ double CameraParameters::calibrate(
859932
GVector::vector2d<double> proj_p_diff;
860933
field2image(alpha_point, proj_p_diff);
861934
J(0,STATE_SPACE_DIMENSION + i) =
862-
((proj_p_diff.x - (*pts_it).first.x) - proj_p.x) / epsilon;
935+
((proj_p_diff.x - (*pts_it).img_point.x) - proj_p.x) / epsilon;
863936
J(1,STATE_SPACE_DIMENSION + i) =
864-
((proj_p_diff.y - (*pts_it).first.y) - proj_p.y) / epsilon;
937+
((proj_p_diff.y - (*pts_it).img_point.y) - proj_p.y) / epsilon;
865938

866939
alpha += J.transpose() * cov_ls_inv * J;
867940
beta += J.transpose() * cov_ls_inv *
@@ -980,7 +1053,7 @@ double CameraParameters::calibrate(
9801053
GVector::vector2d<double> proj_p;
9811054
field2image(*it_p_f, proj_p);
9821055
GVector::vector3d<double> some_point;
983-
image2field(some_point,proj_p, 150);
1056+
image2field(some_point,proj_p, 0);
9841057
std::cerr << "Point in world: ("<< it_p_f->x << "," << it_p_f->y << ","
9851058
<< it_p_f->z << ")" << std::endl;
9861059
std::cerr << "Point should be at (" << it_p_i->x << "," << it_p_i->y
@@ -991,7 +1064,7 @@ double CameraParameters::calibrate(
9911064
double diff_y = proj_p.y - it_p_i->y;
9921065
corner_x += diff_x * diff_x;
9931066
corner_y += diff_y * diff_y;
994-
corner_sum += sqrt(diff_x * diff_x + diff_y * diff_y);
1067+
corner_sum += diff_x * diff_x + diff_y * diff_y;
9951068
}
9961069

9971070
std::cerr << "RESIDUAL CORNER POINTS: "
@@ -1009,9 +1082,9 @@ double CameraParameters::calibrate(
10091082

10101083
int i = 0;
10111084
for (; ls_it != calibrationSegments.end(); ls_it++) {
1012-
auto pts_it = (*ls_it).imgPts.begin();
1013-
for (; pts_it != (*ls_it).imgPts.end(); pts_it++) {
1014-
if (pts_it->second) {
1085+
auto pts_it = (*ls_it).points.begin();
1086+
for (; pts_it != (*ls_it).points.end(); pts_it++) {
1087+
if (pts_it->detected) {
10151088
GVector::vector2d<double> proj_p;
10161089
double pts_alpha = p_alpha(i);
10171090
GVector::vector3d<double >alpha_point;
@@ -1027,8 +1100,8 @@ double CameraParameters::calibrate(
10271100

10281101
field2image(alpha_point, proj_p, p);
10291102

1030-
line_x += (proj_p.x - pts_it->first.x) * (proj_p.x - pts_it->first.x);
1031-
line_y += (proj_p.y - pts_it->first.y) * (proj_p.y - pts_it->first.y);
1103+
line_x += (proj_p.x - pts_it->img_point.x) * (proj_p.x - pts_it->img_point.x);
1104+
line_y += (proj_p.y - pts_it->img_point.y) * (proj_p.y - pts_it->img_point.y);
10321105

10331106
i++;
10341107
}
@@ -1040,7 +1113,6 @@ double CameraParameters::calibrate(
10401113
<< sqrt(line_y/(double)i) << std::endl;
10411114
}
10421115
}
1043-
return sqrt(corner_sum/4);
10441116
#else
10451117
return -1;
10461118
#endif

0 commit comments

Comments
 (0)