【问题标题】:How to detect faces with imutils?如何用imutils检测人脸?
【发布时间】:2022-01-11 22:36:13
【问题描述】:

我目前正在创建一个 django 人脸检测/识别应用程序来标记员工出勤率,但是在捕获相机提要和检测提要上的人脸时遇到了一些问题。

view.py 中的以下功能是检测员工面部并捕获已登录员工的 300 张图像 - 本质上,此问题的目的是解决面部检测问题,而问题具体在于 face_aligned = fa .align(frame, gray_frame, face).

views.py:

def create_dataset(username):
   

    id = username
    if (os.path.exists('Recog_Data/Train_Data/{}/'.format(id)) == False):
        os.makedirs('Recog_Data/Train_Data/{}/'.format(id))
    directory = 'Recog_Data/Train_Data/{}/'.format(id)

    # Detect face
    # Loading the HOG face detector and the shape predictpr for allignment

    print("[INFO] Loading the facial detector")
    detector = dlib.get_frontal_face_detector()
    predictor = dlib.shape_predictor('Recog_Data/shape_predictor_68_face_landmarks.dat')  # Add path to the shape predictor ######CHANGE TO RELATIVE PATH LATER
    fa = FaceAligner(predictor, desiredFaceWidth=256)
    # capture images from the webcam and process and detect the face
    # Initialize the video stream
    print("[INFO] Initializing Video stream")
    vs = VideoStream(src=0).start()
    # time.sleep(2.0) ####CHECK######

    # Our identifier
    # We will put the id here and we will store the id with a face, so that later we can identify whose face it is

    # Our dataset naming counter
    sampleNum = 0
    # Capturing the faces one by one and detect the faces and showing it on the window
    while (True):
        # Capturing the image
        # vs.read each frame
        frame = vs.read()
        # Resize each image
        frame = imutils.resize(frame, width=800)
        # the returned img is a colored image but for the classifier to work we need a greyscale image
        # to convert
        gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # To store the faces
        # This will detect all the images in the current frame, and it will return the coordinates of the faces
        # Takes in image and some other parameter for accurate result
        faces = detector(gray_frame, 2)
        # In above 'faces' variable there can be multiple faces so we have to get each and every face and draw a rectangle around it.

        for face in faces:
            print("inside for loop")
            (x, y, w, h) = face_utils.rect_to_bb(face)

            face_aligned = fa.align(frame, gray_frame, face)
            # Whenever the program captures the face, we will write that is a folder
            # Before capturing the face, we need to tell the script whose face it is
            # For that we will need an identifier, here we call it id
            # So now we captured a face, we need to write it in a file
            sampleNum = sampleNum + 1
            # Saving the image dataset, but only the face part, cropping the rest

            if face is None:
                print("face is none")
                continue

            cv2.imwrite(directory + '/' + str(sampleNum) + '.jpg', face_aligned)
            face_aligned = imutils.resize(face_aligned, width=400)
            # cv2.imshow("Image Captured",face_aligned)
            # @params the initial point of the rectangle will be x,y and
            # @params end point will be x+width and y+height
            # @params along with color of the rectangle
            # @params thickness of the rectangle
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 1)
            # Before continuing to the next loop, I want to give it a little pause
            # waitKey of 100 millisecond
            cv2.waitKey(50)

        # Showing the image in another window
        # Creates a window with window name "Face" and with the image img
        cv2.imshow("Add Images", frame)
        # Before closing it we need to give a wait command, otherwise the open cv wont work
        # @params with the millisecond of delay 1
        cv2.waitKey(1)
        # To get out of the loop
        if (sampleNum > 300):
            break

    # Stoping the videostream
    vs.stop()
    # destroying all the windows
    cv2.destroyAllWindows()

@login_required
def add_photos(request):
    if not request.user.is_authenticated:
        messages.warning(request, f'Employee not authorised')
        return redirect('dashboard')
    elif request.user.is_authenticated:
        user = request.user
        create_dataset(user)
        messages.success(request, f'Dataset Created')
        return redirect('dashboard')
    else:
        messages.warning(request, f'Error: dataset not created')
        return render(request, 'dashboard')

与错误相关的堆栈跟踪:

Traceback (most recent call last):
  File "/Users/xxxx/Desktop/djangoWebcamTest/venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/Users/xxxx/Desktop/djangoWebcamTest/venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/xxxx/Desktop/djangoWebcamTest/venv/lib/python3.9/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/Users/xxxx/Desktop/djangoWebcamTest/users/views.py", line 204, in add_photos
    create_dataset(user)
  File "/Users/xxxx/Desktop/djangoWebcamTest/users/views.py", line 157, in create_dataset
    face_aligned = fa.align(frame, gray_frame, face)
  File "/Users/xxxx/Desktop/djangoWebcamTest/venv/lib/python3.9/site-packages/imutils/face_utils/facealigner.py", line 68, in align
    M = cv2.getRotationMatrix2D(eyesCenter, angle, scale)

Exception Type: TypeError at /vidstream/
Exception Value: Can't parse 'center'. Sequence item with index 0 has a wrong type

这是打印到控制台的变量的屏幕截图 - face_aligned = fa.align(frame, gray_frame, face):

任何有关此问题的帮助将不胜感激

【问题讨论】:

    标签: python django opencv face-detection imutils


    【解决方案1】:

    检查以下输入的值:

    face_aligned = fa.align(frame, gray_frame, face)
    

    虽然文档中没有提到,fa.align() 似乎期待数据/对象,见:https://github.com/PyImageSearch/imutils/blob/master/imutils/face_utils/facealigner.py#L23

    its body 中的 .align() 函数的参数没有太多变化。您的fa.align(frame, gray_frame, face) 函数调用中的face 变量很可能是'center' 字符串(或此类字符串的列表),而它应该是带有边界框或类似内容的列表。

    您在:M = cv2.getRotationMatrix2D(eyesCenter, angle, scale) 收到错误,请参阅:https://github.com/PyImageSearch/imutils/blob/master/imutils/face_utils/facealigner.py#L68。以下之一:eyesCenteranglescale 的值为 'center',而它可能需要一个列表或一个数组(不是字符串)。


    编辑

    我重新分析了问题。

    这是在本地环境中重现问题的代码:

    import cv2
    import dlib
    import imutils
    import time
    
    from imutils import face_utils
    from imutils.face_utils import FaceAligner
    from imutils.video import VideoStream
    
    detector = dlib.get_frontal_face_detector()
    # Shape predictor: https://github.com/italojs/facial-landmarks-recognition/blob/master/shape_predictor_68_face_landmarks.dat
    predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
    fa = FaceAligner(predictor, desiredFaceWidth=256)
    
    
    print("[INFO] Initializing Video stream")
    vs = VideoStream(src=0).start()
    time.sleep(2.0)
    
    frame = vs.read()
    #print(frame)
    frame = imutils.resize(frame, width=800)
    
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    faces = detector(gray_frame, 2)
    print(faces)
    
    
    for face in faces:
        print("inside for loop")
    
        if face is None:
            print("face is none")
            continue
    
        (x, y, w, h) = face_utils.rect_to_bb(face)
    
        #cv2.imwrite('1.jpg', face_aligned)
        #face_aligned = imutils.resize(face_aligned, width=400)
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 1)
        cv2.waitKey(2000)
    
        cv2.imshow("Add Images", frame)
        cv2.waitKey(2000)
    
        vs.stop()
        cv2.destroyAllWindows()
    
    
    
        #########################
        #                       #
        #  HERE IS THE PROBLEM  #
        #                       #
        #########################
        #print(gray_frame)
        #print(face)
        # Your code
        face_aligned = fa.align(frame, gray_frame, face)
    

    您可能有一个错误的predictor,或者imutils 源代码有问题(那里有一些"hacks" ;))。无论如何,fa.align 函数内部发生的事情是,有一个错误的对象作为 eyesCenter 传递给 M = cv2.getRotationMatrix2D(eyesCenter, angle, scale) (ref)。

    我建议编辑您的imutils 源代码副本以打印eyesCenter 的值,以检查此数据结构有什么问题。在您的示例中,eyesCenter 值不是 getRotationMatrix2D 函数所期望的值。另请参阅this 示例,该示例似乎有效。

    希望有帮助!

    【讨论】:

    • 嘿@Mikolaj Buchwald,我正在将 (frame, gray_frame, face) 的值打印到控制台,我看到以下内容: frame: [[[ 7 7 7] [ 0 0 0] [ 10 7 7] ... [ 17 37 44] [ 21 40 49] [ 5 16 25]] [[ 12 12 13] [ 1 1 1] [ 0 0 0] ... etc gray_frame: [[ 0 0 1 ... 20 19 15] [ 0 0 0 ... 19 20 12] [ 0 0 1 ... 19 21 11] ... [ 0 0 0 ... 214 216 218] [ 0 0 0 ... 215 217 219] [ 0 0 0 ... 212 213 213]] face: @987654352 @
    • 对我之前帖子中的格式表示歉意,但是我是新来的,我对这些面部识别/检测技术不熟悉。但是,以上对您来说是否正确?数组似乎与... 分开 - 我在@mikolaj-buchwald 之前从未见过这个
    • @rhys,你能不能也请张控制台的截图?变量是数值,而不是字符串,好的。现在我看到了,您的错误堆栈跟踪中的 'center' 可能是指 OpenCV 的 getRotationMatrix2D 函数的参数名称:docs.opencv.org/3.4/da/d54/… 换句话说,frame 应该具有类型Point2f 在 OpenCV 中,它是 Python 中 (x, y) 的一元组:github.com/PyImageSearch/imutils/blob/master/imutils/face_utils/…
    • 同时,您似乎在frame 变量中存储了其他内容:: [[[ 7 7 7] [ 0 0 0] [ 10 7 7] ... [ 17 37 44] [ 21 40 49] [ 5 16 25]] [[ 12 12 13] [ 1 1 1] [ 0 0 0]
    • 嘿@mikolaj-buchwald,我将屏幕截图上传到我的原始帖子。您可以看到上面列出的变量的每个输出。关于 Point2f 类型,控制台错误:Exception Value: Can't parse 'center'. Sequence item with index 0 has a wrong type - 表明frame 的类型错误,但是我不完全确定如何操作它并将其设置为正确的类型,有什么想法吗?
    猜你喜欢
    • 2020-06-28
    • 2019-11-18
    • 2013-09-24
    • 1970-01-01
    • 2016-11-18
    • 2010-11-26
    • 2020-10-24
    • 2017-06-01
    • 2012-04-17
    相关资源
    最近更新 更多