diff --git a/EyeRecToo/src/gaze-estimation/BinocularPolyFit.cpp b/EyeRecToo/src/gaze-estimation/BinocularPolyFit.cpp index 264ced887aad7bfeb1d3104b32a36bb22986d493..635594703275653a41685de2e0077fd71320cfc8 100644 --- a/EyeRecToo/src/gaze-estimation/BinocularPolyFit.cpp +++ b/EyeRecToo/src/gaze-estimation/BinocularPolyFit.cpp @@ -18,9 +18,6 @@ string BinocularPolyFit::description() const bool BinocularPolyFit::calibrate(vector& calibrationTuples, QString& errorMsg) { - if (!PolyFit::calibrate(calibrationTuples, errorMsg)) - return false; - PointVector leftPupil; PointVector rightPupil; PointVector gaze; @@ -39,9 +36,50 @@ bool BinocularPolyFit::calibrate(vector& calibrationTuples, QSt binocularCalibrated = calibrate(plType, leftPupil.x, leftPupil.y, rightPupil.x, rightPupil.y, gaze.x, bcx, errorMsg) && calibrate(plType, leftPupil.x, leftPupil.y, rightPupil.x, rightPupil.y, gaze.y, bcy, errorMsg); + if (!binocularCalibrated) + return binocularCalibrated; + + const auto& ref = calibrationTuples[0]; + float threshold = 0.01f * hypot(ref.field.width, ref.field.height); + vector inliers; + for (const auto& tuple : calibrationTuples) { + GazeEstimate l, r, b; + l.pupilConfidence = tuple.lEye.pupil.confidence; + r.pupilConfidence = tuple.rEye.pupil.confidence; + estimateBinocular2d(tuple, l, r, b); + Point2f gt = { tuple.field.collectionMarker.center.x, tuple.field.collectionMarker.center.y }; + if (cv::norm(gt - b.gp) < threshold) + inliers.push_back(tuple); + } + + binocularCalibrated = calibrateWithInliers(inliers, errorMsg); return binocularCalibrated; } +bool BinocularPolyFit::calibrateWithInliers(std::vector& calibrationTuples, QString& errorMsg) +{ + if (!PolyFit::calibrate(calibrationTuples, errorMsg)) + return false; + + PointVector leftPupil; + PointVector rightPupil; + PointVector gaze; + + for (const auto& tuple : calibrationTuples) { + leftPupil.insert(PolyFit::normalize(tuple.lEye.pupil.center, tuple.lEye.input)); + rightPupil.insert(PolyFit::normalize(tuple.rEye.pupil.center, tuple.rEye.input)); + gaze.insert(PolyFit::normalize(tuple.field.collectionMarker.center, tuple.field.input)); + } + + if (gaze.size() < binocularUnknowns) { + errorMsg = QString("Not enough calibration points (%1/%2).").arg(gaze.size()).arg(binocularUnknowns); + return false; + } + + return calibrate(plType, leftPupil.x, leftPupil.y, rightPupil.x, rightPupil.y, gaze.x, bcx, errorMsg) + && calibrate(plType, leftPupil.x, leftPupil.y, rightPupil.x, rightPupil.y, gaze.y, bcy, errorMsg); +} + bool BinocularPolyFit::calibrate(const PlType& type, const Mat& lx, const Mat& ly, const Mat& rx, const Mat& ry, const Mat& z, Mat1d& c, QString& errorMsg) { diff --git a/EyeRecToo/src/gaze-estimation/BinocularPolyFit.h b/EyeRecToo/src/gaze-estimation/BinocularPolyFit.h index 44a720b07ff88a8b4eaedb1fb77f6aa132c1ab39..5a9c465e90994ff4a948f3e05a85ebcb1a0f77d6 100644 --- a/EyeRecToo/src/gaze-estimation/BinocularPolyFit.h +++ b/EyeRecToo/src/gaze-estimation/BinocularPolyFit.h @@ -18,6 +18,7 @@ private: cv::Mat1d bcy; bool calibrate(const PlType& type, const cv::Mat& lx, const cv::Mat& ly, const cv::Mat& rx, const cv::Mat& ry, const cv::Mat& z, cv::Mat1d& c, QString& errorMsg); + bool calibrateWithInliers(std::vector& calibrationTuples, QString& errorMsg); }; #endif // BINOCULARPOLYFIT_H