cv::Point findEyeCenter(cv::Mat face, cv::Rect eye, std::string debugWindow) { cv::Mat eyeROIUnscaled = face(eye); cv::Mat eyeROI; if(GBStatus) { cv::GaussianBlur( face, face, cv::Size(3,3), 0, 0, cv::BORDER_DEFAULT ); } if(debugL1 && GBStatus && (debugWindow == costado)) { std::string gaussianBlur_window = "GaussianBlur"; cv::namedWindow(gaussianBlur_window,CV_WINDOW_NORMAL); cv::moveWindow(gaussianBlur_window, gaussBlurx, gaussBlury); imshow(gaussianBlur_window,face); } scaleToFastSize(eyeROIUnscaled, eyeROI); // draw eye region rectangle(face,eye,1234); //-- Find the gradient cv::Mat gradientX; cv::Mat gradientY; if(sobel) { cv::Sobel( eyeROIUnscaled, gradientX, ddepth, 1, 0, 3, scale, delta, cv::BORDER_DEFAULT ); // cv::Sobel( (eyeROI.t()).t(), gradientY, ddepth, 0, 1, 3, scale, delta, cv::BORDER_DEFAULT ); cv::Sobel (eyeROIUnscaled, gradientY, ddepth, 0, 1, 3, scale, delta, cv::BORDER_DEFAULT ); } if(maxgradient) { gradientX = computeMatXGradient(eyeROI); gradientY = computeMatXGradient(eyeROI.t()).t(); } calculos("Gradient Y",gradientY); cv::Mat abs_grad_x, abs_grad_y; cv::convertScaleAbs( gradientX, abs_grad_x ); cv::convertScaleAbs( gradientY, abs_grad_y ); calculos("Valor absoluto Gradient Y",abs_grad_y); // cv::Mat gradientY = computeMatXGradient(eyeROI); //-- Normalize and threshold the gradient // compute all the magnitudes cv::Mat mags; if(debugL6) { mags = matrixMagnitude(gradientX, gradientY); } else { addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, mags ); } calculos("Sobel",mags); //compute the threshold double gradientThresh = computeDynamicThreshold(mags, kGradientThreshold); //double gradientThresh = kGradientThreshold; //double gradientThresh = 0; //normalize if(debugL1 && (debugWindow == costado)) { /////////// std::string eyeROI_window = debugWindow; /////////// cv::namedWindow(eyeROI_window,CV_WINDOW_NORMAL); /////////// cv::moveWindow(eyeROI_window, 640, 350); /////////// imshow(eyeROI_window,eyeROI); std::string Sobel_window = "Salida del Filtro"; cv::namedWindow(Sobel_window,CV_WINDOW_NORMAL); cv::moveWindow(Sobel_window, sobelx, sobely); imshow(Sobel_window,mags); } for (int y = 0; y < eyeROI.rows; ++y) { double *Xr = gradientX.ptr<double>(y), *Yr = gradientY.ptr<double>(y); const double *Mr = mags.ptr<double>(y); for (int x = 0; x < eyeROI.cols; ++x) { double gX = Xr[x], gY = Yr[x]; double magnitude = Mr[x]; if (magnitude > gradientThresh) { Xr[x] = gX/magnitude; Yr[x] = gY/magnitude; } else { Xr[x] = 0.0; Yr[x] = 0.0; } } } if(debugL4) { // imshow(debugWindow,gradientX); } //-- Create a blurred and inverted image for weighting cv::Mat weight; GaussianBlur( eyeROI, weight, cv::Size( kWeightBlurSize, kWeightBlurSize ), 0, 0 ); for (int y = 0; y < weight.rows; ++y) { unsigned char *row = weight.ptr<unsigned char>(y); for (int x = 0; x < weight.cols; ++x) { row[x] = (255 - row[x]); } } if(debugL4) { imshow(debugWindow,weight); } //-- Run the algorithm! cv::Mat outSum = cv::Mat::zeros(eyeROI.rows,eyeROI.cols,CV_64F); // for each possible center // printf("Eye Size: %ix%i\n",outSum.cols,outSum.rows); if(debugL4) { imshow("outSum",outSum); } for (int y = 0; y < weight.rows; ++y) { const unsigned char *Wr = weight.ptr<unsigned char>(y); const double *Xr = gradientX.ptr<double>(y), *Yr = gradientY.ptr<double>(y); for (int x = 0; x < weight.cols; ++x) { double gX = Xr[x], gY = Yr[x]; if (gX == 0.0 && gY == 0.0) { continue; } testPossibleCentersFormula(x, y, Wr[x], gX, gY, outSum); } } // scale all the values down, basically averaging them double numGradients = (weight.rows*weight.cols); cv::Mat out; outSum.convertTo(out, CV_32F,1.0/numGradients); if(debugL4) { imshow(debugWindow,outSum); } //-- Find the maximum point cv::Point maxP; double maxVal; cv::minMaxLoc(out, NULL,&maxVal,NULL,&maxP); //-- Flood fill the edges if(kEnablePostProcess) { cv::Mat floodClone; //double floodThresh = computeDynamicThreshold(out, 1.5); double floodThresh = maxVal * kPostProcessThreshold; cv::threshold(out, floodClone, floodThresh, 0.0f, cv::THRESH_TOZERO); if(kPlotVectorField) { //plotVecField(gradientX, gradientY, floodClone); imwrite("eyeFrame.png",eyeROIUnscaled); } cv::Mat mask = floodKillEdges(floodClone); if(debugL4) { imshow(debugWindow + " Mask",mask); // imshow(debugWindow,out); //redo max; } cv::minMaxLoc(out, NULL,&maxVal,NULL,&maxP,mask); } cv::circle(eyeROI, maxP, 3,cv::Scalar(0,0,255)); if(debugL1 && (debugWindow == costado)) { calculos("EyeROI", eyeROI); std::string eyeROI_window = debugWindow; cv::namedWindow(eyeROI_window,CV_WINDOW_NORMAL); cv::moveWindow(eyeROI_window, 640, 350); imshow(eyeROI_window,eyeROI); int c = cv::waitKey(10); if( (char)c == 'g' ) { imwrite("ojo.png",eyeROIUnscaled); } } return unscalePoint(maxP,eye); }
cv::Point findEyeCenter(cv::Mat face, cv::Rect eye, std::string debugWindow) { cv::Mat eyeROIUnscaled = face(eye); cv::Mat eyeROI; scaleToFastSize(eyeROIUnscaled, eyeROI); // draw eye region rectangle(face,eye,1234); //-- Find the gradient cv::Mat gradientX = computeMatXGradient(eyeROI); cv::Mat gradientY = computeMatXGradient(eyeROI.t()).t(); //-- Normalize and threshold the gradient // compute all the magnitudes cv::Mat mags = matrixMagnitude(gradientX, gradientY); //compute the threshold double gradientThresh = computeDynamicThreshold(mags, kGradientThreshold); //double gradientThresh = kGradientThreshold; //double gradientThresh = 0; //normalize for (int y = 0; y < eyeROI.rows; ++y) { double *Xr = gradientX.ptr<double>(y), *Yr = gradientY.ptr<double>(y); const double *Mr = mags.ptr<double>(y); for (int x = 0; x < eyeROI.cols; ++x) { double gX = Xr[x], gY = Yr[x]; double magnitude = Mr[x]; if (magnitude > gradientThresh) { Xr[x] = gX/magnitude; Yr[x] = gY/magnitude; } else { Xr[x] = 0.0; Yr[x] = 0.0; } } } // imshow(debugWindow,gradientX); //-- Create a blurred and inverted image for weighting cv::Mat weight; GaussianBlur( eyeROI, weight, cv::Size( kWeightBlurSize, kWeightBlurSize ), 0, 0 ); for (int y = 0; y < weight.rows; ++y) { unsigned char *row = weight.ptr<unsigned char>(y); for (int x = 0; x < weight.cols; ++x) { row[x] = (255 - row[x]); } } //imshow(debugWindow,weight); //-- Run the algorithm! cv::Mat outSum = cv::Mat::zeros(eyeROI.rows,eyeROI.cols,CV_64F); // for each possible center // printf("Eye Size: %ix%i\n",outSum.cols,outSum.rows); for (int y = 0; y < weight.rows; ++y) { const unsigned char *Wr = weight.ptr<unsigned char>(y); const double *Xr = gradientX.ptr<double>(y), *Yr = gradientY.ptr<double>(y); for (int x = 0; x < weight.cols; ++x) { double gX = Xr[x], gY = Yr[x]; if (gX == 0.0 && gY == 0.0) { continue; } testPossibleCentersFormula(x, y, Wr[x], gX, gY, outSum); } } // scale all the values down, basically averaging them double numGradients = (weight.rows*weight.cols); cv::Mat out; outSum.convertTo(out, CV_32F,1.0/numGradients); //imshow(debugWindow,out); //-- Find the maximum point cv::Point maxP; double maxVal; cv::minMaxLoc(out, NULL,&maxVal,NULL,&maxP); //-- Flood fill the edges if(kEnablePostProcess) { cv::Mat floodClone; //double floodThresh = computeDynamicThreshold(out, 1.5); double floodThresh = maxVal * kPostProcessThreshold; cv::threshold(out, floodClone, floodThresh, 0.0f, cv::THRESH_TOZERO); if(kPlotVectorField) { //plotVecField(gradientX, gradientY, floodClone); imwrite("eyeFrame.png",eyeROIUnscaled); } cv::Mat mask = floodKillEdges(floodClone); //imshow(debugWindow + " Mask",mask); //imshow(debugWindow,out); // redo max cv::minMaxLoc(out, NULL,&maxVal,NULL,&maxP,mask); } return unscalePoint(maxP,eye); }
cv::Point EyeTracker::computePupilLocation(cv::Mat eye) { cv::Mat x_gradient = computeMaxGradient(eye); cv::Mat y_gradient = computeMaxGradient(eye.t()).t(); cv::Mat magnitude = computeMagnitudes(x_gradient, y_gradient); double gradient_threshold = computeDynamicThreshold(magnitude, 50.0); resizeAndRender(magnitude, "sample_eye_gradient_mag"); DEBUG("Gradient threshold: " << gradient_threshold); for (int y = 0; y < eye.rows; ++y) { double* x_row = x_gradient.ptr<double>(y); double* y_row = y_gradient.ptr<double>(y); const double* mag_row = magnitude.ptr<double>(y); for (int x = 0; x < eye.cols; ++x) { double gX = x_row[x]; double gY = y_row[x]; double m = mag_row[x]; if (m > gradient_threshold) { x_row[x] = gX / m; y_row[x] = gY / m; } else { x_row[x] = 0; y_row[x] = 0; } } } resizeAndRender(x_gradient, "sample_eye_gradient_x"); resizeAndRender(y_gradient, "sample_eye_gradient_y"); cv::Mat weight; cv::GaussianBlur(eye, weight, cv::Size(5, 5), 0, 0); for (int y = 0; y < weight.rows; ++y) { unsigned char* row = weight.ptr<unsigned char>(y); for (int x = 0; x < weight.cols; ++x) { row[x] = (255 - row[x]); } } resizeAndRender(weight, "sample_eye_weight"); cv::Mat out_sum = cv::Mat::zeros(eye.rows, eye.cols, CV_64F); for (int y = 0; y < weight.rows; ++y) { const double* Xr = x_gradient.ptr<double>(y); const double* Yr = y_gradient.ptr<double>(y); for (int x = 0; x < weight.cols; ++x) { double gX = Xr[x]; double gY = Yr[x]; if (gX == 0.0 && gY == 0.0) { continue; } test_center(x, y, weight, gX, gY, out_sum); } } double gradients_num = weight.rows * weight.cols; cv::Mat out; out_sum.convertTo(out, CV_32F, 1.0 / gradients_num); cv::Point max_point; double max_value; cv::minMaxLoc(out, NULL, &max_value, NULL, &max_point); cv::Mat flood_clone; double flood_thresh = max_value * 0.97; cv::threshold(out, flood_clone, flood_thresh, 0.0f, cv::THRESH_TOZERO); cv::Mat mask = floodKillEdges(flood_clone); cv::minMaxLoc(out, NULL, &max_value, NULL, &max_point, mask); resizeAndRender(mask, "sample_eye_mask"); resizeAndRender(out, "sample_eye_possible_centers"); return max_point; }