Permalink
Browse files

Updated SP2 version (copied EyeTab files across)

  • Loading branch information...
1 parent 0563d26 commit b9b4e22c45a72861b85241765c04531b582f51bf @errollw committed Mar 25, 2014
View
@@ -57,25 +57,47 @@ int main(int argc, const char** argv) {
// sets callback function for emergency stop, e.g. pulling out camera
vidInput.setEmergencyStopEvent(cam_id, NULL, StopEvent);
- // setup image files used in the capture process
- Mat captureFrame, grayscaleFrame, smallFrame;
-
// create a window to present the results
namedWindow("output", 1);
CvSize size = cvSize(vidInput.getWidth(cam_id), vidInput.getHeight(cam_id));
- // VideoInput library uses IplImage
+ // VideoInput library copies data into IplImage
IplImage* frame;
frame = cvCreateImage(size, 8, 3);
+
+ // setup image files used in the capture process
+ Mat captureFrame, grayscaleFrame, smallFrame;
- // main loop
- while(true) {
+ // ##################
+ // MAIN LOOP
+ // ##################
+ while(true) {
if(vidInput.isFrameNew(cam_id)) {
+ clock_t start = clock();
+
+ // copy data into the IplImage frame
vidInput.getPixels(cam_id, (unsigned char *)frame->imageData);
- cv::Mat image(frame);
- cv::imshow("output", image);
+ // make a Mat of the IplImage
+ Mat captureFrame(frame);
+
+ // flip image for reverse-portrait orientation
+ flip(captureFrame, captureFrame, -1);
+
+ // convert captured image to equalized gray scale
+ cvtColor(captureFrame, grayscaleFrame, CV_BGR2GRAY);
+ equalizeHist(grayscaleFrame, grayscaleFrame);
+
+ track_gaze(captureFrame, grayscaleFrame);
+
+ // show calculated FPS (two draw functions to simulate text shadow)
+ String fps_string = to_string(int(1 / ( ((float)clock()-start) / CLOCKS_PER_SEC ))) + " FPS";
+ putText(captureFrame, fps_string, Point2i(11, 21), FONT_HERSHEY_SIMPLEX, 0.5, BLACK);
+ putText(captureFrame, fps_string, Point2i(10, 20), FONT_HERSHEY_SIMPLEX, 0.5, WHITE);
+
+ // show the output
+ imshow("output", captureFrame);
}
char c = cv::waitKey(5);
@@ -0,0 +1,64 @@
+#include "stdafx.h"
+
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+#include <opencv2/photo/photo.hpp>
+
+#include <iostream> // cout
+#include <stdio.h>
+#include <time.h> // clock_t, clock, CLOCKS_PER_SEC
+
+using namespace std;
+using namespace cv;
+
+const Mat ERASE_SPEC_KERNEL = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
+
+void erase_specular(Mat& eye_bgr) {
+
+ // Rather arbitrary decision on how large a specularity may be
+ int max_spec_contour_area = (eye_bgr.size().width + eye_bgr.size().height)/2;
+
+ // Convert BGR coarse ROI to gray, blur it slightly to reduce noise
+ Mat eye_grey;
+ cvtColor(eye_bgr, eye_grey, CV_BGR2GRAY);
+ GaussianBlur(eye_grey, eye_grey, Size(5,5), 0);
+
+ // Close to suppress eyelashes
+ morphologyEx(eye_grey, eye_grey, MORPH_CLOSE, ERASE_SPEC_KERNEL);
+
+ // Compute thresh value (using of highest and lowest pixel values)
+ double m, M; // m(in) and (M)ax values in image
+ minMaxLoc(eye_grey, &m, &M, NULL, NULL);
+ double thresh = (m + M) * 3/4;
+
+ // Threshold the image
+ Mat eye_thresh;
+ threshold(eye_grey, eye_thresh, thresh, 255, THRESH_BINARY);
+
+ // Find all contours in threshed image (possible specularities)
+ vector< vector<Point> > all_contours, contours;
+ findContours(eye_thresh, all_contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
+
+ // Only save small ones (assumed to be spec.s)
+ for (int i=0; i<all_contours.size(); i++){
+ if( contourArea(all_contours[i]) < max_spec_contour_area )
+ contours.push_back(all_contours[i]);
+ }
+
+ // Draw the contours into an inpaint mask
+ Mat small_contours_mask = Mat::zeros(eye_grey.size(), eye_grey.type());
+ drawContours(small_contours_mask, contours, -1, 255, -1);
+ dilate(small_contours_mask, small_contours_mask, ERASE_SPEC_KERNEL);
+
+ // Inpaint within contour bounds
+ inpaint(eye_bgr, small_contours_mask, eye_bgr, 2, INPAINT_TELEA);
+}
+
+void test_erase_specular() {
+
+ // Load test image and convert to gray
+ Mat eye_bgr, eye_grey, eye_grey_small;
+ eye_bgr = imread("images\\erroll1_l.png", CV_LOAD_IMAGE_COLOR);
+
+ erase_specular(eye_bgr);
+}
View
@@ -0,0 +1,144 @@
+#include "stdafx.h"
+
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+
+#include <stdio.h>
+#include <time.h> // clock_t, clock, CLOCKS_PER_SEC
+
+using namespace std;
+using namespace cv;
+
+// GLOBAL VARIABLES
+
+const int fastSize_width = 40;
+const int DARKNESS_WEIGHT_SCALE = 100;
+
+Mat get_centermap(Mat& eye_grey) {
+
+ // Calculate image gradients
+ Mat grad_x, grad_y;
+ Sobel(eye_grey, grad_x, CV_32F, 1, 0, 5);
+ Sobel(eye_grey, grad_y, CV_32F, 0, 1, 5);
+
+ // Get magnitudes of gradients, and calculate thresh
+ Mat mags;
+ Scalar mean, stddev;
+ magnitude(grad_x, grad_y, mags);
+ meanStdDev(mags, mean, stddev);
+ int mag_thresh = stddev.val[0] / 2 + mean.val[0];
+
+ // Threshold out gradients with mags which are too low
+ grad_x.setTo(0, mags < mag_thresh);
+ grad_y.setTo(0, mags < mag_thresh);
+
+ // Normalize gradients
+ grad_x = grad_x / (mags+1); // (+1 is hack to guard against div by 0)
+ grad_y = grad_y / (mags+1);
+
+ // Initialize 1d vectors of x and y indicies of Mat
+ vector<int> x_inds_vec, y_inds_vec;
+ for(int i = 0; i < eye_grey.size().width; i++)
+ x_inds_vec.push_back(i);
+ for(int i = 0; i < eye_grey.size().height; i++)
+ y_inds_vec.push_back(i);
+
+ // Repeat vectors to form indices Mats
+ Mat x_inds(x_inds_vec), y_inds(y_inds_vec);
+ x_inds = repeat(x_inds.t(), eye_grey.size().height, 1);
+ y_inds = repeat(y_inds, 1, eye_grey.size().width);
+ x_inds.convertTo(x_inds, CV_32F); // Has to be float for arith. with dx, dy
+ y_inds.convertTo(y_inds, CV_32F);
+
+ // Set-up Mats for main loop
+ Mat ones = Mat::ones(x_inds.rows, x_inds.cols, CV_32F); // for re-use with creating normalized disp. vecs
+ Mat darkness_weights = (255 - eye_grey) / DARKNESS_WEIGHT_SCALE;
+ Mat accumulator = Mat::zeros(eye_grey.size(), CV_32F);
+ Mat diffs, dx, dy;
+
+ // Loop over all pixels, testing each as a possible center
+ for(int y = 0; y < eye_grey.rows; ++y) {
+
+ // Get pointers for each row
+ float* grd_x_p = grad_x.ptr<float>(y);
+ float* grd_y_p = grad_y.ptr<float>(y);
+ uchar* d_w_p = darkness_weights.ptr<uchar>(y);
+
+ for(int x = 0; x < eye_grey.cols; ++x) {
+
+ // Deref and increment pointers
+ float grad_x_val = *grd_x_p++;
+ float grad_y_val = *grd_y_p++;
+
+ // Skip if no gradient
+ if(grad_x_val == 0 && grad_y_val == 0)
+ continue;
+
+ dx = ones * x - x_inds;
+ dy = ones * y - y_inds;
+
+ magnitude(dx, dy, mags);
+ dx = dx / mags;
+ dy = dy / mags;
+
+ diffs = (dx * grad_x_val + dy * grad_y_val) * *d_w_p++;
+ diffs.setTo(0, diffs < 0);
+
+ accumulator = accumulator + diffs;
+ }
+ }
+
+ // Normalize and convert accumulator
+ accumulator = accumulator / eye_grey.total();
+ normalize(accumulator, accumulator, 0, 255, NORM_MINMAX);
+ accumulator.convertTo(accumulator, CV_8U);
+
+ return accumulator;
+}
+
+Point find_eye_center(Mat& eye_bgr){
+
+ // Convert BGR coarse ROI to gray
+ Mat eye_grey, eye_grey_small;
+ cvtColor(eye_bgr, eye_grey, CV_BGR2GRAY);
+
+ // Resize the image to a constant fast size
+ // TODO: prevent upscaling
+ float scale = fastSize_width / (float)eye_grey.size().width;
+ resize(eye_grey, eye_grey_small, Size(0,0), scale, scale);
+ GaussianBlur(eye_grey_small,eye_grey_small,Size(5,5),0);
+
+ // Create centermap
+ Mat centermap = get_centermap(eye_grey_small);
+
+ // Find position of max value in small-size centermap
+ Point maxLoc;
+ minMaxLoc(centermap, NULL, NULL, NULL, &maxLoc);
+
+ // Return re-scaled center to full size
+ return maxLoc * (1/scale);
+}
+
+void test_centermap() {
+
+ // Load test image and convert to gray
+ Mat eye_bgr, eye_grey, eye_grey_small;
+ eye_bgr = imread("images\\phil1_l.png", CV_LOAD_IMAGE_COLOR);
+
+ // Find eye-center 10 times, and find equivalent FPS
+ int reps = 10;
+ clock_t start = clock();
+ Point maxLoc;
+ for (int i = 0; i < 10; i++)
+ maxLoc = find_eye_center(eye_bgr);
+
+ float t = ( ((float)clock()-start) / CLOCKS_PER_SEC );
+ printf ("Find eye-center: %f FPS\n", 1/(t/reps));
+
+ // Show output
+ circle(eye_bgr, maxLoc , 4, Scalar(0, 0, 255), -1);
+ namedWindow("centermap");
+ imshow("centermap", eye_bgr);
+
+ waitKey();
+}
Oops, something went wrong.

0 comments on commit b9b4e22

Please sign in to comment.