29 #include "ui_calibrationDialog.h" 31 #include <opencv2/core/core.hpp> 32 #include <opencv2/imgproc/imgproc.hpp> 33 #include <opencv2/imgproc/imgproc_c.h> 34 #include <opencv2/calib3d/calib3d.hpp> 35 #if CV_MAJOR_VERSION >= 3 36 #include <opencv2/calib3d/calib3d_c.h> 38 #include <opencv2/highgui/highgui.hpp> 39 #if CV_MAJOR_VERSION > 2 or (CV_MAJOR_VERSION == 2 and (CV_MINOR_VERSION >4 or (CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >=10))) 43 #include <QFileDialog> 44 #include <QMessageBox> 45 #include <QCloseEvent> 60 rightSuffix_(
"right"),
61 savingDirectory_(savingDirectory),
62 processingData_(
false),
63 savedCalibration_(
false)
78 qRegisterMetaType<cv::Mat>(
"cv::Mat");
80 ui_ =
new Ui_calibrationDialog();
83 connect(ui_->pushButton_calibrate, SIGNAL(clicked()),
this, SLOT(
calibrate()));
84 connect(ui_->pushButton_restart, SIGNAL(clicked()),
this, SLOT(
restart()));
85 connect(ui_->pushButton_save, SIGNAL(clicked()),
this, SLOT(
save()));
86 connect(ui_->checkBox_switchImages, SIGNAL(stateChanged(
int)),
this, SLOT(
restart()));
87 connect(ui_->checkBox_unlock, SIGNAL(stateChanged(
int)), SLOT(
unlock()));
89 connect(ui_->spinBox_boardWidth, SIGNAL(valueChanged(
int)),
this, SLOT(
setBoardWidth(
int)));
90 connect(ui_->spinBox_boardHeight, SIGNAL(valueChanged(
int)),
this, SLOT(
setBoardHeight(
int)));
91 connect(ui_->doubleSpinBox_squareSize, SIGNAL(valueChanged(
double)),
this, SLOT(
setSquareSize(
double)));
92 connect(ui_->spinBox_maxScale, SIGNAL(valueChanged(
int)),
this, SLOT(
setMaxScale(
int)));
94 connect(ui_->buttonBox, SIGNAL(rejected()),
this, SLOT(close()));
96 ui_->image_view->setFocus();
98 ui_->progressBar_count->setMaximum(
COUNT_MIN);
99 ui_->progressBar_count->setFormat(
"%v");
100 ui_->progressBar_count_2->setMaximum(
COUNT_MIN);
101 ui_->progressBar_count_2->setFormat(
"%v");
103 ui_->radioButton_raw->setChecked(
true);
105 ui_->checkBox_switchImages->setChecked(switchImages);
107 ui_->checkBox_fisheye->setChecked(
false);
108 ui_->checkBox_fisheye->setEnabled(
false);
123 settings.beginGroup(group);
125 settings.setValue(
"board_width",
ui_->spinBox_boardWidth->value());
126 settings.setValue(
"board_height",
ui_->spinBox_boardHeight->value());
127 settings.setValue(
"board_square_size",
ui_->doubleSpinBox_squareSize->value());
128 settings.setValue(
"max_scale",
ui_->spinBox_maxScale->value());
129 settings.setValue(
"geometry", this->saveGeometry());
140 settings.beginGroup(group);
142 this->
setBoardWidth(settings.value(
"board_width",
ui_->spinBox_boardWidth->value()).toInt());
143 this->
setBoardHeight(settings.value(
"board_height",
ui_->spinBox_boardHeight->value()).toInt());
144 this->
setSquareSize(settings.value(
"board_square_size",
ui_->doubleSpinBox_squareSize->value()).toDouble());
145 this->
setMaxScale(settings.value(
"max_scale",
ui_->spinBox_maxScale->value()).toDouble());
146 QByteArray bytes = settings.value(
"geometry", QByteArray()).toByteArray();
149 this->restoreGeometry(bytes);
171 ui_->groupBox_progress->setVisible(visible);
176 ui_->checkBox_switchImages->setChecked(switched);
181 ui_->checkBox_fisheye->setChecked(enabled);
190 ui_->groupBox_progress->setVisible(
true);
196 ui_->progressBar_count_2->setVisible(
stereo_);
205 ui_->label_baseline_name->setVisible(
stereo_);
210 ui_->radioButton_stereoRectified->setVisible(
stereo_);
211 ui_->checkBox_switchImages->setVisible(
stereo_);
216 if(width !=
ui_->spinBox_boardWidth->value())
218 ui_->spinBox_boardWidth->setValue(width);
225 if(height !=
ui_->spinBox_boardHeight->value())
227 ui_->spinBox_boardHeight->setValue(height);
234 if(size !=
ui_->doubleSpinBox_squareSize->value())
236 ui_->doubleSpinBox_squareSize->setValue(size);
243 if(scale !=
ui_->spinBox_maxScale->value())
245 ui_->spinBox_maxScale->setValue(scale);
256 QMessageBox::StandardButton b = QMessageBox::question(
this, tr(
"Save calibration?"),
257 tr(
"The camera is calibrated but you didn't " 258 "save the calibration, do you want to save it?"),
259 QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::Cancel, QMessageBox::Yes);
261 if(b == QMessageBox::Yes)
268 else if(b == QMessageBox::Ignore)
277 if(event->isAccepted())
293 QMetaObject::invokeMethod(
this,
"processImages",
296 Q_ARG(QString, QString(e->
cameraName().c_str())));
305 UDEBUG(
"Processing images");
308 if(!cameraName.isEmpty())
318 std::vector<cv::Mat> inputRawImages(2);
319 if(
ui_->checkBox_switchImages->isChecked())
321 inputRawImages[0] = imageRight;
322 inputRawImages[1] = imageLeft;
326 inputRawImages[0] = imageLeft;
327 inputRawImages[1] = imageRight;
330 std::vector<cv::Mat> images(2);
331 images[0] = inputRawImages[0];
332 images[1] = inputRawImages[1];
336 bool boardFound[2] = {
false};
337 bool boardAccepted[2] = {
false};
338 bool readyToCalibrate[2] = {
false};
340 std::vector<std::vector<cv::Point2f> > pointBuf(2);
342 bool depthDetected =
false;
343 for(
int id=0;
id<(
stereo_?2:1); ++id)
346 if(!images[
id].empty())
348 if(images[
id].type() == CV_16UC1)
351 cv::minMaxLoc(images[
id], &min, &max);
352 UDEBUG(
"Camera IR %d: min=%f max=%f",
id, min, max);
362 depthDetected =
true;
365 viewGray = cv::Mat(images[
id].rows, images[
id].cols, CV_8UC1);
366 for(
int i=0; i<images[id].rows; ++i)
368 for(
int j=0; j<images[id].cols; ++j)
370 viewGray.at<
unsigned char>(i, j) = (
unsigned char)
std::min(
float(
std::max(images[
id].at<unsigned short>(i,j) -
minIrs_[
id], 0)) * factor, 255.0
f);
373 cvtColor(viewGray, images[
id], cv::COLOR_GRAY2BGR);
375 else if(images[
id].channels() == 3)
377 cvtColor(images[
id], viewGray, cv::COLOR_BGR2GRAY);
381 viewGray = images[id];
382 cvtColor(viewGray, images[
id], cv::COLOR_GRAY2BGR);
387 UERROR(
"Image %d is empty!! Should not!",
id);
394 if(!
ui_->pushButton_save->isEnabled())
396 cv::Size boardSize(
ui_->spinBox_boardWidth->value(),
ui_->spinBox_boardHeight->value());
397 if(!viewGray.empty())
399 int flags = CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE;
401 if(!viewGray.empty())
403 int maxScale =
ui_->spinBox_maxScale->value();
410 cv::resize(viewGray, timg, cv::Size(),
scale,
scale, CV_INTER_CUBIC);
411 boardFound[id] = cv::findChessboardCorners(timg, boardSize, pointBuf[
id], flags);
416 cv::Mat cornersMat(pointBuf[
id]);
417 cornersMat *= 1./
scale;
428 float minSquareDistance = -1.0f;
429 for(
unsigned int i=0; i<pointBuf[id].size()-1; ++i)
431 float d = cv::norm(pointBuf[
id][i] - pointBuf[
id][i+1]);
432 if(minSquareDistance == -1.0
f || minSquareDistance > d)
434 minSquareDistance = d;
437 float radius = minSquareDistance/2.0f +0.5f;
438 cv::cornerSubPix( viewGray, pointBuf[
id], cv::Size(radius, radius), cv::Size(-1,-1),
439 cv::TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1 ));
442 cv::drawChessboardCorners(images[
id], boardSize, cv::Mat(pointBuf[
id]), boardFound[
id]);
444 std::vector<float> params(4,0);
445 getParams(pointBuf[
id], boardSize,
imageSize_[
id], params[0], params[1], params[2], params[3]);
447 bool addSample =
true;
460 boardAccepted[id] =
true;
465 UINFO(
"[%d] Added board, total=%d. (x=%f, y=%f, size=%f, skew=%f)",
id, (
int)
imagePoints_[
id].size(), params[0], params[1], params[2], params[3]);
469 std::vector<float> xRange(2,
imageParams_[
id][0].at(0));
470 std::vector<float> yRange(2,
imageParams_[
id][0].at(1));
471 std::vector<float> sizeRange(2,
imageParams_[
id][0].at(2));
472 std::vector<float> skewRange(2,
imageParams_[
id][0].at(3));
491 float xGood = xRange[1] - xRange[0];
492 float yGood = yRange[1] - yRange[0];
493 float sizeGood = sizeRange[1] - sizeRange[0];
494 float skewGood = skewRange[1] - skewRange[0];
498 ui_->progressBar_x->setValue(xGood*100);
499 ui_->progressBar_y->setValue(yGood*100);
500 ui_->progressBar_size->setValue(sizeGood*100);
501 ui_->progressBar_skew->setValue(skewGood*100);
510 ui_->progressBar_x_2->setValue(xGood*100);
511 ui_->progressBar_y_2->setValue(yGood*100);
512 ui_->progressBar_size_2->setValue(sizeGood*100);
513 ui_->progressBar_skew_2->setValue(skewGood*100);
522 if(
imagePoints_[
id].size() >=
COUNT_MIN && xGood > 0.5 && yGood > 0.5 && sizeGood > 0.4 && skewGood > 0.5)
524 readyToCalibrate[id] =
true;
528 if(inputRawImages[
id].type() == CV_16UC1)
533 for(
size_t i = 0; i < pointBuf[id].size(); ++i)
535 const cv::Point2f &p = pointBuf[id][i];
538 roi.width =
std::min(roi.width, inputRawImages[
id].cols - roi.x);
539 roi.height =
std::min(roi.height, inputRawImages[
id].rows - roi.y);
543 cv::minMaxLoc(inputRawImages[
id](roi), &min, &max);
557 ui_->label_baseline->setVisible(!depthDetected);
558 ui_->label_baseline_name->setVisible(!depthDetected);
560 if(
stereo_ && ((boardAccepted[0] && boardFound[1]) || (boardAccepted[1] && boardFound[0])))
567 if(!
stereo_ && readyToCalibrate[0])
576 if(
ui_->radioButton_rectified->isChecked())
578 if(
models_[0].isValidForRectification())
580 images[0] =
models_[0].rectifyImage(images[0]);
582 if(
models_[1].isValidForRectification())
584 images[1] =
models_[1].rectifyImage(images[1]);
587 else if(
ui_->radioButton_stereoRectified->isChecked() &&
596 if(
ui_->checkBox_showHorizontalLines->isChecked())
598 for(
int id=0;
id<(
stereo_?2:1); ++id)
603 cv::line(images[
id], cv::Point(0, i), cv::Point(
imageSize_[
id].width, i), CV_RGB(0,255,0));
608 ui_->label_left->setText(tr(
"%1x%2").arg(images[0].cols).arg(images[0].rows));
611 ui_->image_view->setImage(
uCvMat2QImage(images[0]).mirrored(
ui_->checkBox_mirror->isChecked(),
false));
614 ui_->label_right->setText(tr(
"%1x%2").arg(images[1].cols).arg(images[1].rows));
615 ui_->image_view_2->setImage(
uCvMat2QImage(images[1]).mirrored(
ui_->checkBox_mirror->isChecked(),
false));
638 ui_->pushButton_calibrate->setEnabled(
ui_->checkBox_unlock->isChecked());
639 ui_->checkBox_fisheye->setEnabled(
ui_->checkBox_unlock->isChecked());
640 ui_->pushButton_save->setEnabled(
false);
641 ui_->radioButton_raw->setChecked(
true);
642 ui_->radioButton_rectified->setEnabled(
false);
643 ui_->radioButton_stereoRectified->setEnabled(
false);
645 ui_->progressBar_count->reset();
647 ui_->progressBar_x->reset();
648 ui_->progressBar_y->reset();
649 ui_->progressBar_size->reset();
650 ui_->progressBar_skew->reset();
652 ui_->progressBar_count_2->reset();
654 ui_->progressBar_x_2->reset();
655 ui_->progressBar_y_2->reset();
656 ui_->progressBar_size_2->reset();
657 ui_->progressBar_skew_2->reset();
659 ui_->label_serial->clear();
660 ui_->label_fx->setNum(0);
661 ui_->label_fy->setNum(0);
662 ui_->label_cx->setNum(0);
663 ui_->label_cy->setNum(0);
664 ui_->label_baseline->setNum(0);
665 ui_->label_error->setNum(0);
666 ui_->lineEdit_K->clear();
667 ui_->lineEdit_D->clear();
668 ui_->lineEdit_R->clear();
669 ui_->lineEdit_P->clear();
670 ui_->label_fx_2->setNum(0);
671 ui_->label_fy_2->setNum(0);
672 ui_->label_cx_2->setNum(0);
673 ui_->label_cy_2->setNum(0);
674 ui_->lineEdit_K_2->clear();
675 ui_->lineEdit_D_2->clear();
676 ui_->lineEdit_R_2->clear();
677 ui_->lineEdit_P_2->clear();
682 ui_->pushButton_calibrate->setEnabled(
true);
683 ui_->checkBox_fisheye->setEnabled(
true);
691 QMessageBox mb(QMessageBox::Information,
692 tr(
"Calibrating..."),
693 tr(
"Operation in progress..."));
695 QApplication::processEvents();
697 QApplication::processEvents();
699 std::vector<std::vector<cv::Point3f> > objectPoints(1);
700 cv::Size boardSize(
ui_->spinBox_boardWidth->value(),
ui_->spinBox_boardHeight->value());
701 float squareSize =
ui_->doubleSpinBox_squareSize->value();
703 for(
int i = 0; i < boardSize.height; ++i )
704 for(
int j = 0; j < boardSize.width; ++j )
705 objectPoints[0].push_back(cv::Point3f(
float( j*squareSize ),
float( i*squareSize ), 0));
707 for(
int id=0;
id<(
stereo_?2:1); ++id)
711 objectPoints.resize(
imagePoints_[
id].size(), objectPoints[0]);
714 std::vector<cv::Mat> rvecs, tvecs;
715 std::vector<float> reprojErrs;
717 K = cv::Mat::eye(3,3,CV_64FC1);
721 #if CV_MAJOR_VERSION > 2 or (CV_MAJOR_VERSION == 2 and (CV_MINOR_VERSION >4 or (CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >=10))) 722 bool fishEye =
ui_->checkBox_fisheye->isChecked();
735 cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC |
736 cv::fisheye::CALIB_CHECK_COND |
737 cv::fisheye::CALIB_FIX_SKEW);
739 catch(
const cv::Exception &
e)
741 UERROR(
"Error: %s (try restarting the calibration)", e.what());
742 QMessageBox::warning(
this, tr(
"Calibration failed!"), tr(
"Error: %1 (try restarting the calibration)").arg(e.what()));
750 rms = cv::calibrateCamera(objectPoints,
759 UINFO(
"Re-projection error reported by calibrateCamera: %f", rms);
762 std::vector<cv::Point2f> imagePoints2;
763 int i, totalPoints = 0;
764 double totalErr = 0, err;
765 reprojErrs.resize(objectPoints.size());
767 for( i = 0; i < (int)objectPoints.size(); ++i )
769 #if CV_MAJOR_VERSION > 2 or (CV_MAJOR_VERSION == 2 and (CV_MINOR_VERSION >4 or (CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >=10))) 772 cv::fisheye::projectPoints( cv::Mat(objectPoints[i]), imagePoints2, rvecs[i], tvecs[i], K, D);
777 cv::projectPoints( cv::Mat(objectPoints[i]), rvecs[i], tvecs[i], K, D, imagePoints2);
779 err = cv::norm(cv::Mat(
imagePoints_[
id][i]), cv::Mat(imagePoints2), CV_L2);
781 int n = (int)objectPoints[i].size();
782 reprojErrs[i] = (float)
std::sqrt(err*err/n);
787 double totalAvgErr =
std::sqrt(totalErr/totalPoints);
789 UINFO(
"avg re projection error = %f", totalAvgErr);
791 cv::Mat P(3,4,CV_64FC1);
792 P.at<
double>(2,3) = 1;
793 K.copyTo(P.colRange(0,3).rowRange(0,3));
795 #if CV_MAJOR_VERSION > 2 or (CV_MAJOR_VERSION == 2 and (CV_MINOR_VERSION >4 or (CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >=10))) 799 cv::Mat newD = cv::Mat::zeros(1,6,CV_64FC1);
800 newD.at<
double>(0,0) = D.at<
double>(0,0);
801 newD.at<
double>(0,1) = D.at<
double>(0,1);
802 newD.at<
double>(0,4) = D.at<
double>(0,2);
803 newD.at<
double>(0,5) = D.at<
double>(0,3);
808 std::cout <<
"K = " << K << std::endl;
809 std::cout <<
"D = " << D << std::endl;
810 std::cout <<
"width = " <<
imageSize_[id].width << std::endl;
811 std::cout <<
"height = " <<
imageSize_[id].height << std::endl;
821 ui_->label_error->setNum(totalAvgErr);
823 std::stringstream strK, strD, strR, strP;
828 ui_->lineEdit_K->setText(strK.str().c_str());
829 ui_->lineEdit_D->setText(strD.str().c_str());
830 ui_->lineEdit_R->setText(strR.str().c_str());
831 ui_->lineEdit_P->setText(strP.str().c_str());
839 ui_->label_error_2->setNum(totalAvgErr);
841 std::stringstream strK, strD, strR, strP;
846 ui_->lineEdit_K_2->setText(strK.str().c_str());
847 ui_->lineEdit_D_2->setText(strD.str().c_str());
848 ui_->lineEdit_R_2->setText(strR.str().c_str());
849 ui_->lineEdit_P_2->setText(strP.str().c_str());
856 std::stringstream strR1, strP1, strR2, strP2;
861 ui_->lineEdit_R->setText(strR1.str().c_str());
862 ui_->lineEdit_P->setText(strP1.str().c_str());
863 ui_->lineEdit_R_2->setText(strR2.str().c_str());
864 ui_->lineEdit_P_2->setText(strP2.str().c_str());
872 if(
models_[0].isValidForRectification())
874 models_[0].initRectificationMap();
876 if(
models_[1].isValidForRectification())
878 models_[1].initRectificationMap();
880 if(
models_[0].isValidForRectification() ||
models_[1].isValidForRectification())
882 ui_->radioButton_rectified->setEnabled(
true);
887 ui_->radioButton_stereoRectified->setEnabled(
true);
888 ui_->radioButton_stereoRectified->setChecked(
true);
889 ui_->pushButton_save->setEnabled(
true);
893 ui_->radioButton_rectified->setChecked(
ui_->radioButton_rectified->isEnabled());
896 else if(
models_[0].isValidForRectification())
898 models_[0].initRectificationMap();
899 ui_->radioButton_rectified->setEnabled(
true);
900 ui_->radioButton_rectified->setChecked(
true);
901 ui_->pushButton_save->setEnabled(
true);
904 UINFO(
"End calibration");
913 UERROR(
"No stereo correspondences!");
918 if (left.
K_raw().empty() || left.
D_raw().empty())
920 UERROR(
"Empty intrinsic parameters (K, D) for the %s camera! Aborting stereo calibration...",
leftSuffix_.toStdString().c_str());
923 if (right.
K_raw().empty() || right.
D_raw().empty())
925 UERROR(
"Empty intrinsic parameters (K, D) for the %s camera! Aborting stereo calibration...",
rightSuffix_.toStdString().c_str());
931 UERROR(
"left model (%dx%d) has not the same size as the processed images (%dx%d)",
938 UERROR(
"right model (%dx%d) has not the same size as the processed images (%dx%d)",
947 cv::Size boardSize(
ui_->spinBox_boardWidth->value(),
ui_->spinBox_boardHeight->value());
948 float squareSize =
ui_->doubleSpinBox_squareSize->value();
951 #if CV_MAJOR_VERSION > 2 or (CV_MAJOR_VERSION == 2 and (CV_MINOR_VERSION >4 or (CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >=10))) 952 bool fishEye = left.
D_raw().cols == 6;
957 std::vector<std::vector<cv::Point3d> > objectPoints(1);
958 for (
int i = 0; i < boardSize.height; ++i)
959 for (
int j = 0; j < boardSize.width; ++j)
960 objectPoints[0].push_back(cv::Point3d(
double(j*squareSize),
double(i*squareSize), 0));
964 cv::Vec4d D_left(left.
D_raw().at<
double>(0,0), left.
D_raw().at<
double>(0,1), left.
D_raw().at<
double>(0,4), left.
D_raw().at<
double>(0,5));
965 cv::Vec4d D_right(right.
D_raw().at<
double>(0,0), right.
D_raw().at<
double>(0,1), right.
D_raw().at<
double>(0,4), right.
D_raw().at<
double>(0,5));
986 rms = cv::fisheye::stereoCalibrate(
992 cv::fisheye::CALIB_FIX_INTRINSIC,
993 cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS, 100, 1
e-5));
994 UINFO(
"stereo calibration... done with RMS error=%f", rms);
996 catch(
const cv::Exception &
e)
998 UERROR(
"Error: %s (try restarting the calibration)", e.what());
1002 std::cout <<
"R = " << R << std::endl;
1003 std::cout <<
"T = " << Tvec << std::endl;
1007 UINFO(
"Compute stereo rectification");
1009 cv::Mat R1, R2, P1, P2, Q;
1011 left.
K_raw(), D_left,
1012 right.
K_raw(), D_right,
1013 imageSize, R, Tvec, R1, R2, P1, P2, Q,
1014 cv::CALIB_ZERO_DISPARITY, 0, imageSize);
1024 std::cout <<
"R1 = " << R1 << std::endl;
1025 std::cout <<
"R2 = " << R2 << std::endl;
1026 std::cout <<
"P1 = " << P1 << std::endl;
1027 std::cout <<
"P2 = " << P2 << std::endl;
1030 if(P1.at<
double>(0,0) < 0)
1032 P1.at<
double>(0,0) *= -1;
1033 P1.at<
double>(1,1) *= -1;
1035 if(P2.at<
double>(0,0) < 0)
1037 P2.at<
double>(0,0) *= -1;
1038 P2.at<
double>(1,1) *= -1;
1040 if(P2.at<
double>(0,3) > 0)
1042 P2.at<
double>(0,3) *= -1;
1044 P2.at<
double>(0,3) = P2.at<
double>(0,3) * left.
K_raw().at<
double>(0,0) / P2.at<
double>(0,0);
1045 P1.at<
double>(0,0) = P1.at<
double>(1,1) = left.
K_raw().at<
double>(0,0);
1046 P2.at<
double>(0,0) = P2.at<
double>(1,1) = left.
K_raw().at<
double>(0,0);
1048 std::cout <<
"P1n = " << P1 << std::endl;
1049 std::cout <<
"P2n = " << P2 << std::endl;
1052 cv::Mat T(3,1,CV_64FC1);
1053 T.at <
double>(0,0) = Tvec[0];
1054 T.at <
double>(1,0) = Tvec[1];
1055 T.at <
double>(2,0) = Tvec[2];
1077 std::vector<std::vector<cv::Point3f> > objectPoints(1);
1078 for (
int i = 0; i < boardSize.height; ++i)
1079 for (
int j = 0; j < boardSize.width; ++j)
1080 objectPoints[0].push_back(cv::Point3f(
float(j*squareSize),
float(i*squareSize), 0));
1083 #if CV_MAJOR_VERSION < 3 1084 rms = cv::stereoCalibrate(
1090 imageSize, R, T, E, F,
1091 cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS, 100, 1
e-5),
1092 cv::CALIB_FIX_INTRINSIC);
1094 rms = cv::stereoCalibrate(
1100 imageSize, R, T, E, F,
1101 cv::CALIB_FIX_INTRINSIC,
1102 cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS, 100, 1
e-5));
1104 UINFO(
"stereo calibration... done with RMS error=%f", rms);
1106 std::cout <<
"R = " << R << std::endl;
1107 std::cout <<
"T = " << T << std::endl;
1108 std::cout <<
"E = " << E << std::endl;
1109 std::cout <<
"F = " << F << std::endl;
1113 UINFO(
"Compute stereo rectification");
1115 cv::Mat R1, R2, P1, P2, Q;
1116 cv::stereoRectify(left.
K_raw(), left.
D_raw(),
1118 imageSize, R, T, R1, R2, P1, P2, Q,
1119 cv::CALIB_ZERO_DISPARITY, 0, imageSize);
1121 std::cout <<
"R1 = " << R1 << std::endl;
1122 std::cout <<
"P1 = " << P1 << std::endl;
1123 std::cout <<
"R2 = " << R2 << std::endl;
1124 std::cout <<
"P2 = " << P2 << std::endl;
1128 std::vector<cv::Vec3f> lines[2];
1129 UINFO(
"Computing avg re-projection error...");
1136 cv::undistortPoints(imgpt0, imgpt0, left.
K_raw(), left.
D_raw(), R1, P1);
1137 cv::undistortPoints(imgpt1, imgpt1, right.
K_raw(), right.
D_raw(), R2, P2);
1138 computeCorrespondEpilines(imgpt0, 1, F, lines[0]);
1139 computeCorrespondEpilines(imgpt1, 2, F, lines[1]);
1141 for(
int j = 0; j < npt; j++ )
1151 double totalAvgErr = err/(double)npoints;
1152 UINFO(
"stereo avg re projection error = %f", totalAvgErr);
1181 QString cameraName =
models_[0].name().c_str();
1182 QString filePath = QFileDialog::getSaveFileName(
this, tr(
"Export"),
savingDirectory_+
"/"+cameraName+
".yaml",
"*.yaml");
1184 if(!filePath.isEmpty())
1186 QString name = QFileInfo(filePath).baseName();
1187 QString dir = QFileInfo(filePath).absoluteDir().absolutePath();
1188 models_[0].setName(name.toStdString());
1191 QMessageBox::information(
this, tr(
"Export"), tr(
"Calibration file saved to \"%1\".").arg(filePath));
1192 UINFO(
"Saved \"%s\"!", filePath.toStdString().c_str());
1198 UERROR(
"Error saving \"%s\"", filePath.toStdString().c_str());
1207 QString filePath = QFileDialog::getSaveFileName(
this, tr(
"Export"),
savingDirectory_ +
"/" + cameraName,
"*.yaml");
1208 QString name = QFileInfo(filePath).baseName();
1209 QString dir = QFileInfo(filePath).absoluteDir().absolutePath();
1212 bool switched =
ui_->checkBox_switchImages->isChecked();
1214 std::string base = (dir+QDir::separator()+name).toStdString();
1217 std::string posePath = base+
"_pose.yaml";
1220 QMessageBox::information(
this, tr(
"Export"), tr(
"Calibration files saved:\n \"%1\"\n \"%2\"\n \"%3\".").
1221 arg(leftPath.c_str()).arg(rightPath.c_str()).arg(posePath.c_str()));
1222 UINFO(
"Saved \"%s\" and \"%s\"!", leftPath.c_str(), rightPath.c_str());
1228 UERROR(
"Error saving \"%s\" and \"%s\"", leftPath.c_str(), rightPath.c_str());
1242 cv::Point2f up_left = corners[0];
1243 cv::Point2f up_right = corners[boardSize.width-1];
1244 cv::Point2f down_right = corners[corners.size()-1];
1245 cv::Point2f down_left = corners[corners.size()-boardSize.width];
1246 cv::Point2f a = up_right - up_left;
1247 cv::Point2f b = down_right - up_right;
1248 cv::Point2f c = down_left - down_right;
1249 cv::Point2f p = b + c;
1250 cv::Point2f q = a + b;
1251 return std::fabs(p.x*q.y - p.y*q.x) / 2.0f;
1260 cv::Point2f up_left = corners[0];
1261 cv::Point2f up_right = corners[boardSize.width-1];
1262 cv::Point2f down_right = corners[corners.size()-1];
1266 cv::Point2f ab = up_left - up_right;
1267 cv::Point2f cb = down_right - up_right;
1268 float angle =
std::acos(ab.dot(cb) / (cv::norm(ab) * cv::norm(cb)));
1270 float r = 2.0f * std::fabs((CV_PI / 2.0
f) - angle);
1271 return r > 1.0f?1.0f:r;
1279 float & x,
float & y,
float & size,
float & skew)
1281 float area =
getArea(corners, boardSize);
1282 size =
std::sqrt(area / (imageSize.width * imageSize.height));
1283 skew =
getSkew(corners, boardSize);
1286 for(
unsigned int i=0; i<corners.size(); ++i)
1288 meanX += corners[i].x;
1289 meanY += corners[i].y;
1291 meanX /= corners.size();
1292 meanY /= corners.size();
1293 x = meanX / imageSize.width;
1294 y = meanY / imageSize.height;
void processImages(const cv::Mat &imageLeft, const cv::Mat &imageRight, const QString &cameraName)
const cv::Size & imageSize() const
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
void setBoardWidth(int width)
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
std::vector< std::vector< std::vector< cv::Point2f > > > stereoImagePoints_
void loadSettings(QSettings &settings, const QString &group="")
const std::string & cameraName() const
GLM_FUNC_DECL genType e()
std::vector< unsigned short > minIrs_
void setSquareSize(double size)
GLM_FUNC_DECL T angle(detail::tquat< T, P > const &x)
std::vector< unsigned short > maxIrs_
void setSwitchedImages(bool switched)
virtual ~CalibrationDialog()
const std::string & getRightSuffix() const
const cv::Mat & imageRaw() const
GLM_FUNC_DECL genType step(genType const &edge, genType const &x)
void initRectificationMap()
void setBoardHeight(int height)
rtabmap::StereoCameraModel stereoModel_
#define UASSERT(condition)
virtual void closeEvent(QCloseEvent *event)
const CameraModel & left() const
std::vector< std::vector< std::vector< cv::Point2f > > > imagePoints_
void getParams(const std::vector< cv::Point2f > &corners, const cv::Size &boardSize, const cv::Size &imageSize, float &x, float &y, float &size, float &skew)
QImage uCvMat2QImage(const cv::Mat &image, bool isBgr=true, uCvQtDepthColorMap colorMap=uCvQtDepthWhiteToBlack)
CvImagePtr cvtColor(const CvImageConstPtr &source, const std::string &encoding)
virtual std::string getClassName() const =0
void stereoRectifyFisheye(cv::InputArray _cameraMatrix1, cv::InputArray _distCoeffs1, cv::InputArray _cameraMatrix2, cv::InputArray _distCoeffs2, cv::Size imageSize, cv::InputArray _Rmat, cv::InputArray _Tmat, cv::OutputArray _Rmat1, cv::OutputArray _Rmat2, cv::OutputArray _Pmat1, cv::OutputArray _Pmat2, cv::OutputArray _Qmat, int flags, double alpha, cv::Size newImageSize)
bool isValidForRectification() const
std::vector< rtabmap::CameraModel > models_
bool save(const std::string &directory, bool ignoreStereoTransform=true) const
const cv::Mat & depthOrRightRaw() const
DiscreteDepthDistortionModel RTABMAP_EXP calibrate(const std::map< int, rtabmap::SensorData > &sequence, const std::map< int, rtabmap::Transform > &trajectory, const pcl::PointCloud< pcl::PointXYZ >::Ptr &map, double coneRadius=0.02, double coneStdevThresh=0.03)
cv::Mat rectifyImage(const cv::Mat &raw, int interpolation=cv::INTER_LINEAR) const
void uSleep(unsigned int ms)
CalibrationDialog(bool stereo=false, const QString &savingDirectory=".", bool switchImages=false, QWidget *parent=0)
void setStereoMode(bool stereo, const QString &leftSuffix="left", const QString &rightSuffix="right")
void setProgressVisibility(bool visible)
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
bool isValidForRectification() const
const CameraModel & right() const
void setMaxScale(int scale)
ULogger class and convenient macros.
GLM_FUNC_DECL genType acos(genType const &x)
void setName(const std::string &name, const std::string &leftSuffix="left", const std::string &rightSuffix="right")
std::vector< cv::Size > imageSize_
float getArea(const std::vector< cv::Point2f > &corners, const cv::Size &boardSize)
std::vector< std::vector< std::vector< float > > > imageParams_
const SensorData & data() const
Ui_calibrationDialog * ui_
virtual bool handleEvent(UEvent *event)
void unregisterFromEventsManager()
void saveSettings(QSettings &settings, const QString &group="") const
const std::string & getLeftSuffix() const
void setCameraName(const QString &name)
float getSkew(const std::vector< cv::Point2f > &corners, const cv::Size &boardSize)
void setFisheyeImages(bool enabled)
StereoCameraModel stereoCalibration(const CameraModel &left, const CameraModel &right, bool ignoreStereoRectification) const
const std::string & name() const