2015-04-12 5 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.

Насколько я помню:

  • Вы получаете B & W тока и 100мс назад кадры
  • Вам новый - старый (см 154 в GitHub код)
  • Вы применяете порог, то дилатация фильтр
  • вы вычислить контуры
  • Если у вас есть blob with area > to a threshold на месте глаз, это означает, что пользователь прищурив глаз

Посмотрите на функцию is_blink по строке 316. В его случае он делает 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

Как правило, нет очевидного решения этой проблемы, но количество подходов довольно велико, поэтому я уверен, что после некоторого задержек вы найдете что-то достаточно хорошее для вас. Например, вы можете использовать алгоритм, который я упомянул here (есть ссылка на этот вопрос в разделе «Связанный» btw - проверьте и другую ссылку из этой группы).

+0

Да, вы правы. Я видел разные способы в разных местах, которые меня смутили. Прямо сейчас я пытаюсь работать над методом @Tom A, который мне сказал. Вы знаете лучший способ? –

1

Что я сделал, так это то, что я преобразовал область глаз от RGB к HSV и применял обнаружение кожи. Я узнал диапазон цвета кожи в HSV. Если процент пикселов кожи больше порогового значения, что означает, что Eye близок, иначе он открыт. Несмотря на то, что по-прежнему существует некоторая точность, из-за количества присутствующего света. Спасибо всем, что дали мне начало :)

Смежные вопросы