From 45eeed930634857fc05baea71747868ec5fb012d Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 29 Aug 2018 13:58:47 +0900 Subject: [PATCH] Optimizations to drift correction and model filter --- main/eye_model_updater.cpp | 131 +++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 62 deletions(-) diff --git a/main/eye_model_updater.cpp b/main/eye_model_updater.cpp index 1bced8a..130065d 100644 --- a/main/eye_model_updater.cpp +++ b/main/eye_model_updater.cpp @@ -226,7 +226,7 @@ int EyeModelUpdater::get_current_count() { */ void EyeModelUpdater::rm_oldest_observation() { //remove one observation (without going under 80% of max) - if (is_model_built_ && space_bin_searcher_.is_initialized() && fitter_count_ >= fitter_max_count_ * .9f) { + if (is_model_built_ && space_bin_searcher_.is_initialized() && fitter_count_ >= fitter_max_count_ * .5f) { simple_fitter_.remove_observation(); space_bin_searcher_.rm_oldest_index(); fitter_count_--; @@ -327,7 +327,7 @@ double EyeModelUpdater::compute_reliability(cv::Mat &img, sef::Ellipse2D void EyeModelUpdater::render(cv::Mat &img, sef::Ellipse2D &el, std::vector &inlier_pts){ - if (simple_fitter_.eye){ + //if (simple_fitter_.eye){ const float displayscale = 1.0f; // Unproject the current 2D ellipse observation to a 3D disk @@ -348,79 +348,86 @@ void EyeModelUpdater::render(cv::Mat &img, sef::Ellipse2D &el, std::vect // 3D gaze vector singleeyefitter::EyeModelFitter::Circle c_end = curr_circle; c_end.centre = curr_circle.centre + (10.0)*curr_circle.normal; // Unit: mm - //std::cout << "x: " << c_end.centre.x() << std::endl; - //std::cout << "y: " << c_end.centre.y() << std::endl; - //std::cout << "z: " << c_end.centre.z() << std::endl; - - //std::cout << "eye center x: " << simple_fitter_.eye.centre[0] << std::endl; - //std::cout << "eye center y: " << simple_fitter_.eye.centre[1] << std::endl; - //std::cout << "eye center z: " << simple_fitter_.eye.centre[2] << std::endl; - - //std::cout << "radius: " << c_end.radius << std::endl; - - - //write coordinates to file - //std::ofstream myfile("C:\\Users\\O\\Documents\\Visual Studio 2013\\Projects\\EyeTrackerRealTime\\coordinates.txt"); - ////std::ofstream myfile; - ////myfile.open("C:\\Documents\\Osaka\\Research\\Presence 2017\\testcoordinates.txt", std::ios_base::app); - //myfile << "" << c_end.centre.x() << "," << c_end.centre.y() << "," << c_end.centre.z() - // << "," << simple_fitter_.eye.centre[0] << "," << simple_fitter_.eye.centre[1] << "," << simple_fitter_.eye.centre[2] << - // std::endl; - //myfile.close(); singleeyefitter::Ellipse2D e_end(sef::project(c_end, focal_length_)); cv::RotatedRect rr_end = eye_tracker::toImgCoord(singleeyefitter::toRotatedRect(e_end), img, displayscale); cv::line(img, cv::Point(rr_pupil.center), cv::Point(rr_end.center), cv::Vec3b(0, 255, 128), 2, CV_AA); } - } + //else if (curr_circle) { + // // 3D pupil + // singleeyefitter::Ellipse2D pupil_el(sef::project(curr_circle, focal_length_)); + // cv::RotatedRect rr_pupil = eye_tracker::toImgCoord(singleeyefitter::toRotatedRect(pupil_el), img, displayscale); + // cv::ellipse(img, rr_pupil, cv::Vec3b(0, 10, 248), 5, CV_AA); + // //cv::line(img, rr_eye.center, rr_pupil.center, cv::Vec3b(255, 128, 0), 1, CV_AA); + //} + //} } singleeyefitter::EyeModelFitter::Sphere EyeModelUpdater::eyeModelFilter( singleeyefitter::EyeModelFitter::Sphere eye, - std::vector &eyes, int filterLength) { + std::vector &eyes, + int filterLength, + bool ignoreNewEye, + singleeyefitter::EyeModelFitter::Sphere originalCalibratedEye) { + int max = filterLength; //max number of elements to average - double radiiAverage = 0; - singleeyefitter::EyeModelFitter::Sphere filteredEyeModel; - singleeyefitter::EyeModelFitter::Sphere eyeTemp(eye); - eyes.push_back(eyeTemp);//add the newest eye model to the vector - std::cout << "Adding x of : " + std::to_string(eyes[eyes.size()-1].centre(0)) << std::endl; - //std::cout << "raw radius: " << eyeTemp.radius << std::endl; - if (eyes.size() > max) {//remove oldest element if > max - eyes.erase(eyes.begin()); - } - //temp arrays for sorting - std::vector temp(eyes); - std::vector xs; - std::vector ys; - std::vector zs; - std::vector radii; - //add data to all arrays from eye spheres - for (int i = 0; i < temp.size(); i++) { - xs.push_back(eyes[i].centre[0]); - ys.push_back(eyes[i].centre[1]); - zs.push_back(eyes[i].centre[2]); - radii.push_back(eyes[i].radius); - radiiAverage += eyes[i].radius / temp.size(); - } + double radiiAverage = 0; + singleeyefitter::EyeModelFitter::Sphere filteredEyeModel; + singleeyefitter::EyeModelFitter::Sphere eyeTemp(eye); + float filterFactor = 3; - //sort each coordinate and radii - std::sort(xs.begin(), xs.begin() + xs.size()); - std::sort(ys.begin(), ys.begin() + ys.size()); - std::sort(zs.begin(), zs.begin() + zs.size()); - std::sort(radii.begin(), radii.begin() + radii.size()); - //for (int i = 0; i < radii.size(); i++) { - // std::cout << "radius " << i << ": " << radii[i] << std::endl; - //} - //set return sphere to median values - filteredEyeModel.centre[0] = xs[(int)xs.size() / 2]; - filteredEyeModel.centre[1] = ys[(int)ys.size() / 2]; - filteredEyeModel.centre[2] = zs[(int)zs.size() / 2]; - filteredEyeModel.radius = radiiAverage;// radii[(int)radii.size() / 2]; - //return median Sphere - std::cout << "Returning x of : " + std::to_string(filteredEyeModel.centre(0)) << std::endl; + //check to see if new eye model is way different than originals and ignore if so + if (ignoreNewEye == false && ( + std::abs(eye.centre.x() - originalCalibratedEye.centre.x()) > filterFactor || + std::abs(eye.centre.y() - originalCalibratedEye.centre.y()) > filterFactor || + std::abs(eye.centre.z() - originalCalibratedEye.centre.z()) > filterFactor)){ + ignoreNewEye = true; + } - return filteredEyeModel; + if (!ignoreNewEye) { + eyes.push_back(eyeTemp);//add the newest eye model to the vector + } + + if (eyes.size() > max) {//remove oldest element if > max + eyes.erase(eyes.begin()); + } + + //temp arrays for sorting + std::vector temp(eyes); + std::vector xs; + std::vector ys; + std::vector zs; + std::vector radii; + //add data to all arrays from eye spheres + for (int i = 0; i < temp.size(); i++) { + xs.push_back(eyes[i].centre[0]); + ys.push_back(eyes[i].centre[1]); + zs.push_back(eyes[i].centre[2]); + radii.push_back(eyes[i].radius); + radiiAverage += eyes[i].radius / temp.size(); + } + + //sort each coordinate and radii + std::sort(xs.begin(), xs.begin() + xs.size()); + std::sort(ys.begin(), ys.begin() + ys.size()); + std::sort(zs.begin(), zs.begin() + zs.size()); + std::sort(radii.begin(), radii.begin() + radii.size()); + + //set return sphere to median values + if (xs.size() > 0) { + filteredEyeModel.centre[0] = xs[(int)xs.size() / 2]; + filteredEyeModel.centre[1] = ys[(int)ys.size() / 2]; + filteredEyeModel.centre[2] = zs[(int)zs.size() / 2]; + filteredEyeModel.radius = radiiAverage;// radii[(int)radii.size() / 2]; + } + else { + filteredEyeModel.centre[0] = 0; + filteredEyeModel.centre[1] = 0; + filteredEyeModel.centre[2] = 0; + filteredEyeModel.radius = 0;// radii[(int)radii.size() / 2]; + } + return filteredEyeModel; } void EyeModelUpdater::reset(){