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)
calibrationTogglePB->setText("Calibrating...");
calibrationTogglePB->setEnabled(false);
collectPB->setEnabled(false);
setLabelText(rmsQL, "Calculating", "orange");
if (dbgCB->isChecked())
destroyWindow(DBG_WINDOW_NAME);
QMetaObject::invokeMethod(this, "finishCalibration", Qt::QueuedConnection);
}
}
......@@ -26,20 +29,29 @@ void CameraCalibration::startCalibration()
calibrationTogglePB->setText("Finish");
settingsGB->setEnabled(false);
collectPB->setEnabled(true);
undistortPB->setEnabled(false);
imagePoints.clear();
sampleCountQL->setText(QString::number(imagePoints.size()));
setCoverage();
sampleCount = 0;
sampleCountQL->setText(QString::number(sampleCount));
covered = Rect();
if (dbgCB->isChecked())
namedWindow(DBG_WINDOW_NAME);
}
void CameraCalibration::finishCalibration()
{
if (dbgCB->isChecked())
destroyWindow(DBG_WINDOW_NAME);
calibrate();
QFuture<void> future = QtConcurrent::run(this, &CameraCalibration::calibrate);
watcher.setFuture(future);
}
void CameraCalibration::onCalibrated()
{
this->layout()->setEnabled(true);
updateCalibrationStatus( calibrationSuccessful );
calibrationTogglePB->setText("Start");
calibrationTogglePB->setEnabled(true);
undistortPB->setEnabled(true);
settingsGB->setEnabled(true);
emit calibrationFinished( calibrationSuccessful );
}
......@@ -49,18 +61,15 @@ void CameraCalibration::updateCalibrationStatus(bool success)
if (success) {
qInfo() << "Camera calibration done. RMS Error =" << rms;
undistortPB->setEnabled(true);
if (rms < 1)
rmsQL->setStyleSheet("QLabel { font : bold; color : green }");
else {
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) );
setRms(rms);
setCoverage(coverage);
sampleCountQL->setText(QString::number(sampleCount));
} else {
qInfo() << "Camera calibration failed.";
undistortPB->setEnabled(false);
rmsQL->setStyleSheet("QLabel { font : bold; color : black }");
rmsQL->setText( "N/A" );
setRms();
setCoverage();
sampleCountQL->setText(QString::number(sampleCount));
}
}
......@@ -157,6 +166,18 @@ void CameraCalibration::processSample(const Mat &frame)
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()) {
Mat tmp;
if (frame.channels() == 1)
......@@ -168,14 +189,10 @@ void CameraCalibration::processSample(const Mat &frame)
drawChessboardCorners( tmp, patternSize, Mat(pointBuf), found);
else
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);
}
if (found) {
imagePoints.push_back(pointBuf);
sampleCountQL->setText(QString::number(imagePoints.size()));
}
collectPB->setEnabled(true);
}
......@@ -188,11 +205,11 @@ void CameraCalibration::calibrate()
else
distCoeffs = Mat::zeros(8, 1, CV_64F);
if (imagePoints.size() < 5) {
rms = 0;
calibrationSuccessful = false;
calibrationSuccessful = false;
rms = 0;
if (imagePoints.size() < 5)
return;
}
vector<vector<Point3f> > objectPoints(1);
calculateBoardCorners(objectPoints[0]);
......@@ -216,6 +233,8 @@ void CameraCalibration::store(const QString &fileName)
fs << "distCoeffs" << distCoeffs;
fs << "imageSize" << imageSize;
fs << "newCameraMatrix" << newCameraMatrix;
fs << "sampleCount" << sampleCount;
fs << "coverage" << coverage;
fs << "rms" << rms;
}
......@@ -230,6 +249,8 @@ void CameraCalibration::load(const QString &fileName)
fs["distCoeffs"] >> distCoeffs;
fs["imageSize"] >> imageSize;
fs["newCameraMatrix"] >> newCameraMatrix;
fs["sampleCount"] >> sampleCount;
fs["coverage"] >> coverage;
fs["rms"] >> rms;
calibrationSuccessful = true;
}
......
......@@ -16,6 +16,8 @@
#include <QCheckBox>
#include <QLabel>
#include <QFileInfo>
#include <QtConcurrent/QtConcurrent>
#include <QFutureWatcher>
#include "opencv2/imgproc.hpp"
#include "opencv2/calib3d.hpp"
......@@ -29,7 +31,9 @@ class CameraCalibration : public QDialog
public:
CameraCalibration(QWidget *parent=0)
: QDialog(parent),
calibrationSuccessful(false)
calibrationSuccessful(false),
sampleCount(0),
coverage(0)
{
this->setWindowModality(Qt::ApplicationModal);
this->setWindowTitle("Camera Calibration");
......@@ -102,14 +106,20 @@ public:
sampleCountQL = new QLabel();
sampleCountQL->setText(QString::number(0));
formLayout->addRow( new QLabel("Samples:"), sampleCountQL);
coveredQL = new QLabel();
coveredQL->setText(QString::number(0) + " %");
formLayout->addRow( new QLabel("Covered:"), coveredQL);
rmsQL = new QLabel();
rmsQL->setStyleSheet("QLabel { font : bold; color : black }");
rmsQL->setText("N/A");
setRms();
formLayout->addRow( new QLabel("RMS Error:"), rmsQL);
controlGB->setLayout(formLayout);
hl->addWidget(controlGB);
setLayout(hl);
connect(&watcher, SIGNAL(finished()),
this, SLOT(onCalibrated()) );
}
enum CALIBRATION_PATTERN {
......@@ -121,6 +131,8 @@ public:
cv::Mat cameraMatrix;
cv::Mat newCameraMatrix;
cv::Mat distCoeffs;
int sampleCount;
double coverage;
bool calibrationSuccessful;
signals:
......@@ -153,21 +165,51 @@ private:
QPushButton *collectPB;
QPushButton *undistortPB;
QLabel *sampleCountQL;
QLabel *coveredQL;
QLabel *rmsQL;
QFutureWatcher<void> watcher;
std::vector<std::vector<cv::Point2f> > imagePoints;
cv::Size imageSize;
cv::Rect covered;
void processSample(const cv::Mat &frame);
void undistortSample(const cv::Mat &frame);
void calculateBoardCorners(std::vector<cv::Point3f> &corners);
void calibrate();
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;
private slots:
void startCalibration();
void finishCalibration();
void onCalibrated();
};
#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