diff --git a/EyeRecToo/src/CameraCalibration.cpp b/EyeRecToo/src/CameraCalibration.cpp index 8d2ea6937bee59d443e48855562fbd0ceb7bc5c4..9154d27fb219948bc8f53ca1ad61dcc2424a4007 100644 --- a/EyeRecToo/src/CameraCalibration.cpp +++ b/EyeRecToo/src/CameraCalibration.cpp @@ -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 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 > 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; } diff --git a/EyeRecToo/src/CameraCalibration.h b/EyeRecToo/src/CameraCalibration.h index 7d52dee0c94c6d9afe1cb69f6fe89b648930c444..733f97ba3c7532ed988a315db4a5db416732de03 100644 --- a/EyeRecToo/src/CameraCalibration.h +++ b/EyeRecToo/src/CameraCalibration.h @@ -16,6 +16,8 @@ #include #include #include +#include +#include #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 watcher; + std::vector > imagePoints; cv::Size imageSize; + cv::Rect covered; + void processSample(const cv::Mat &frame); void undistortSample(const cv::Mat &frame); void calculateBoardCorners(std::vector &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