2015-04-12 122 views
-3

我正在开发一个android应用程序,我需要检测眼睛的眨眼。到目前为止,我已经能够使用OpenCV检测脸部和眼睛。但现在我需要检查眼睛是否打开或关闭。我在某处读到,我可以通过测量像素强度(灰度级)来实现这一点。但没有正确解释如何一步一步做到这一点。我实际上是OpenCV的新手。所以任何人都可以请帮助我,我该怎么做。这真的很重要。检测眼睛是否打开或关闭

这里是我的onCameraFrame方法:

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; 
} 

在此先感谢。

回答

1

我已经工作在这个问题上和这个算法。它的实现(C++)在这里:https://github.com/maz/blinking-angel,算法在这里:http://www.cs.bu.edu/techreports/pdf/2005-012-blink-detection.pdf

至于我能记得:

  • 你得到乙& W通电和100ms的前框
  • 你新 - 老(见154 GitHub的代码)
  • 您应用一个阈值,则一个扩张过滤
  • 您计算轮廓
  • 如果你有一个blob with area > to a threshold在眼睛的位置,这意味着用户眨眼

请看0123行的is_blink函数。在他的情况下,他做了w * h of blob surrounding box > to a threshold

事实上,它用眼/皮肤颜色之间的差别。在Github实现中,使用阈值> 5。

+0

非常感谢。我会看看代码。 –

+0

感谢您一步一步的解释。所以现在我知道我需要遵循哪些步骤来感谢你。首先,我必须将RGBA图像转换为B&W。我找不到任何Java代码。你能给我发送到它的java代码的链接吗? –

+0

CvtColor:http://docs.opencv.org/java/org/opencv/imgproc/Imgproc.html –

0

一般是有这个问题没有明显的解决方案,但方案的数量是相当大的,所以我敢肯定这一点serching你会找到的东西够你不错的了。例如,你可以使用我提到的算法here(这里有一个链接到“相关”btw这个问题 - 检查来自这个组的其他链接)。

+0

你是对的。我在不同的地方看到了令我困惑的不同方式。现在我正在尝试@Tom A告诉我的方法。你知道更好的方法吗? –

1

我做什么,我转换的眼睛区域从RGB到HSV和应用皮肤检测。我发现了HSV皮肤颜色的范围。如果皮肤像素的百分比大于阈值,则意味着眼睛关闭,否则它是开放的。尽管由于光量的存在,仍然存在一些准确度问题。谢谢大家给我一个开始:)