Commit 6a4b6aac authored by Thiago C. Santini's avatar Thiago C. Santini

Integrates the calibration methods

parent 5a0bef49
...@@ -2,6 +2,14 @@ ...@@ -2,6 +2,14 @@
Calibration::Calibration() Calibration::Calibration()
{ {
QString methodName = settings.value("calibration/method").toString();
if ( methodName == "polyfit" ) {
method = new PolyFit(PolyFit::POLY_1_X_Y_XX_YY_XY_XXYY);
} else {
method = new Homography();
}
collecting = false; collecting = false;
calibrating = false; calibrating = false;
calibrated = false; calibrated = false;
...@@ -112,28 +120,21 @@ bool Calibration::calibrate() ...@@ -112,28 +120,21 @@ bool Calibration::calibrate()
} }
#endif #endif
int minPointsForCalibration = settings.value("calibration/minPointsForCalibration").toInt(); QString errorMsg;
if (fieldPoints.size() < minPointsForCalibration) {
QMessageBox::warning(NULL, "Calibration failed.",
QString("Not enough calibration points.\nGot %1\nRequired: %2\nPlease start again.").arg(fieldPoints.size()).arg(minPointsForCalibration),
QMessageBox::Ok, QMessageBox::NoButton);
success = false;
}
else {
calibrationMatrix = cv::findHomography(pupilEstimates, fieldPoints, cv::RANSAC);
if ( calibrationMatrix.empty() )
calibrationMatrix = cv::findHomography(pupilEstimates, fieldPoints);
if (calibrationMatrix.empty()) {
QMessageBox::warning(NULL, "Calibration failed.", "Could not find perspective transformation.\nPlease start again.", QMessageBox::Ok, QMessageBox::NoButton);
success = false;
}
} success = method->calibrate(
vector<Point2d>(pupilEstimates.begin(), pupilEstimates.end()),
vector<Point2d>(pupilEstimates.begin(), pupilEstimates.end()),
vector<Point2d>(fieldPoints.begin(), fieldPoints.end()),
errorMsg
);
if (!success) if (!success) {
QMessageBox::warning(NULL, "Calibration failed.",
errorMsg,
QMessageBox::Ok, QMessageBox::NoButton);
reset(); reset();
}
return success; return success;
} }
......
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
#include "opencv2/core/core.hpp" #include "opencv2/core/core.hpp"
#include "opencv2/calib3d/calib3d.hpp" #include "opencv2/calib3d/calib3d.hpp"
#include "CalibrationMethod.h"
#include "PolyFit.h"
#include "Homography.h"
#include "settings.h" #include "settings.h"
#include "utils.h" #include "utils.h"
...@@ -42,6 +46,7 @@ public: ...@@ -42,6 +46,7 @@ public:
bool calibrated; bool calibrated;
bool calibrating; bool calibrating;
bool recording; bool recording;
CalibrationMethod *method;
private slots: private slots:
void endCollection(); void endCollection();
......
...@@ -25,11 +25,7 @@ void ImageProcessing::project(JournalEntry &journalEntry) ...@@ -25,11 +25,7 @@ void ImageProcessing::project(JournalEntry &journalEntry)
journalEntry.fieldProjection = cv::Point(0,0); journalEntry.fieldProjection = cv::Point(0,0);
return; return;
} else { } else {
std::vector<cv::Point2f> fieldEstimation; journalEntry.fieldProjection = calibration->method->evaluate(journalEntry.pupil.center, journalEntry.pupil.center);
std::vector<cv::Point2f> pupil;
pupil.push_back(cv::Point2f(journalEntry.pupil.center.x, journalEntry.pupil.center.y));
cv::perspectiveTransform(pupil, fieldEstimation, calibration->calibrationMatrix);
journalEntry.fieldProjection = fieldEstimation[0];
} }
} }
......
...@@ -3,6 +3,14 @@ ...@@ -3,6 +3,14 @@
PolyFit::PolyFit(PlType plType) PolyFit::PolyFit(PlType plType)
{ {
this->plType = plType; this->plType = plType;
switch (plType) {
case POLY_1_X_Y_XX_YY_XY_XXYY:
unknowns = 7;
break;
default:
break;
}
} }
PolyFit::~PolyFit() PolyFit::~PolyFit()
...@@ -15,6 +23,11 @@ bool PolyFit::calibrate(vector<Point2d> leftPupil, vector<Point2d> rightPupil, v ...@@ -15,6 +23,11 @@ bool PolyFit::calibrate(vector<Point2d> leftPupil, vector<Point2d> rightPupil, v
// Ax = b // Ax = b
// x = A^{-1} b // x = A^{-1} b
if ( field.size() < unknowns ) {
errorMsg = QString("Not enough calibration points.\nGot %1\nRequired: %2\nPlease start again.").arg(field.size()).arg(unknowns);
return false;
}
// Possible terms; not using more than third order atm // Possible terms; not using more than third order atm
Mat x, y , xx, yy, xy, xxyy, zx, zy, A, iA; Mat x, y , xx, yy, xy, xxyy, zx, zy, A, iA;
...@@ -34,10 +47,8 @@ bool PolyFit::calibrate(vector<Point2d> leftPupil, vector<Point2d> rightPupil, v ...@@ -34,10 +47,8 @@ bool PolyFit::calibrate(vector<Point2d> leftPupil, vector<Point2d> rightPupil, v
// TODO: depending on the polynom and number of calibration points, we can have an overdetermined system. // TODO: depending on the polynom and number of calibration points, we can have an overdetermined system.
// Right now, we simply drop the extra equations, but we can select the set of equations that minimize error in the future. // Right now, we simply drop the extra equations, but we can select the set of equations that minimize error in the future.
int unknowns;
switch (plType) { switch (plType) {
case POLY_1_X_Y_XX_YY_XY_XXYY: case POLY_1_X_Y_XX_YY_XY_XXYY:
unknowns = 7;
// A.col(0) was initialized with one // A.col(0) was initialized with one
x.copyTo(A.col(1)); x.copyTo(A.col(1));
y.copyTo(A.col(2)); y.copyTo(A.col(2));
...@@ -51,12 +62,6 @@ bool PolyFit::calibrate(vector<Point2d> leftPupil, vector<Point2d> rightPupil, v ...@@ -51,12 +62,6 @@ bool PolyFit::calibrate(vector<Point2d> leftPupil, vector<Point2d> rightPupil, v
break; break;
} }
if ( x.rows < unknowns ) {
errorMsg = QString("Not enough calibration points.\nGot %1\nRequired: %2\nPlease start again.").arg(x.rows).arg(unknowns);
return false;
}
A = A(Rect2d(0,0,unknowns,unknowns)); A = A(Rect2d(0,0,unknowns,unknowns));
zx = zx(Rect2d(0,0,1,unknowns)); zx = zx(Rect2d(0,0,1,unknowns));
zy = zy(Rect2d(0,0,1,unknowns)); zy = zy(Rect2d(0,0,1,unknowns));
......
...@@ -30,6 +30,7 @@ private: ...@@ -30,6 +30,7 @@ private:
PlType plType; PlType plType;
Mat1d cx; Mat1d cx;
Mat1d cy; Mat1d cy;
int unknowns;
}; };
#endif // POLYFIT_H #endif // POLYFIT_H
...@@ -147,6 +147,9 @@ int main(int argc, char *argv[]) ...@@ -147,6 +147,9 @@ int main(int argc, char *argv[])
* GUI placement and start the main event loop * GUI placement and start the main event loop
********************************************************************/ ********************************************************************/
qDebug() << "Pupil detection method:" << settings.value("general/PupilDetector").toString();
qDebug() << "Calibration method:" << settings.value("calibration/method").toString();
QRect screenGeometry = QApplication::desktop()->screenGeometry(); QRect screenGeometry = QApplication::desktop()->screenGeometry();
int x = (screenGeometry.width() - gui.width()) / 2; int x = (screenGeometry.width() - gui.width()) / 2;
int y = (screenGeometry.height() - gui.height()) / 2; int y = (screenGeometry.height() - gui.height()) / 2;
......
...@@ -48,9 +48,9 @@ void updateSettings() ...@@ -48,9 +48,9 @@ void updateSettings()
testUpdate("outputTimestamp/format", "yyyyMMddHHmmss"); testUpdate("outputTimestamp/format", "yyyyMMddHHmmss");
testUpdate("outputTimestamp/tz", "UTC+01:00"); testUpdate("outputTimestamp/tz", "UTC+01:00");
testUpdate("calibration/minPointsForCalibration", 4);
testUpdate("calibration/minSamplesPerPoint", 5); testUpdate("calibration/minSamplesPerPoint", 5);
testUpdate("calibration/pointSamplingTimeMs", 500); testUpdate("calibration/pointSamplingTimeMs", 500);
testUpdate("calibration/method", "polyfit");
testUpdate("general/outputDirectory", "output"); testUpdate("general/outputDirectory", "output");
testUpdate("general/pupilDetector", "else"); testUpdate("general/pupilDetector", "else");
......
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