使用OpenCV和face_recognition库的人脸识别脚本

问题描述 投票:0回答:2

我正在开发一个人脸识别项目,但在使用以下代码时遇到问题。它是一个Python程序,使用OpenCV和face_recognition库对图像和实时图像进行人脸识别。我遇到了一些问题,希望能够帮助解决这些问题。当实时时,opencv 工作并打开相机,但是当识别到人脸时,程序直接关闭,这种情况不应该发生,如果有人有任何解决方案,我将不胜感激。

import argparse
import pickle
from collections import Counter
from pathlib import Path

import cv2
import face_recognition
from PIL import Image, ImageDraw

DEFAULT_ENCODINGS_PATH = Path("output/encodings.pkl")
BOUNDING_BOX_COLOR = (255, 0, 0)  # Blue color (BGR format)
TEXT_COLOR = (255, 255, 255)  # White color (BGR format)


# Create directories if they don't already exist
Path("training").mkdir(exist_ok=True)
Path("output").mkdir(exist_ok=True)
Path("validation").mkdir(exist_ok=True)

parser = argparse.ArgumentParser(description="Recognize faces in an image")
parser.add_argument("--train", action="store_true", help="Train on input data")
parser.add_argument("--validate", action="store_true", help="Validate trained model")
parser.add_argument("--test", action="store_true", help="Test the model with an unknown image")
parser.add_argument("-m", action="store", default="hog", choices=["hog", "cnn"], help="Which model to use for training: hog (CPU), cnn (GPU)")
parser.add_argument("-f", action="store", help="Path to an image with an unknown face")
parser.add_argument("--realtime", action="store_true", help="Enable real-time face detection using the camera")
args = parser.parse_args()


def encode_known_faces(model: str = "hog", encodings_location: Path = DEFAULT_ENCODINGS_PATH) -> None:
    """
    Loads images in the training directory and builds a dictionary of their
    names and encodings.
    """
    names = []
    encodings = []

    for filepath in Path("training").glob("*/*"):
        name = filepath.parent.name
        image = face_recognition.load_image_file(filepath)

        face_locations = face_recognition.face_locations(image, model=model)
        face_encodings = face_recognition.face_encodings(image, face_locations)

        for encoding in face_encodings:
            names.append(name)
            encodings.append(encoding)

    name_encodings = {"names": names, "encodings": encodings}
    with encodings_location.open(mode="wb") as f:
        pickle.dump(name_encodings, f)


def recognize_faces(image_location: str, model: str = "hog", encodings_location: Path = DEFAULT_ENCODINGS_PATH) -> None:
    """
    Given an unknown image, get the locations and encodings of any faces and
    compares them against the known encodings to find potential matches.
    """
    with encodings_location.open(mode="rb") as f:
        loaded_encodings = pickle.load(f)

    input_image = face_recognition.load_image_file(image_location)

    input_face_locations = face_recognition.face_locations(input_image, model=model)
    input_face_encodings = face_recognition.face_encodings(input_image, input_face_locations)

    pillow_image = Image.fromarray(input_image)
    draw = ImageDraw.Draw(pillow_image)

    for bounding_box, unknown_encoding in zip(input_face_locations, input_face_encodings):
        name = _recognize_face(unknown_encoding, loaded_encodings)
        if not name:
            name = "Unknown"
        _display_face(draw, bounding_box, name)

    del draw
    pillow_image.show()


def _recognize_face(unknown_encoding, loaded_encodings):
    """
    Given an unknown encoding and all known encodings, find the known
    encoding with the most matches.
    """
    boolean_matches = face_recognition.compare_faces(loaded_encodings["encodings"], unknown_encoding)
    votes = Counter(name for match, name in zip(boolean_matches, loaded_encodings["names"]) if match)
    if votes:
        return votes.most_common(1)[0][0]


def _display_face(draw, bounding_box, name):
    """
    Draws bounding boxes around faces, a caption area, and text captions.
    """
    top, right, bottom, left = bounding_box
    draw.rectangle(((left, top), (right, bottom)), outline=BOUNDING_BOX_COLOR)
    text_left, text_top, text_right, text_bottom = draw.textbbox((left, bottom), name)
    draw.rectangle(((text_left, text_top), (text_right, text_bottom)), fill=BOUNDING_BOX_COLOR, outline=BOUNDING_BOX_COLOR)
    draw.text((text_left, text_top), name, fill=TEXT_COLOR)


def validate(model: str = "hog"):
    """
    Runs recognize_faces on a set of images with known faces to validate
    known encodings.
    """
    for filepath in Path("validation").rglob("*"):
        if filepath.is_file():
            recognize_faces(image_location=str(filepath.absolute()), model=model)


def detect_faces_realtime(model: str = "hog", encodings_location: Path = DEFAULT_ENCODINGS_PATH) -> None:
    """
    Performs real-time face detection using the camera feed.
    """
    with encodings_location.open(mode="rb") as f:
        loaded_encodings = pickle.load(f)

    video_capture = cv2.VideoCapture(0)  # Open the camera

    while True:
        ret, frame = video_capture.read()  # Read a frame from the camera feed

        # Resize the frame to reduce processing time (optional)
        small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)

        rgb_small_frame = small_frame[:, :, ::-1]  # Convert BGR frame to RGB

        face_locations = face_recognition.face_locations(rgb_small_frame, model=model)
        face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)

        for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
            name = _recognize_face(face_encoding, loaded_encodings)
            if not name:
                name = "Unknown"

            # Scale the face locations back to the original size
            top *= 4
            right *= 4
            bottom *= 4
            left *= 4

            cv2.rectangle(frame, (left, top), (right, bottom), BOUNDING_BOX_COLOR, 2)
            cv2.putText(
                frame,
                name,
                (left + 6, bottom - 6),
                cv2.FONT_HERSHEY_SIMPLEX,
                1.0,
                TEXT_COLOR,
                1,
            )

        cv2.imshow("Video", frame)  # Display the resulting frame

        if cv2.waitKey(1) & 0xFF == ord("q"):
            break  # Break the loop if 'q' is pressed

    video_capture.release()  # Release the camera
    cv2.destroyAllWindows()  # Close all OpenCV windows


if __name__ == "__main__":
    if args.train:
        encode_known_faces(model=args.m)
    if args.validate:
        validate(model=args.m)
    if args.test:
        recognize_faces(image_location=args.f, model=args.m)
    if args.realtime:
        detect_faces_realtime(model=args.m)

说明:该代码使用OpenCV和face_recognition库对图像和视频进行人脸识别。它由几个函数组成,包括encode_known_faces、recognize_faces、validate和detect_faces_realtime。

encode_known_faces 函数从训练目录加载图像,检测人脸并提取其编码。然后将这些编码保存在 pickle 文件中。

recognize_faces 函数获取未知图像,检测面部,并将其编码与 pickle 文件中的已知编码进行比较。它显示识别出的面孔以及边界框和标签。

验证函数用于通过在验证目录中具有已知面孔的一组图像上运行 recognize_faces 来验证已知编码。

detector_faces_realtime 函数使用摄像头输入执行实时人脸检测。它连续捕获帧、检测面部并使用已知的编码来识别它们。

该脚本利用 argparse 模块来处理不同功能的命令行参数,例如训练、验证、测试和实时检测。所选模型(hog 或 cnn)也可以指定为命令行参数。

错误代码:

python .\ detector.py --实时 回溯(最近一次调用最后一次): 文件“C:\Users\Cartu\Downloads\materials-face-recognition\source_code_final\ detector.py”,第 171 行,位于 detector_faces_realtime(模型=args.m) 文件“C:\Users\Cartu\Downloads\materials-face-recognition\source_code_final\ detector.py”,第 130 行,在 detector_faces_realtime 中 face_encodings =face_recognition.face_encodings(rgb_small_frame,face_locations) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ 文件“C:\Python311\Lib\site-packages ace_recognition pi.py”,第 214 行,face_encodings 返回 [np.array(face_encoder.compute_face_descriptor(face_image, raw_landmark_set, num_jitters)) for raw_landmark_set in raw_landmarks] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 文件“C:\Python311\Lib\site-packages ace_recognition pi.py”,第 214 行,位于 返回 [np.array(face_encoder.compute_face_descriptor(face_image, raw_landmark_set, num_jitters)) for raw_landmark_set in raw_landmarks] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 类型错误:compute_face_descriptor():函数参数不兼容。支持以下参数类型: 1.(自身:_dlib_pybind11.face_recognition_model_v1,img:numpy.ndarray[(rows,cols,3),numpy.uint8],脸部:_dlib_pybind11.full_object_detection,num_jitters:int = 0,填充:float = 0.25)-> _dlib_pybind11。向量 2. (self: _dlib_pybind11.face_recognition_model_v1, img: numpy.ndarray[(rows,cols,3),numpy.uint8], num_jitters: int = 0) -> _dlib_pybind11.vector 3.(自身:_dlib_pybind11.face_recognition_model_v1,img:numpy.ndarray[(rows,cols,3),numpy.uint8],面孔:_dlib_pybind11.full_object_detections,num_jitters:int = 0,填充:float = 0.25)-> _dlib_pybind11。向量 4.(自我:_dlib_pybind11.face_recognition_model_v1,batch_img:列表[numpy.ndarray [(行,列,3),numpy.uint8]],batch_faces:列表[_dlib_pybind11.full_object_detections],num_jitters:int = 0,填充:float = 0.25) -> _dlib_pybind11.vectorss 5.(自身:_dlib_pybind11.face_recognition_model_v1,batch_img:列表[numpy.ndarray [(行,列,3),numpy.uint8]],num_jitters:int = 0)-> _dlib_pybind11.vectors

调用方式:<_dlib_pybind11.face_recognition_model_v1 object at 0x0000019DD1502D70>, array([[[179, 179, 179], [179, 179, 179], [179, 179, 179], ..., [126、129、128]、 [126、130、129]、 [123, 130, 128]],

   [[181, 181, 181],
    [181, 181, 181],
    [180, 180, 180],
    ...,
    [123, 129, 136],
    [122, 130, 130],
    [122, 131, 131]],

   [[180, 180, 180],
    [179, 179, 179],
    [180, 180, 180],
    ...,
    [122, 128, 130],
    [124, 132, 132],
    [121, 130, 128]],

   ...,

   [[175, 174, 165],
    [172, 173, 168],
    [173, 174, 171],
    ...,
    [ 71,  71,  71],
    [ 71,  71,  71],
    [ 72,  72,  71]],

   [[176, 172, 165],
    [175, 172, 167],
    [172, 173, 169],
    ...,
    [ 65,  67,  67],
    [ 68,  69,  69],
    [ 60,  64,  63]],

   [[176, 171, 169],
    [174, 171, 169],
    [173, 171, 171],
    ...,
    [ 66,  66,  66],
    [ 70,  70,  70],
    [ 62,  65,  64]]], dtype=uint8), <_dlib_pybind11.full_object_detection object at 0x0000019DD19F07F0>, 1

我尝试多次更改代码,删除内容以查找错误,我一直在搜索但找不到任何信息。如果有人有其他选择,我看过一些关于 deepface 的内容,但我不知道它是否更容易使用。

python opencv image-processing argparse face-recognition
2个回答
0
投票

简单

from deepface import DeepFace

DeepFace.stream(db_path = r"C:\database", time_threshold=1, frame_threshold=5)

这是我目前得到的最好结果,现在我正在尝试在识别到人脸时发送通知


0
投票

嘿 cartu28 我还想创建具有人脸识别功能的人体入侵检测,但我想训练模型如何使用 Deepface 来做到这一点。

© www.soinside.com 2019 - 2024. All rights reserved.