track_eye.cpp ( File view )

  • By marque 2014-03-29
  • View(s):51
  • Download(s):6
  • Point(s): 2
			#include <iostream>

#include "constants.h"
#include "track_eye.h"

// Histogram Equalize seperately for the left and right sides of the face.
void equalizeLeftAndRightHalves(cv::Mat &faceImg)
{

    // It is common that there is stronger light from one half of the face than the other. In that case,
    // if you simply did histogram equalization on the whole face then it would make one half dark and
    // one half bright. So we will do histogram equalization separately on each face half, so they will
    // both look similar on average. But this would cause a sharp edge in the middle of the face, because
    // the left half and right half would be suddenly different. So we also histogram equalize the whole
    // image, and in the middle part we blend the 3 images together for a smooth brightness transition.

    int w = faceImg.cols;
    int h = faceImg.rows;

    // 1) First, equalize the whole face.
    cv::Mat wholeFace;
    equalizeHist(faceImg, wholeFace);

    // 2) Equalize the left half and the right half of the face separately.
    int midX = w/2;
    cv::Mat leftSide = faceImg(cv::Rect(0,0, midX,h));
    cv::Mat rightSide = faceImg(cv::Rect(midX,0, w-midX,h));
    equalizeHist(leftSide, leftSide);
    equalizeHist(rightSide, rightSide);

    // 3) Combine the left half and right half and whole face together, so that it has a smooth transition.
    for (int y=0; y<h; y++) {

        for (int x=0; x<w; x++) {

            int v;
            if (x < w/4) {
          // Left 25%: just use the left face.
                v = leftSide.at<uchar>(y,x);
            
}
            else if (x < w*2/4) {
   // Mid-left 25%: blend the left face & whole face.
                int lv = leftSide.at<uchar>(y,x);
                int wv = wholeFace.at<uchar>(y,x);
                // Blend more of the whole face as it moves further right along the face.
                float f = (x - w*1/4) / (float)(w*0.25f);
                v = cvRound((1.0f - f) * lv + (f) * wv);
            
}
            else if (x < w*3/4) {
   // Mid-right 25%: blend the right face & whole face.
                int rv = rightSide.at<uchar>(y,x-midX);
                int wv = wholeFace.at<uchar>(y,x);
                // Blend more of the right-side face as it moves further right along the face.
                float f = (x - w*2/4) / (float)(w*0.25f);
                v = cvRound((1.0f - f) * wv + (f) * rv);
            
}
            else {
                  // Right 25%: just use the right face.
                v = rightSide.at<uchar>(y,x-midX);
            
}
            faceImg.at<uchar>(y,x) = v;
        
}// end x loop
    
}//end y loop

}

static bool getIrisArea(cv::Mat faceROI, cv::Rect eyeRegion, cv::Rect& maxContourRect)
{

    // equalize light effect
	//equalizeLeftAndRightHalves(faceROI);
    cv::Mat eyeROI = faceROI(eyeRegion);
	cv::Mat eyeBinInv;

    double minVal = 0;
    minMaxLoc(eyeROI, &minVal, NULL, NULL, NULL);

    threshold(eyeROI, eyeBinInv, minVal + 10, 255, cv::THRESH_BINARY_INV);

    //(Optional) remove noise (small areas of white pixels)
    // cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3), cv::Point(1, 1));
    // erode(eyeBinInv, eyeBinInv, element);
    // dilate(eyeBinInv, eyeBinInv, element);

    std::vector<cv::Vec4i> hierarchy;
    std::vector< std::vector <cv::Point2i> > contours;

	findContours(eyeBinInv, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

    //find contour with max area
    int maxArea = 0;

	for (unsigned int i=0; i<contours.size(); i++)
    {

        int area = contourArea(contours[i]);
        cv::Rect rect = boundingRect(contours[i]);
        double squareKoef = ((double) rect.width)/rect.height;

        //check if contour is like square (shape)
#define SQUARE_KOEF 1.5
        if (area>maxArea && squareKoef < SQUARE_KOEF && squareKoef > 1.0/SQUARE_KOEF)
        {

            maxArea = area;
            maxContourRect = rect;
        
}
    
}
	// std::cout << "Max Area" << maxArea << std::endl; 
	return (maxArea > min_iris_area);

}

void trackEyes(cv::Mat frame_gray, cv::Rect face, cv::Point& rightPupil, cv::Point& leftPupil ) 
{

    cv::Mat faceROI = frame_gray(face);
    cv::Scalar eyeColor = CV_RGB(255,0,0); 

	if (kSmoothFaceImage) {

       double sigma = kSmoothFaceFactor * face.width;
       GaussianBlur( faceROI, faceROI, cv::Size( 0, 0 ), sigma);
    
}
    
	//-- Find eye regions and draw them
    int eye_region_width = face.width * (kEyePercentWidth/100.0);
    int eye_region_height = face.width * (kEyePercentHeight/100.0);
    int eye_region_top = face.height * (kEyePercentTop/100.0);
    cv::Rect leftEyeRegion(face.width* (kEyePercentSide/100.0),
                           eye_region_top,eye_region_width,eye_region_height);
    cv::Rect rightEyeRegion(face.width - eye_region_width - face.width*(kEyePercentSide/100.0),
                          eye_region_top,eye_region_width,eye_region_height);

	cv::Rect maxContourRect;

	if (true == getIrisArea(faceROI, leftEyeRegion, maxContourRect) )
    {

        cv::Rect leftEyeRect = cv::Rect(maxContourRect.x-maxContourRect.width, maxContourRect.y-maxContourRect.height, maxContourRect.width*3, maxContourRect.height*3);

		leftEyeRect.x += leftEyeRegion.x;
		leftEyeRect.y += leftEyeRegion.y;

        leftPupil = cv::Point(leftEyeRect.x + leftEyeRect.width/2, leftEyeRect.y + leftEyeRect.height/2);

        //rectangle(faceROI, leftEyeRect, 1234);

		circle(faceROI, leftPupil, 6, eyeColor, 1, CV_AA);
	
} else {

		leftPupil.x = leftPupil.y = -1;
	
}

	if (true == getIrisArea(faceROI, rightEyeRegion, maxContourRect) )
    {

        cv::Rect rightEyeRect = cv::Rect(maxContourRect.x-maxContourRect.width, maxContourRect.y-maxContourRect.height, maxContourRect.width*3, maxContourRect.height*3);

		rightEyeRect.x += rightEyeRegion.x;
		rightEyeRect.y += rightEyeRegion.y;

        rightPupil = cv::Point(rightEyeRect.x + rightEyeRect.width/2, rightEyeRect.y + rightEyeRect.height/2);

        //rectangle(faceROI, rightEyeRect, 1234);

		circle(faceROI, rightPupil, 6, eyeColor, 1, CV_AA);
	
} else {

		rightPupil.x = rightPupil.y = -1;
	
}

	rectangle(faceROI, leftEyeRegion, 1234);
    rectangle(faceROI, rightEyeRegion, 1234);
    imshow(face_window_name, faceROI);

}
			
...
Expand> <Close

Want complete source code? Download it here

Point(s): 2

Download
0 lines left, continue to read
Sponsored links

File list

Tips: You can preview the content of files by clicking file names^_^
Name Size Date
constants.h685.00 B2014-03-23 00:51
eye_track.sln879.00 B2014-01-12 12:47
eye_track.vcxproj5.52 kB2014-03-22 23:39
eye_track.vcxproj.filters1.49 kB2014-03-22 23:39
main.cpp2.52 kB2014-03-23 01:09
OPENCV_DEBUG.props883.00 B2014-01-14 18:35
OPENCV_RELEASE.props872.00 B2014-01-14 18:36
01.97 kB
haarcascade_frontalface_alt.xml923.86 kB2014-01-12 12:58
haarcascade_frontalface_alt_tree.xml3.48 MB2013-11-13 15:14
lbpcascade_frontalface.xml50.64 kB2013-11-13 15:14
track_eye.cpp6.28 kB2014-03-23 01:22
track_eye.h267.00 B2014-03-22 23:51
...
Sponsored links

track_eye.cpp (550.50 kB)

Need 2 point
Your Point(s)

Your Point isn't enough.

Get point immediately by PayPal

More(Debit card / Credit card / PayPal Credit / Online Banking)

Submit your source codes. Get more point

LOGIN

Don't have an account? Register now
Need any help?
Mail to: support@codeforge.com

切换到中文版?

CodeForge Chinese Version
CodeForge English Version

Where are you going?

^_^"Oops ...

Sorry!This guy is mysterious, its blog hasn't been opened, try another, please!
OK

Warm tip!

CodeForge to FavoriteFavorite by Ctrl+D