-2

I am developing an android application where I need to detect the blinking of eyes. So far I have been able to detect the face and eyes using OpenCV. But now I need to check if the eyes are open or close. I read somewhere that one of the ways I can do that is by measuring the pixel intensities (grey levels). But it was not properly explained as in how to do that step by step. I am actually new to OpenCV. So can anyone please help me how can I do that. It is really very important.

Here is my onCameraFrame method:

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {

    mRgba = inputFrame.rgba();
    mGray = inputFrame.gray();

    if (mAbsoluteFaceSize == 0) {
        int height = mGray.rows();
        if (Math.round(height * mRelativeFaceSize) > 0) {
            mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize);
        }
    }

    if (mZoomWindow == null || mZoomWindow2 == null)
       CreateAuxiliaryMats();

    MatOfRect faces = new MatOfRect();

        if (mJavaDetector != null)
            mJavaDetector.detectMultiScale(mGray, faces, 1.1, 2,
                    2, // TODO: objdetect.CV_HAAR_SCALE_IMAGE
                    new Size(mAbsoluteFaceSize, mAbsoluteFaceSize),
                    new Size());

    Rect[] facesArray = faces.toArray();
    for (int i = 0; i < facesArray.length; i++) {
        Core.rectangle(mRgba, facesArray[i].tl(), facesArray[i].br(),
                FACE_RECT_COLOR, 2);
        xCenter = (facesArray[i].x + facesArray[i].width + facesArray[i].x) / 2;
        yCenter = (facesArray[i].y + facesArray[i].y + facesArray[i].height) / 2;
        Point center = new Point(xCenter, yCenter);

        Rect r = facesArray[i];
        // compute the eye area
        Rect eyearea = new Rect(r.x + r.width / 20,
                (int) (r.y + (r.height / 20)), r.width - 2 * r.width / 20,
                (int) (r.height / 9.0));

        // split it
        Rect eyearea_right = new Rect(r.x + r.width / 6,
                (int) (r.y + (r.height / 4)),
                (r.width - 2 * r.width / 16) / 3, (int) (r.height / 4.0));
        Rect eyearea_left = new Rect(r.x + r.width / 11
                + (r.width - 2 * r.width / 16) / 2,
                (int) (r.y + (r.height / 4)),
                (r.width - 2 * r.width / 16) / 3, (int) (r.height / 4.0));
        // draw the area - mGray is working grayscale mat, if you want to
        // see area in rgb preview, change mGray to mRgba
        Core.rectangle(mRgba, eyearea_left.tl(), eyearea_left.br(),
                new Scalar(255, 0, 0, 255), 2);
        Core.rectangle(mRgba, eyearea_right.tl(), eyearea_right.br(),
                new Scalar(255, 0, 0, 255), 2);

        if (learn_frames < 5) {
            teplateR = get_template(mJavaDetectorEye, eyearea_right, 24);
            teplateL = get_template(mJavaDetectorEye, eyearea_left, 24);
            learn_frames++;
        } else {
            // Learning finished, use the new templates for template
            // matching
             match_eye(eyearea_right, teplateR, method); 
             match_eye(eyearea_left, teplateL, method); 

        }

    }

    return mRgba;
}

Thanks in advance.

Vishal Chhatwani
  • 167
  • 1
  • 4
  • 14

3 Answers3

1

I already worked on this problem and this algorithm. It's implemented (C++) here: https://github.com/maz/blinking-angel with algorithm here: http://www.cs.bu.edu/techreports/pdf/2005-012-blink-detection.pdf .

As far as I can remember:

  • You get B&W current and 100ms ago frames
  • You do new - old (see 154 in github code)
  • You apply a threshold then a dilatation filter
  • You compute contours
  • If you have a blob with area > to a threshold at the eye location, it means that user blinked eyes

Give a look at the is_blink function at line 316. In his case, he do w * h of blob surrounding box > to a threshold.

In fact it use difference between eye/skin color. In Github implementation, threshold > 5 is used.

Tom A
  • 639
  • 5
  • 10
  • Thanks for the step by step explanation. So now I know what steps I need to follow thanks to you. First of all, I have to convert RGBA image into B&W. I couldnt find any java code for that. Can you send me the link to its java code? – Vishal Chhatwani Apr 13 '15 at 16:40
  • Why RGBA? BGR 2 GRAY rather? – Tom A Apr 13 '15 at 17:34
  • You need to use http://docs.opencv.org/java/org/opencv/imgproc/Imgproc.html#cvtColor(org.opencv.core.Mat,%20org.opencv.core.Mat,%20int) with COLOR_BGR2GRAY as code to get a gray frame then http://docs.opencv.org/java/org/opencv/imgproc/Imgproc.html#threshold(org.opencv.core.Mat,%20org.opencv.core.Mat,%20double,%20double,%20int) with threshold 5-255 and THRESH_BINARY to get a binary frame. I will try to write the complete code when back home. Ps: BGR frame is a Blue Green Right frame, RGBA is a Red Green Blue Alpha frame where Alpha is the transparency channel. – Tom A Apr 13 '15 at 17:52
  • Thanks a lot Sir. I will try to do it. So nice of you. :) – Vishal Chhatwani Apr 13 '15 at 18:18
  • i have successfully converted RGBA to Gray and then to Binary. Thanks to you :) Now I have to compare current frame with the previous frame. How do I save the previous frame so that I can compare it with current frame ? – Vishal Chhatwani Apr 15 '15 at 00:26
1

What I did was that I converted the eye region from RGB to HSV and applied skin detection. I found out the range of skin color in HSV. If the percentage of skin pixels is greater than threshold value that means Eye is close otherwise it is open. Though there is still some accuracy issue due to amount of light present. Thank you all for giving me a start :)

Vishal Chhatwani
  • 167
  • 1
  • 4
  • 14
0

Generally there is no obvious solution for this problem, but the number of approaches is quite big, so i'm sure that after a bit of serching you will find something good enough for you. For example you can use algorithm which i mentioned here (there is a link to this question in "Related" btw - check other link from this group as well).

Community
  • 1
  • 1
cyriel
  • 3,522
  • 17
  • 34
  • yea you are right. I have seen different ways on different places which confused me. Right now I am trying to work on method @Tom A told me. Do you know any better way? – Vishal Chhatwani Apr 13 '15 at 16:48