mirror of
https://github.com/YutaItoh/3D-Eye-Tracker.git
synced 2025-11-04 15:39:41 +08:00
Optimizations to drift correction and model filter
This commit is contained in:
parent
2e48bedf55
commit
45eeed9306
@ -226,7 +226,7 @@ int EyeModelUpdater::get_current_count() {
|
|||||||
*/
|
*/
|
||||||
void EyeModelUpdater::rm_oldest_observation() {
|
void EyeModelUpdater::rm_oldest_observation() {
|
||||||
//remove one observation (without going under 80% of max)
|
//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();
|
simple_fitter_.remove_observation();
|
||||||
space_bin_searcher_.rm_oldest_index();
|
space_bin_searcher_.rm_oldest_index();
|
||||||
fitter_count_--;
|
fitter_count_--;
|
||||||
@ -327,7 +327,7 @@ double EyeModelUpdater::compute_reliability(cv::Mat &img, sef::Ellipse2D<double>
|
|||||||
|
|
||||||
void EyeModelUpdater::render(cv::Mat &img, sef::Ellipse2D<double> &el, std::vector<cv::Point2f> &inlier_pts){
|
void EyeModelUpdater::render(cv::Mat &img, sef::Ellipse2D<double> &el, std::vector<cv::Point2f> &inlier_pts){
|
||||||
|
|
||||||
if (simple_fitter_.eye){
|
//if (simple_fitter_.eye){
|
||||||
const float displayscale = 1.0f;
|
const float displayscale = 1.0f;
|
||||||
|
|
||||||
// Unproject the current 2D ellipse observation to a 3D disk
|
// Unproject the current 2D ellipse observation to a 3D disk
|
||||||
@ -348,79 +348,86 @@ void EyeModelUpdater::render(cv::Mat &img, sef::Ellipse2D<double> &el, std::vect
|
|||||||
// 3D gaze vector
|
// 3D gaze vector
|
||||||
singleeyefitter::EyeModelFitter::Circle c_end = curr_circle;
|
singleeyefitter::EyeModelFitter::Circle c_end = curr_circle;
|
||||||
c_end.centre = curr_circle.centre + (10.0)*curr_circle.normal; // Unit: mm
|
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<double> e_end(sef::project(c_end, focal_length_));
|
singleeyefitter::Ellipse2D<double> e_end(sef::project(c_end, focal_length_));
|
||||||
cv::RotatedRect rr_end = eye_tracker::toImgCoord(singleeyefitter::toRotatedRect(e_end), img, displayscale);
|
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);
|
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<double> 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 EyeModelUpdater::eyeModelFilter(
|
||||||
singleeyefitter::EyeModelFitter::Sphere eye,
|
singleeyefitter::EyeModelFitter::Sphere eye,
|
||||||
std::vector<singleeyefitter::EyeModelFitter::Sphere> &eyes, int filterLength) {
|
std::vector<singleeyefitter::EyeModelFitter::Sphere> &eyes,
|
||||||
|
int filterLength,
|
||||||
|
bool ignoreNewEye,
|
||||||
|
singleeyefitter::EyeModelFitter::Sphere originalCalibratedEye) {
|
||||||
|
|
||||||
int max = filterLength; //max number of elements to average
|
int max = filterLength; //max number of elements to average
|
||||||
double radiiAverage = 0;
|
double radiiAverage = 0;
|
||||||
singleeyefitter::EyeModelFitter::Sphere filteredEyeModel;
|
singleeyefitter::EyeModelFitter::Sphere filteredEyeModel;
|
||||||
singleeyefitter::EyeModelFitter::Sphere eyeTemp(eye);
|
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<singleeyefitter::EyeModelFitter::Sphere> temp(eyes);
|
|
||||||
std::vector<double> xs;
|
|
||||||
std::vector<double> ys;
|
|
||||||
std::vector<double> zs;
|
|
||||||
std::vector<double> 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
float filterFactor = 3;
|
||||||
|
|
||||||
//sort each coordinate and radii
|
//check to see if new eye model is way different than originals and ignore if so
|
||||||
std::sort(xs.begin(), xs.begin() + xs.size());
|
if (ignoreNewEye == false && (
|
||||||
std::sort(ys.begin(), ys.begin() + ys.size());
|
std::abs(eye.centre.x() - originalCalibratedEye.centre.x()) > filterFactor ||
|
||||||
std::sort(zs.begin(), zs.begin() + zs.size());
|
std::abs(eye.centre.y() - originalCalibratedEye.centre.y()) > filterFactor ||
|
||||||
std::sort(radii.begin(), radii.begin() + radii.size());
|
std::abs(eye.centre.z() - originalCalibratedEye.centre.z()) > filterFactor)){
|
||||||
//for (int i = 0; i < radii.size(); i++) {
|
ignoreNewEye = true;
|
||||||
// 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;
|
|
||||||
|
|
||||||
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<singleeyefitter::EyeModelFitter::Sphere> temp(eyes);
|
||||||
|
std::vector<double> xs;
|
||||||
|
std::vector<double> ys;
|
||||||
|
std::vector<double> zs;
|
||||||
|
std::vector<double> 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(){
|
void EyeModelUpdater::reset(){
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user