【问题标题】:Detect open or closed eye using openCV in python在python中使用openCV检测睁眼或闭眼
【发布时间】:2017-05-11 01:47:17
【问题描述】:

我正在尝试使用 python 中的 haar 级联算法检测用户的眼睛在实时视频中是睁着还是闭着。 可惜效果不好。

我知道“haarcascade_eye.xml”用于检测睁眼,“haarcascade_lefteye_2splits”用于检测眼睛(闭眼或睁眼)。

我想比较视频中睁开的眼睛和一般的眼睛,但它会错误地识别出闭上的眼睛。还有其他\更多改进方法吗?

这是我的代码:

import numpy as np
import cv2

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
lefteye_cascade = cv2.CascadeClassifier('haarcascade_lefteye_2splits.xml')

cap = cv2.VideoCapture(0)

while True:
   ret, img = cap.read()
   gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
   faces = face_cascade.detectMultiScale(gray, 1.3, 5)

for (x, y, w, h) in faces:
    cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
    # regions of interest
    roi_gray = gray[y:y + h, (x+w)/2:x + w]
    roi_color = img[y:y + h, (x+w)/2:x + w]
    eye = 0
    openEye = 0
    counter = 0
    openEyes = eye_cascade.detectMultiScale(roi_gray)
    AllEyes = lefteye_cascade.detectMultiScale(roi_gray)
    for (ex, ey, ew, eh) in openEyes:
        openEye += 1
        cv2.rectangle(roi_color, (ex, ey), (ex + ew, ey + eh), (0, 255, 0),2)

    for (ex, ey, ew, eh) in AllEyes:
        eye += 1
        cv2.rectangle(roi_color, (ex, ey), (ex + ew, ey + eh), (0, 0, 40),2)

    if (openEye != eye):
        print ('alert')

cv2.imshow('img', img)

k = cv2.waitKey(30) & 0xff
if k == 27:
    break

cap.release()
cv2.destroyAllWindows()

【问题讨论】:

  • 找到了一个解决方案——使用 DLib 库并识别面部标志 :)

标签: python opencv computer-vision face-detection haar-classifier


【解决方案1】:
# Import the necessary packages 
import datetime as dt
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from EAR_calculator import *
from imutils import face_utils 
from imutils.video import VideoStream
import matplotlib.pyplot as plt
import matplotlib.animation as animate
from matplotlib import style 
import imutils 
import dlib
import time 
import cv2 
from playsound import playsound
from scipy.spatial import distance as dist
import os 
import csv
import numpy as np
import pandas as pd
from datetime import datetime

# Declare a constant which will work as the threshold for EAR value, below which it will be regared as a blink 
EAR_THRESHOLD = 0.2
# Declare another costant to hold the consecutive number of frames to consider for a blink 
CONSECUTIVE_FRAMES = 20 
# Another constant which will work as a threshold for MAR value
MAR_THRESHOLD = 14

# Now, intialize the dlib's face detector model as 'detector' and the landmark predictor model as 'predictor'
detector = dlib.get_frontal_face_detector() 
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

# Grab the indexes of the facial landamarks for the left and right eye respectively 
(lstart, lend) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
(rstart, rend) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]
(mstart, mend) = face_utils.FACIAL_LANDMARKS_IDXS["mouth"]

image = cv2.imread("images/raja_sleepy.jpg")

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Detect faces 
rects = detector(image, 1)

if len(rects)==1:
    
    for (i, rect) in enumerate(rects):
        shape = predictor(gray, rect)
        # Convert it to a (68, 2) size numpy array 
        shape = face_utils.shape_to_np(shape)
        # Draw a rectangle over the detected face 
        (x, y, w, h) = face_utils.rect_to_bb(rect) 
        cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)    
        # Put a number 
        
        leftEye = shape[lstart:lend]
        rightEye = shape[rstart:rend] 
        mouth = shape[mstart:mend]
        # Compute the EAR for both the eyes 
        leftEAR = eye_aspect_ratio(leftEye)
        rightEAR = eye_aspect_ratio(rightEye)

        # Take the average of both the EAR
        EAR = (leftEAR + rightEAR) / 2.0
        #live datawrite in csv
        
        # Compute the convex hull for both the eyes and then visualize it
        leftEyeHull = cv2.convexHull(leftEye)
        rightEyeHull = cv2.convexHull(rightEye)
        # Draw the contours 
        cv2.drawContours(image, [leftEyeHull], -1, (0, 255, 0), 1)
        cv2.drawContours(image, [rightEyeHull], -1, (0, 255, 0), 1)
        cv2.drawContours(image, [mouth], -1, (0, 255, 0), 1)
        
        MAR = mouth_aspect_ratio(mouth)
            # Check if EAR < EAR_THRESHOLD, if so then it indicates that a blink is taking place 
            # Thus, count the number of frames for which the eye remains closed 
        if EAR < EAR_THRESHOLD: 
            cv2.drawContours(image, [leftEyeHull], -1, (0, 0, 255), 1)
            cv2.drawContours(image, [rightEyeHull], -1, (0, 0, 255), 1)
            cv2.putText(image, "Sleepy", (270, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
        else:
            FRAME_COUNT = 0        
            # Check if the person is yawning
        if MAR > MAR_THRESHOLD:
            cv2.drawContours(image, [mouth], -1, (0, 0, 255), 1) 
            cv2.putText(image, "Yawn ", (270, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            
    cv2.imshow("Output", image)
    cv2.waitKey(0)

elif len(rects)==0:
    print("Face not available")

else:
    print("Multiple face detected")     
    

【讨论】:

    【解决方案2】:

    看看这个。它给出了眼睛的状态。根据雷电条件改变阈值。 资源:https://www.pyimagesearch.com/2017/04/24/eye-blink-detection-opencv-python-dlib/

    # import the necessary packages
    from scipy.spatial import distance as dist
    from imutils.video import FileVideoStream
    from imutils.video import VideoStream
    from imutils import face_utils
    import numpy as np
    import argparse
    import imutils
    import time
    import dlib
    import cv2
    
    
    def eye_aspect_ratio(eye):
        # compute the euclidean distances between the two sets of
        # vertical eye landmarks (x, y)-coordinates
        A = dist.euclidean(eye[1], eye[5])
        B = dist.euclidean(eye[2], eye[4])
    
        # compute the euclidean distance between the horizontal
        # eye landmark (x, y)-coordinates
        C = dist.euclidean(eye[0], eye[3])
    
        # compute the eye aspect ratio
        ear = (A + B) / (2.0 * C)
    
        # return the eye aspect ratio
        return ear
    
    # frames the eye must be below the threshold
    EYE_AR_THRESH = 0.35
    EYE_AR_CONSEC_FRAMES = 3
    
    # initialize the frame counters and the total number of blinks
    COUNTER = 0
    TOTAL = 0
    
    # initialize dlib's face detector (HOG-based) and then create
    # the facial landmark predictor
    print("[INFO] loading facial landmark predictor...")
    detector = dlib.get_frontal_face_detector()
    predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
    
    # grab the indexes of the facial landmarks for the left and
    # right eye, respectively
    (lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
    (rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]
    
    vs = VideoStream(src=0).start()
    # vs = VideoStream(usePiCamera=True).start()
    time.sleep(1.0)
    
    # loop over frames from the video stream
    while True:
        # if this is a file video stream, then we need to check if
        # there any more frames left in the buffer to process
    
        # grab the frame from the threaded video file stream, resize
        # it, and convert it to grayscale
        # channels)
        frame = vs.read()
        frame = imutils.resize(frame, width=450)
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    
        # detect faces in the grayscale frame
        rects = detector(gray, 0)
    
        # loop over the face detections
        for rect in rects:
            # determine the facial landmarks for the face region, then
            # convert the facial landmark (x, y)-coordinates to a NumPy
            # array
            shape = predictor(gray, rect)
            shape = face_utils.shape_to_np(shape)
    
            # extract the left and right eye coordinates, then use the
            # coordinates to compute the eye aspect ratio for both eyes
            leftEye = shape[lStart:lEnd]
            rightEye = shape[rStart:rEnd]
            leftEAR = eye_aspect_ratio(leftEye)
            rightEAR = eye_aspect_ratio(rightEye)
    
            # average the eye aspect ratio together for both eyes
            ear = (leftEAR + rightEAR)
    
            # compute the convex hull for the left and right eye, then
            # visualize each of the eyes
            leftEyeHull = cv2.convexHull(leftEye)
            rightEyeHull = cv2.convexHull(rightEye)
            cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)
            cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1)
    
            # check to see if the eye aspect ratio is below the blink
            # threshold, and if so, increment the blink frame counter
            if ear < EYE_AR_THRESH:
                cv2.putText(frame, "Eye: {}".format("close"), (10, 30),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
                cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
    
    
            # otherwise, the eye aspect ratio is not below the blink
            # threshold
            else:
                cv2.putText(frame, "Eye: {}".format("Open"), (10, 30),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
                cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
    
        # draw the total number of blinks on the frame along with
        # the computed eye aspect ratio for the frame
    
        # show the frame
        cv2.imshow("Frame", frame)
        key = cv2.waitKey(1) & 0xFF
    
        # if the `q` key was pressed, break from the loop
        if key == ord("q"):
            break
    
    # do a bit of cleanup
    cv2.destroyAllWindows()
    vs.stop()
    

    【讨论】:

      【解决方案3】:

      最终我使用 DLib 库来识别面部标志 :)

      【讨论】:

        猜你喜欢
        • 2015-05-02
        • 2014-01-01
        • 2015-06-17
        • 2012-09-21
        • 1970-01-01
        • 1970-01-01
        • 2012-08-27
        • 2015-12-11
        • 2012-11-01
        相关资源
        最近更新 更多