Commit 58c23648 authored by Thiago Santini's avatar Thiago Santini

Calibrate on separate thread, improves user feedback

parent 20542325
...@@ -17,6 +17,9 @@ void CameraCalibration::toggleCalibration(bool status) ...@@ -17,6 +17,9 @@ void CameraCalibration::toggleCalibration(bool status)
calibrationTogglePB->setText("Calibrating..."); calibrationTogglePB->setText("Calibrating...");
calibrationTogglePB->setEnabled(false); calibrationTogglePB->setEnabled(false);
collectPB->setEnabled(false); collectPB->setEnabled(false);
setLabelText(rmsQL, "Calculating", "orange");
if (dbgCB->isChecked())
destroyWindow(DBG_WINDOW_NAME);
QMetaObject::invokeMethod(this, "finishCalibration", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "finishCalibration", Qt::QueuedConnection);
} }
} }
...@@ -26,20 +29,29 @@ void CameraCalibration::startCalibration() ...@@ -26,20 +29,29 @@ void CameraCalibration::startCalibration()
calibrationTogglePB->setText("Finish"); calibrationTogglePB->setText("Finish");
settingsGB->setEnabled(false); settingsGB->setEnabled(false);
collectPB->setEnabled(true); collectPB->setEnabled(true);
undistortPB->setEnabled(false);
imagePoints.clear(); imagePoints.clear();
sampleCountQL->setText(QString::number(imagePoints.size())); setCoverage();
sampleCount = 0;
sampleCountQL->setText(QString::number(sampleCount));
covered = Rect();
if (dbgCB->isChecked()) if (dbgCB->isChecked())
namedWindow(DBG_WINDOW_NAME); namedWindow(DBG_WINDOW_NAME);
} }
void CameraCalibration::finishCalibration() void CameraCalibration::finishCalibration()
{ {
if (dbgCB->isChecked()) QFuture<void> future = QtConcurrent::run(this, &CameraCalibration::calibrate);
destroyWindow(DBG_WINDOW_NAME); watcher.setFuture(future);
calibrate(); }
void CameraCalibration::onCalibrated()
{
this->layout()->setEnabled(true);
updateCalibrationStatus( calibrationSuccessful ); updateCalibrationStatus( calibrationSuccessful );
calibrationTogglePB->setText("Start"); calibrationTogglePB->setText("Start");
calibrationTogglePB->setEnabled(true); calibrationTogglePB->setEnabled(true);
undistortPB->setEnabled(true);
settingsGB->setEnabled(true); settingsGB->setEnabled(true);
emit calibrationFinished( calibrationSuccessful ); emit calibrationFinished( calibrationSuccessful );
} }
...@@ -49,18 +61,15 @@ void CameraCalibration::updateCalibrationStatus(bool success) ...@@ -49,18 +61,15 @@ void CameraCalibration::updateCalibrationStatus(bool success)
if (success) { if (success) {
qInfo() << "Camera calibration done. RMS Error =" << rms; qInfo() << "Camera calibration done. RMS Error =" << rms;
undistortPB->setEnabled(true); undistortPB->setEnabled(true);
if (rms < 1) setRms(rms);
rmsQL->setStyleSheet("QLabel { font : bold; color : green }"); setCoverage(coverage);
else { sampleCountQL->setText(QString::number(sampleCount));
rmsQL->setStyleSheet("QLabel { font : bold; color : red }");
qInfo() << "RMS Error is above the expected value. It's recommended to recalibrate.";
}
rmsQL->setText( QString::number(rms) );
} else { } else {
qInfo() << "Camera calibration failed."; qInfo() << "Camera calibration failed.";
undistortPB->setEnabled(false); undistortPB->setEnabled(false);
rmsQL->setStyleSheet("QLabel { font : bold; color : black }"); setRms();
rmsQL->setText( "N/A" ); setCoverage();
sampleCountQL->setText(QString::number(sampleCount));
} }
} }
...@@ -157,6 +166,18 @@ void CameraCalibration::processSample(const Mat &frame) ...@@ -157,6 +166,18 @@ void CameraCalibration::processSample(const Mat &frame)
break; break;
} }
if (found) {
imagePoints.push_back(pointBuf);
sampleCount = imagePoints.size();
if (sampleCount == 1)
covered = boundingRect(pointBuf);
else
covered |= boundingRect(pointBuf);
sampleCountQL->setText(QString::number(sampleCount));
coverage = covered.area() / (double) imageSize.area();
setCoverage( coverage );
}
if (dbgCB->isChecked()) { if (dbgCB->isChecked()) {
Mat tmp; Mat tmp;
if (frame.channels() == 1) if (frame.channels() == 1)
...@@ -168,14 +189,10 @@ void CameraCalibration::processSample(const Mat &frame) ...@@ -168,14 +189,10 @@ void CameraCalibration::processSample(const Mat &frame)
drawChessboardCorners( tmp, patternSize, Mat(pointBuf), found); drawChessboardCorners( tmp, patternSize, Mat(pointBuf), found);
else else
putText(tmp, "Pattern not found", Point(0, 0.5*frame.rows), CV_FONT_HERSHEY_PLAIN, 2, Scalar(0,0,255)); putText(tmp, "Pattern not found", Point(0, 0.5*frame.rows), CV_FONT_HERSHEY_PLAIN, 2, Scalar(0,0,255));
rectangle(tmp, covered, Scalar(0,255,0), 2);
imshow(DBG_WINDOW_NAME, tmp); imshow(DBG_WINDOW_NAME, tmp);
} }
if (found) {
imagePoints.push_back(pointBuf);
sampleCountQL->setText(QString::number(imagePoints.size()));
}
collectPB->setEnabled(true); collectPB->setEnabled(true);
} }
...@@ -188,11 +205,11 @@ void CameraCalibration::calibrate() ...@@ -188,11 +205,11 @@ void CameraCalibration::calibrate()
else else
distCoeffs = Mat::zeros(8, 1, CV_64F); distCoeffs = Mat::zeros(8, 1, CV_64F);
if (imagePoints.size() < 5) { calibrationSuccessful = false;
rms = 0; rms = 0;
calibrationSuccessful = false;
if (imagePoints.size() < 5)
return; return;
}
vector<vector<Point3f> > objectPoints(1); vector<vector<Point3f> > objectPoints(1);
calculateBoardCorners(objectPoints[0]); calculateBoardCorners(objectPoints[0]);
...@@ -216,6 +233,8 @@ void CameraCalibration::store(const QString &fileName) ...@@ -216,6 +233,8 @@ void CameraCalibration::store(const QString &fileName)
fs << "distCoeffs" << distCoeffs; fs << "distCoeffs" << distCoeffs;
fs << "imageSize" << imageSize; fs << "imageSize" << imageSize;
fs << "newCameraMatrix" << newCameraMatrix; fs << "newCameraMatrix" << newCameraMatrix;
fs << "sampleCount" << sampleCount;
fs << "coverage" << coverage;
fs << "rms" << rms; fs << "rms" << rms;
} }
...@@ -230,6 +249,8 @@ void CameraCalibration::load(const QString &fileName) ...@@ -230,6 +249,8 @@ void CameraCalibration::load(const QString &fileName)
fs["distCoeffs"] >> distCoeffs; fs["distCoeffs"] >> distCoeffs;
fs["imageSize"] >> imageSize; fs["imageSize"] >> imageSize;
fs["newCameraMatrix"] >> newCameraMatrix; fs["newCameraMatrix"] >> newCameraMatrix;
fs["sampleCount"] >> sampleCount;
fs["coverage"] >> coverage;
fs["rms"] >> rms; fs["rms"] >> rms;
calibrationSuccessful = true; calibrationSuccessful = true;
} }
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#include <QCheckBox> #include <QCheckBox>
#include <QLabel> #include <QLabel>
#include <QFileInfo> #include <QFileInfo>
#include <QtConcurrent/QtConcurrent>
#include <QFutureWatcher>
#include "opencv2/imgproc.hpp" #include "opencv2/imgproc.hpp"
#include "opencv2/calib3d.hpp" #include "opencv2/calib3d.hpp"
...@@ -29,7 +31,9 @@ class CameraCalibration : public QDialog ...@@ -29,7 +31,9 @@ class CameraCalibration : public QDialog
public: public:
CameraCalibration(QWidget *parent=0) CameraCalibration(QWidget *parent=0)
: QDialog(parent), : QDialog(parent),
calibrationSuccessful(false) calibrationSuccessful(false),
sampleCount(0),
coverage(0)
{ {
this->setWindowModality(Qt::ApplicationModal); this->setWindowModality(Qt::ApplicationModal);
this->setWindowTitle("Camera Calibration"); this->setWindowTitle("Camera Calibration");
...@@ -102,14 +106,20 @@ public: ...@@ -102,14 +106,20 @@ public:
sampleCountQL = new QLabel(); sampleCountQL = new QLabel();
sampleCountQL->setText(QString::number(0)); sampleCountQL->setText(QString::number(0));
formLayout->addRow( new QLabel("Samples:"), sampleCountQL); formLayout->addRow( new QLabel("Samples:"), sampleCountQL);
coveredQL = new QLabel();
coveredQL->setText(QString::number(0) + " %");
formLayout->addRow( new QLabel("Covered:"), coveredQL);
rmsQL = new QLabel(); rmsQL = new QLabel();
rmsQL->setStyleSheet("QLabel { font : bold; color : black }"); setRms();
rmsQL->setText("N/A");
formLayout->addRow( new QLabel("RMS Error:"), rmsQL); formLayout->addRow( new QLabel("RMS Error:"), rmsQL);
controlGB->setLayout(formLayout); controlGB->setLayout(formLayout);
hl->addWidget(controlGB); hl->addWidget(controlGB);
setLayout(hl); setLayout(hl);
connect(&watcher, SIGNAL(finished()),
this, SLOT(onCalibrated()) );
} }
enum CALIBRATION_PATTERN { enum CALIBRATION_PATTERN {
...@@ -121,6 +131,8 @@ public: ...@@ -121,6 +131,8 @@ public:
cv::Mat cameraMatrix; cv::Mat cameraMatrix;
cv::Mat newCameraMatrix; cv::Mat newCameraMatrix;
cv::Mat distCoeffs; cv::Mat distCoeffs;
int sampleCount;
double coverage;
bool calibrationSuccessful; bool calibrationSuccessful;
signals: signals:
...@@ -153,21 +165,51 @@ private: ...@@ -153,21 +165,51 @@ private:
QPushButton *collectPB; QPushButton *collectPB;
QPushButton *undistortPB; QPushButton *undistortPB;
QLabel *sampleCountQL; QLabel *sampleCountQL;
QLabel *coveredQL;
QLabel *rmsQL; QLabel *rmsQL;
QFutureWatcher<void> watcher;
std::vector<std::vector<cv::Point2f> > imagePoints; std::vector<std::vector<cv::Point2f> > imagePoints;
cv::Size imageSize; cv::Size imageSize;
cv::Rect covered;
void processSample(const cv::Mat &frame); void processSample(const cv::Mat &frame);
void undistortSample(const cv::Mat &frame); void undistortSample(const cv::Mat &frame);
void calculateBoardCorners(std::vector<cv::Point3f> &corners); void calculateBoardCorners(std::vector<cv::Point3f> &corners);
void calibrate(); void calibrate();
void updateCalibrationStatus(bool success); void updateCalibrationStatus(bool success);
void setLabelText(QLabel* label, QString val, QString color) {
label->setStyleSheet("QLabel { font : bold; color : " + color + " }");
label->setText( val );
}
void setRms() { setLabelText(rmsQL, "N/A", "black"); }
void setRms(double val) {
if ( val < 1)
setLabelText(rmsQL, QString::number(val), "green");
else {
setLabelText(rmsQL, QString::number(val), "red");
qInfo() << "RMS Error is above the expected value. It's recommended to recalibrate.";
}
}
void setCoverage() { setLabelText(coveredQL, "N/A", "black"); }
void setCoverage(double val) {
QString pct = QString::number( (int) 100 * val) + " %";
if ( val >= 0.8) {
setLabelText(coveredQL, pct, "green");
} else if (val >= 0.6) {
setLabelText(coveredQL, pct, "orange");
} else {
setLabelText(coveredQL, pct, "red");
}
}
double rms; double rms;
private slots: private slots:
void startCalibration(); void startCalibration();
void finishCalibration(); void finishCalibration();
void onCalibrated();
}; };
#endif // CAMERACALIBRATION_H #endif // CAMERACALIBRATION_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment