Calibration tool: added support for rational model (8 coeff)

This commit is contained in:
matlabbe
2024-05-31 10:28:14 -07:00
parent 99cb02fdff
commit 8310925c81
6 changed files with 588 additions and 360 deletions

View File

@@ -43,6 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QFileDialog>
#include <QMessageBox>
#include <QCloseEvent>
#include <QDateTime>
#include <rtabmap/core/SensorEvent.h>
#include <rtabmap/utilite/UCv2Qt.h>
@@ -60,10 +61,12 @@ CalibrationDialog::CalibrationDialog(bool stereo, const QString & savingDirector
rightSuffix_("right"),
savingDirectory_(savingDirectory),
processingData_(false),
savedCalibration_(false)
savedCalibration_(false),
currentId_(0)
{
imagePoints_.resize(2);
imageParams_.resize(2);
imageIds_.resize(2);
imageSize_.resize(2);
stereoImagePoints_.resize(2);
models_.resize(2);
@@ -89,6 +92,7 @@ CalibrationDialog::CalibrationDialog(bool stereo, const QString & savingDirector
connect(ui_->spinBox_boardWidth, SIGNAL(valueChanged(int)), this, SLOT(setBoardWidth(int)));
connect(ui_->spinBox_boardHeight, SIGNAL(valueChanged(int)), this, SLOT(setBoardHeight(int)));
connect(ui_->doubleSpinBox_squareSize, SIGNAL(valueChanged(double)), this, SLOT(setSquareSize(double)));
connect(ui_->checkBox_saveCalibrationData, SIGNAL(toggled(bool)), this, SLOT(setCalibrationDataSaved(bool)));
connect(ui_->doubleSpinBox_stereoBaseline, SIGNAL(valueChanged(double)), this, SLOT(setExpectedStereoBaseline(double)));
connect(ui_->spinBox_maxScale, SIGNAL(valueChanged(int)), this, SLOT(setMaxScale(int)));
@@ -105,9 +109,11 @@ CalibrationDialog::CalibrationDialog(bool stereo, const QString & savingDirector
ui_->checkBox_switchImages->setChecked(switchImages);
ui_->checkBox_fisheye->setChecked(false);
ui_->comboBox_calib_model->setCurrentIndex(1);
this->setStereoMode(stereo_);
timestamp_ = QDateTime::currentDateTime().toString("yyyyMMddhhmmss");
}
CalibrationDialog::~CalibrationDialog()
@@ -125,8 +131,10 @@ void CalibrationDialog::saveSettings(QSettings & settings, const QString & group
settings.setValue("board_width", ui_->spinBox_boardWidth->value());
settings.setValue("board_height", ui_->spinBox_boardHeight->value());
settings.setValue("board_square_size", ui_->doubleSpinBox_squareSize->value());
settings.setValue("calibration_data_saved", ui_->checkBox_saveCalibrationData->isChecked());
settings.setValue("max_scale", ui_->spinBox_maxScale->value());
settings.setValue("geometry", this->saveGeometry());
settings.setValue("calibration_model", ui_->comboBox_calib_model->currentIndex());
if(!group.isEmpty())
{
settings.endGroup();
@@ -142,7 +150,21 @@ void CalibrationDialog::loadSettings(QSettings & settings, const QString & group
this->setBoardWidth(settings.value("board_width", ui_->spinBox_boardWidth->value()).toInt());
this->setBoardHeight(settings.value("board_height", ui_->spinBox_boardHeight->value()).toInt());
this->setSquareSize(settings.value("board_square_size", ui_->doubleSpinBox_squareSize->value()).toDouble());
this->setCalibrationDataSaved(settings.value("calibration_data_saved", ui_->checkBox_saveCalibrationData->isChecked()).toBool());
this->setMaxScale(settings.value("max_scale", ui_->spinBox_maxScale->value()).toDouble());
int model = settings.value("calibration_model", ui_->comboBox_calib_model->currentIndex()).toInt();
if(model == 0)
{
this->setFisheyeModel();
}
else if(model ==2)
{
this->setRationalModel();
}
else
{
this->setPlumbobModel();
}
QByteArray bytes = settings.value("geometry", QByteArray()).toByteArray();
if(!bytes.isEmpty())
{
@@ -176,9 +198,19 @@ void CalibrationDialog::setSwitchedImages(bool switched)
ui_->checkBox_switchImages->setChecked(switched);
}
void CalibrationDialog::setFisheyeImages(bool enabled)
void CalibrationDialog::setFisheyeModel()
{
ui_->checkBox_fisheye->setChecked(enabled);
ui_->comboBox_calib_model->setCurrentIndex(0);
}
void CalibrationDialog::setPlumbobModel()
{
ui_->comboBox_calib_model->setCurrentIndex(1);
}
void CalibrationDialog::setRationalModel()
{
ui_->comboBox_calib_model->setCurrentIndex(2);
}
void CalibrationDialog::setStereoMode(bool stereo, const QString & leftSuffix, const QString & rightSuffix)
@@ -200,6 +232,8 @@ void CalibrationDialog::setStereoMode(bool stereo, const QString & leftSuffix, c
ui_->label_fy_2->setVisible(stereo_);
ui_->label_cx_2->setVisible(stereo_);
ui_->label_cy_2->setVisible(stereo_);
ui_->label_fovx_2->setVisible(stereo_);
ui_->label_fovy_2->setVisible(stereo_);
ui_->label_error_2->setVisible(stereo_);
ui_->label_baseline->setVisible(stereo_);
ui_->label_baseline_name->setVisible(stereo_);
@@ -253,6 +287,15 @@ void CalibrationDialog::setSquareSize(double size)
}
}
void CalibrationDialog::setCalibrationDataSaved(bool enabled)
{
if(enabled != ui_->checkBox_saveCalibrationData->isChecked())
{
ui_->checkBox_saveCalibrationData->setChecked(enabled);
this->restart();
}
}
void CalibrationDialog::setExpectedStereoBaseline(double length)
{
if(length != ui_->doubleSpinBox_stereoBaseline->value())
@@ -366,6 +409,7 @@ void CalibrationDialog::processImages(const cv::Mat & imageLeft, const cv::Mat &
std::vector<std::vector<cv::Point2f> > pointBuf(2);
bool depthDetected = false;
bool sampleAdded = false;
for(int id=0; id<(stereo_?2:1); ++id)
{
cv::Mat viewGray;
@@ -465,6 +509,7 @@ void CalibrationDialog::processImages(const cv::Mat & imageLeft, const cv::Mat &
cv::TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1 ));
// Draw the corners.
images[id] = images[id].clone();
cv::drawChessboardCorners(images[id], boardSize, cv::Mat(pointBuf[id]), boardFound[id]);
std::vector<float> params(4,0);
@@ -483,13 +528,18 @@ void CalibrationDialog::processImages(const cv::Mat & imageLeft, const cv::Mat &
}
if(addSample)
{
sampleAdded = true;
boardAccepted[id] = true;
imageIds_[id].push_back(currentId_);
imagePoints_[id].push_back(pointBuf[id]);
imageParams_[id].push_back(params);
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]);
}
else
{
//break;
}
// update statistics
std::vector<float> xRange(2, imageParams_[id][0].at(0));
@@ -548,7 +598,7 @@ void CalibrationDialog::processImages(const cv::Mat & imageLeft, const cv::Mat &
if(imagePoints_[id].size() >= COUNT_MIN &&
xGood > 0.5 &&
yGood > 0.5 &&
(sizeGood > 0.4 || (ui_->checkBox_fisheye->isChecked() && sizeGood > 0.25)) &&
(sizeGood > 0.4 || (ui_->comboBox_calib_model->currentIndex()==0 && sizeGood > 0.25)) &&
skewGood > 0.5)
{
readyToCalibrate[id] = true;
@@ -587,10 +637,32 @@ void CalibrationDialog::processImages(const cv::Mat & imageLeft, const cv::Mat &
ui_->label_baseline->setVisible(!depthDetected);
ui_->label_baseline_name->setVisible(!depthDetected);
if(ui_->checkBox_saveCalibrationData->isChecked() && (boardAccepted[0] || boardAccepted[1]))
{
for(int id=0; id<(stereo_?2:1); ++id)
{
QString rawImagesDir = savingDirectory_+"/"+cameraName_+"_"+timestamp_+(stereo_?"/"+(id==0?leftSuffix_:rightSuffix_):"images");
QString imagesWithBoardDir = rawImagesDir+"_board_detection";
if(!QDir(rawImagesDir).exists())
{
UINFO("Creating dir %s", rawImagesDir.toStdString().c_str());
QDir().mkpath(rawImagesDir);
}
if(!QDir(imagesWithBoardDir).exists())
{
UINFO("Creating dir %s", imagesWithBoardDir.toStdString().c_str());
QDir().mkpath(imagesWithBoardDir);
}
cv::imwrite((rawImagesDir+"/"+QString::number(currentId_)+".png").toStdString(), inputRawImages[id]);
cv::imwrite((imagesWithBoardDir+"/"+QString::number(currentId_)+".png").toStdString(), images[id]);
}
}
if(stereo_ && ((boardAccepted[0] && boardFound[1]) || (boardAccepted[1] && boardFound[0])))
{
stereoImagePoints_[0].push_back(pointBuf[0]);
stereoImagePoints_[1].push_back(pointBuf[1]);
stereoImageIds_.push_back(currentId_);
UINFO("Add stereo image points (size=%d)", (int)stereoImagePoints_[0].size());
}
@@ -645,18 +717,25 @@ void CalibrationDialog::processImages(const cv::Mat & imageLeft, const cv::Mat &
ui_->image_view_2->setImage(uCvMat2QImage(images[1]).mirrored(ui_->checkBox_mirror->isChecked(), false));
}
processingData_ = false;
if(sampleAdded)
++currentId_;
}
void CalibrationDialog::restart()
{
// restart
savedCalibration_ = false;
currentId_ = 0;
timestamp_ = QDateTime::currentDateTime().toString("yyyyMMddhhmmss");
imagePoints_[0].clear();
imagePoints_[1].clear();
imageParams_[0].clear();
imageParams_[1].clear();
imageIds_[0].clear();
imageIds_[1].clear();
stereoImagePoints_[0].clear();
stereoImagePoints_[1].clear();
stereoImageIds_.clear();
models_[0] = CameraModel();
models_[1] = CameraModel();
stereoModel_ = StereoCameraModel();
@@ -690,8 +769,11 @@ void CalibrationDialog::restart()
ui_->label_fy->setNum(0);
ui_->label_cx->setNum(0);
ui_->label_cy->setNum(0);
ui_->label_fovx->setNum(0);
ui_->label_fovy->setNum(0);
ui_->label_baseline->setNum(0);
ui_->label_error->setNum(0);
ui_->label_error_2->setNum(0);
ui_->lineEdit_K->clear();
ui_->lineEdit_D->clear();
ui_->lineEdit_R->clear();
@@ -747,7 +829,7 @@ void CalibrationDialog::calibrate()
//Find intrinsic and extrinsic camera parameters
double rms = 0.0;
#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)))
bool fishEye = ui_->checkBox_fisheye->isChecked();
bool fishEye = ui_->comboBox_calib_model->currentIndex()==0;
if(fishEye)
{
@@ -775,13 +857,28 @@ void CalibrationDialog::calibrate()
else
#endif
{
cv::Mat stdDevsMatInt, stdDevsMatExt;
cv::Mat perViewErrorsMat;
rms = cv::calibrateCamera(objectPoints,
imagePoints_[id],
imageSize_[id],
K,
D,
rvecs,
tvecs);
tvecs,
stdDevsMatInt,
stdDevsMatExt,
perViewErrorsMat,
ui_->comboBox_calib_model->currentIndex()==2?cv::CALIB_RATIONAL_MODEL:0);
if((int)imageIds_[id].size() == perViewErrorsMat.rows &&
ULogger::level() >= ULogger::kInfo)
{
UINFO("Per view errors:");
for(int i=0; i<perViewErrorsMat.rows; ++i)
{
UINFO("Image %d: %f", imageIds_[id][i], perViewErrorsMat.at<double>(i,0));
}
}
}
UINFO("Re-projection error reported by calibrateCamera: %f", rms);
@@ -846,6 +943,8 @@ void CalibrationDialog::calibrate()
ui_->label_fy->setNum(models_[id].fy());
ui_->label_cx->setNum(models_[id].cx());
ui_->label_cy->setNum(models_[id].cy());
ui_->label_fovx->setNum(models_[id].horizontalFOV());
ui_->label_fovy->setNum(models_[id].verticalFOV());
ui_->label_error->setNum(totalAvgErr);
std::stringstream strK, strD, strR, strP;
@@ -864,6 +963,8 @@ void CalibrationDialog::calibrate()
ui_->label_fy_2->setNum(models_[id].fy());
ui_->label_cx_2->setNum(models_[id].cx());
ui_->label_cy_2->setNum(models_[id].cy());
ui_->label_fovx_2->setNum(models_[id].horizontalFOV());
ui_->label_fovy_2->setNum(models_[id].verticalFOV());
ui_->label_error_2->setNum(totalAvgErr);
std::stringstream strK, strD, strR, strP;
@@ -887,7 +988,7 @@ void CalibrationDialog::calibrate()
stereoModel_.baseline() != ui_->doubleSpinBox_stereoBaseline->value())
{
UWARN("Expected stereo baseline is set to %f m, but computed baseline is %f m. Rescaling baseline...",
stereoModel_.baseline(), ui_->doubleSpinBox_stereoBaseline->value());
ui_->doubleSpinBox_stereoBaseline->value(), stereoModel_.baseline());
cv::Mat P = stereoModel_.right().P().clone();
P.at<double>(0,3) = -P.at<double>(0,0)*ui_->doubleSpinBox_stereoBaseline->value();
double scale = ui_->doubleSpinBox_stereoBaseline->value() / stereoModel_.baseline();
@@ -910,20 +1011,12 @@ void CalibrationDialog::calibrate()
ui_->lineEdit_R_2->setText(strR2.str().c_str());
ui_->lineEdit_P_2->setText(strP2.str().c_str());
ui_->label_fovx->setNum(stereoModel_.left().horizontalFOV());
ui_->label_fovx_2->setNum(stereoModel_.right().horizontalFOV());
ui_->label_fovy->setNum(stereoModel_.left().verticalFOV());
ui_->label_fovy_2->setNum(stereoModel_.right().verticalFOV());
ui_->label_baseline->setNum(stereoModel_.baseline());
//ui_->label_error_stereo->setNum(totalAvgErr);
if(!stereoModel_.left().P().empty() &&
!stereoModel_.left().K_raw().empty() &&
fabs(stereoModel_.left().P().at<double>(0,0) - stereoModel_.left().K_raw().at<double>(0,0)) > 5)
{
QMessageBox::warning(this, tr("Stereo Calibration"),
tr("\"fx\" after stereo rectification (%1) is not close from original "
"calibration (%2), the difference would have to be under 5. You may "
"restart the calibration or keep it as is.")
.arg(stereoModel_.left().P().at<double>(0,0))
.arg(stereoModel_.left().K_raw().at<double>(0,0)));
}
}
if(stereo_)
@@ -1148,7 +1241,7 @@ StereoCameraModel CalibrationDialog::stereoCalibration(const CameraModel & left,
right.K_raw(), right.D_raw(),
imageSize, R, T, E, F,
cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS, 100, 1e-5),
cv::CALIB_FIX_INTRINSIC);
cv::CALIB_FIX_INTRINSIC | (ui_->comboBox_calib_model->currentIndex()==2?cv::CALIB_RATIONAL_MODEL:0));
#else
rms = cv::stereoCalibrate(
objectPoints,
@@ -1157,7 +1250,7 @@ StereoCameraModel CalibrationDialog::stereoCalibration(const CameraModel & left,
left.K_raw(), left.D_raw(),
right.K_raw(), right.D_raw(),
imageSize, R, T, E, F,
cv::CALIB_FIX_INTRINSIC,
cv::CALIB_FIX_INTRINSIC | (ui_->comboBox_calib_model->currentIndex()==2?cv::CALIB_RATIONAL_MODEL:0),
cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS, 100, 1e-5));
#endif
UINFO("stereo calibration... done with RMS error=%f", rms);
@@ -1185,7 +1278,7 @@ StereoCameraModel CalibrationDialog::stereoCalibration(const CameraModel & left,
double err = 0;
int npoints = 0;
std::vector<cv::Vec3f> lines[2];
UINFO("Computing avg re-projection error...");
UINFO("Computing re-projection errors...");
for(unsigned int i = 0; i < stereoImagePoints_[0].size(); i++ )
{
int npt = (int)stereoImagePoints_[0][i].size();
@@ -1197,14 +1290,17 @@ StereoCameraModel CalibrationDialog::stereoCalibration(const CameraModel & left,
computeCorrespondEpilines(imgpt0, 1, F, lines[0]);
computeCorrespondEpilines(imgpt1, 2, F, lines[1]);
double sampleErr = 0.0;
for(int j = 0; j < npt; j++ )
{
double errij = fabs(stereoImagePoints_[0][i][j].x*lines[1][j][0] +
stereoImagePoints_[0][i][j].y*lines[1][j][1] + lines[1][j][2]) +
fabs(stereoImagePoints_[1][i][j].x*lines[0][j][0] +
stereoImagePoints_[1][i][j].y*lines[0][j][1] + lines[0][j][2]);
err += errij;
sampleErr += errij;
}
UINFO("Stereo image %d: %f", stereoImageIds_[i], sampleErr/npt);
err += sampleErr;
npoints += npt;
}
double totalAvgErr = err/(double)npoints;
@@ -1251,6 +1347,12 @@ bool CalibrationDialog::save()
UINFO("Saved \"%s\"!", filePath.toStdString().c_str());
savedCalibration_ = true;
saved = true;
if(ui_->checkBox_saveCalibrationData->isChecked())
{
// save a copy in calibration data folder
QFile::copy(filePath, savingDirectory_+"/"+cameraName_+"_"+timestamp_+"/"+QFileInfo(filePath).fileName());
}
}
else
{
@@ -1281,6 +1383,14 @@ bool CalibrationDialog::save()
UINFO("Saved \"%s\" and \"%s\"!", leftPath.c_str(), rightPath.c_str());
savedCalibration_ = true;
saved = true;
if(ui_->checkBox_saveCalibrationData->isChecked())
{
// save a copy in calibration data folder
QFile::copy(leftPath.c_str(), savingDirectory_+"/"+cameraName_+"_"+timestamp_+"/"+QFileInfo(leftPath.c_str()).fileName());
QFile::copy(rightPath.c_str(), savingDirectory_+"/"+cameraName_+"_"+timestamp_+"/"+QFileInfo(rightPath.c_str()).fileName());
QFile::copy(posePath.c_str(), savingDirectory_+"/"+cameraName_+"_"+timestamp_+"/"+QFileInfo(posePath.c_str()).fileName());
}
}
else
{

View File

@@ -7561,11 +7561,11 @@ void PreferencesDialog::calibrate()
}
bool freenect2 = driver == kSrcFreenect2;
bool fisheye = driver == kSrcStereoRealSense2;
_calibrationDialog->setStereoMode(this->getSourceType() != kSrcRGB && driver != kSrcRealSense, freenect2?"rgb":"left", freenect2?"depth":"right"); // RGB+Depth or left+right
_calibrationDialog->setCameraName("");
_calibrationDialog->setSwitchedImages(freenect2);
_calibrationDialog->setFisheyeImages(fisheye);
if(driver == kSrcStereoRealSense2)
_calibrationDialog->setFisheyeModel();
_calibrationDialog->setSavingDirectory(this->getCameraInfoDir());
_calibrationDialog->registerToEventsManager();

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>1314</width>
<height>847</height>
<width>1189</width>
<height>692</height>
</rect>
</property>
<property name="windowTitle">
@@ -30,7 +30,10 @@
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4" stretch="1,1">
<layout class="QHBoxLayout" name="horizontalLayout_4" stretch="1,0">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
@@ -123,7 +126,7 @@
<item>
<widget class="QCheckBox" name="checkBox_showHorizontalLines">
<property name="text">
<string>Show horizontal lines</string>
<string>Show lines</string>
</property>
</widget>
</item>
@@ -146,25 +149,25 @@
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
<bool>false</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>357</width>
<height>820</height>
<width>387</width>
<height>928</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@@ -186,129 +189,27 @@
<string>Chessboard</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="3">
<widget class="QSpinBox" name="spinBox_boardHeight">
<property name="minimum">
<number>2</number>
<item row="8" column="0">
<widget class="QLabel" name="label_stereoBaseline_2">
<property name="toolTip">
<string>If &gt; 1, image is scaled down to help board detection on high definition images</string>
</property>
<property name="value">
<number>6</number>
<property name="text">
<string>Calibration Model</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_15">
<property name="toolTip">
<string/>
</property>
<property name="text">
<string>Square size</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_12">
<property name="toolTip">
<string>Number of inner squares on the board</string>
</property>
<property name="text">
<string>Board size</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QLabel" name="label_16">
<property name="toolTip">
<string>Number of inner squares on the board</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBox_boardWidth">
<property name="minimum">
<number>2</number>
</property>
<property name="value">
<number>8</number>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_squareSize">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>4</number>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>0.033000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_21">
<property name="toolTip">
<string/>
</property>
<property name="text">
<string>Download</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_20">
<property name="toolTip">
<string>Number of inner squares on the board</string>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/introlab/rtabmap/raw/master/data/check-108.pdf&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Sample8x6&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="spinBox_maxScale">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>3</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_22">
<property name="toolTip">
<string>If &gt; 1, image is scaled down to help board detection on high definition images</string>
</property>
<property name="text">
<string>Max scale</string>
<string>Max Scale</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_stereoBaseline">
<property name="toolTip">
<string>If &gt; 1, image is scaled down to help board detection on high definition images</string>
</property>
<property name="text">
<string>Stereo Baseline</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_stereoBaseline">
<property name="toolTip">
<string>If you know the exact baseline of the stereo cameras, you can set it here in case the square size is not super accurate.</string>
@@ -327,9 +228,161 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_20">
<property name="toolTip">
<string>Number of inner squares on the board</string>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/introlab/rtabmap/raw/master/data/check-108.pdf&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Sample8x6&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_stereoBaseline">
<property name="toolTip">
<string>If &gt; 1, image is scaled down to help board detection on high definition images</string>
</property>
<property name="text">
<string>Stereo Expected Baseline</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_15">
<property name="toolTip">
<string/>
</property>
<property name="text">
<string>Square Size</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QComboBox" name="comboBox_calib_model">
<property name="currentIndex">
<number>1</number>
</property>
<item>
<property name="text">
<string>fisheye (4 coeffs)</string>
</property>
</item>
<item>
<property name="text">
<string>plumb_bob (5 coeffs)</string>
</property>
</item>
<item>
<property name="text">
<string>rational (8 coeffs)</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_21">
<property name="toolTip">
<string/>
</property>
<property name="text">
<string>Download</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_stereoBaseline_3">
<property name="toolTip">
<string>If &gt; 1, image is scaled down to help board detection on high definition images</string>
</property>
<property name="text">
<string>Save Calibration Data</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_squareSize">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>4</number>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>0.033000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_12">
<property name="toolTip">
<string>Number of inner squares on the board</string>
</property>
<property name="text">
<string>Board Size</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="spinBox_boardWidth">
<property name="minimum">
<number>2</number>
</property>
<property name="value">
<number>8</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_boardHeight">
<property name="minimum">
<number>2</number>
</property>
<property name="value">
<number>6</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spinBox_maxScale">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>3</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QCheckBox" name="checkBox_saveCalibrationData">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_restart">
<property name="text">
<string>Restart</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_progress">
<property name="title">
@@ -500,7 +553,7 @@
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5" stretch="1,0,0">
<layout class="QHBoxLayout" name="horizontalLayout_5" stretch="1,0">
<item>
<widget class="QPushButton" name="pushButton_calibrate">
<property name="text">
@@ -508,13 +561,6 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_fisheye">
<property name="text">
<string>Fish eye</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_unlock">
<property name="text">
@@ -524,105 +570,27 @@
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="pushButton_save">
<property name="text">
<string>Export calibration (*.yaml)</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Camera intrinsic parameters</string>
<string>Calibration parameters</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="8" column="2">
<widget class="QLineEdit" name="lineEdit_P_2">
<item row="9" column="1">
<widget class="QLineEdit" name="lineEdit_D">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_fx">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_fy">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="lineEdit_K">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_cx">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>cy</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_cy">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_6">
<property name="toolTip">
<string>Camera matrix</string>
</property>
<property name="text">
<string>K</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>fy</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>cx</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>fx</string>
</property>
</widget>
</item>
<item row="7" column="0">
<item row="10" column="0">
<widget class="QLabel" name="label_17">
<property name="toolTip">
<string>Distorsion coefficients</string>
@@ -632,95 +600,34 @@
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QLineEdit" name="lineEdit_D_2">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_7">
<property name="toolTip">
<string>Distorsion coefficients</string>
</property>
<property name="text">
<string>D</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="lineEdit_D">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_14">
<property name="toolTip">
<string>Avg. reproduction error</string>
</property>
<property name="text">
<string>Error</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="label_error">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_fx_2">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_cx_2">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_fy_2">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="label_cy_2">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="5" column="2">
<item row="8" column="2">
<widget class="QLineEdit" name="lineEdit_K_2">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="0">
<item row="5" column="1">
<widget class="QLabel" name="label_fovx">
<property name="toolTip">
<string>Deg</string>
</property>
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>cy</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_18">
<property name="toolTip">
<string>Distorsion coefficients</string>
@@ -730,36 +637,103 @@
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="lineEdit_R">
<property name="readOnly">
<bool>true</bool>
<item row="1" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>fx</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="lineEdit_P">
<property name="readOnly">
<bool>true</bool>
<item row="6" column="2">
<widget class="QLabel" name="label_fovy_2">
<property name="toolTip">
<string>Deg</string>
</property>
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="7" column="2">
<item row="4" column="1">
<widget class="QLabel" name="label_cy">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="10" column="2">
<widget class="QLineEdit" name="lineEdit_R_2">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<item row="8" column="0">
<widget class="QLabel" name="label_6">
<property name="toolTip">
<string>Camera matrix</string>
</property>
<property name="text">
<string>K</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_16">
<property name="toolTip">
<string>Avg. reproduction error</string>
</property>
<property name="text">
<string>fovx</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLineEdit" name="lineEdit_R">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_baseline_name">
<property name="text">
<string>baseline</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_fx">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>cx</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>fy</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QLabel" name="label_baseline">
<widget class="QLabel" name="label_cy_2">
<property name="text">
<string>0</string>
</property>
@@ -769,6 +743,157 @@
</widget>
</item>
<item row="9" column="2">
<widget class="QLineEdit" name="lineEdit_D_2">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_7">
<property name="toolTip">
<string>Distorsion coefficients</string>
</property>
<property name="text">
<string>D</string>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QLineEdit" name="lineEdit_P">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="label_cx_2">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QLabel" name="label_baseline">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="11" column="2">
<widget class="QLineEdit" name="lineEdit_P_2">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_fy_2">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_cx">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="lineEdit_K">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_fx_2">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label_fovy">
<property name="toolTip">
<string>Deg</string>
</property>
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_fy">
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_23">
<property name="toolTip">
<string>Avg. reproduction error</string>
</property>
<property name="text">
<string>fovy</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QLabel" name="label_fovx_2">
<property name="toolTip">
<string>Deg</string>
</property>
<property name="text">
<string>0</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_14">
<property name="toolTip">
<string>Avg. reproduction error</string>
</property>
<property name="text">
<string>Error</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_error">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_error_2">
<property name="text">
<string>0</string>
@@ -778,20 +903,6 @@
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_save">
<property name="text">
<string>Export calibration (*.yaml)</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_restart">
<property name="text">
<string>Restart</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>