基于face_recognition摄像头人脸识别并打包

写在前面

本文利用python中的face_recognition库进行人脸识别,该库需要调用dlib库,安装过程可参考其他博客。关于face_recognition库的介绍和案例,可参考该链接内容https://github.com/ageitgey/face_recognition.本文的代码也是根据其中的一个例子稍作改动而来。
注意:请使用python3.6版本运行此程序我开始使用python3.7在打包过程中遇到了无法解决的问题,换成python3.6便可成功打包运行。python3.6对于人脸识别比较友好。打包的相关注意事项在后面的文章中会提到。
本文基于上文的github中的examples文件夹中的facerec_from_webcam_faster.py文件改动而来。开始使用运用了多线程的facerec_from_webcam_multiprocessing.py,但是在打包后出现了内存一直增长但是摄像头窗口不出现的问题,一直没找到解决办法,在此希望有大佬可以解答一下。

程序

程序一览
其中,face_dataset文件夹存放人脸图片并以人名命名(opencv显示摄像头窗口及名字,内置方法无法显示中文名字,人名须是英文或拼音),该程序先将图片的名字(i.e.人名)及face_recognition中face_encoding方法生成的128维向量存储为json文件格式(另外也写了一个sqlite3保存的),在摄像头识别时读取json文件中的向量与摄像头读取的向量进行比较。

pic2json.py

### pic2json.py

import face_recognition
import os
import json
import numpy as np


def read_files(path, file_types):
    filenames = os.listdir(path)
    filenames1 = []
    for file_type in file_types:
        for filename in filenames:
            if os.path.splitext(filename)[1] == file_type:
                filenames1.append(filename)
    return filenames1


path = './face_dataset/'  # 人脸图片数据库路径


def load_pic():
    pic = read_files(path, ['.jpg', '.JPG', '.png'])

    pic_name = [name.strip('.jpg') for name in pic]
    pic_name = [name.strip('.JPG') for name in pic_name]
    pic_name = [name.strip('.png') for name in pic_name]  # 获取去掉后缀的图片名称

    image_encoding = []

    for i in range(len(pic)):
        temp = face_recognition.load_image_file(path + pic[i])
        face_encoding = face_recognition.face_encodings(temp)[0]
        image_encoding.append(face_encoding)

    return pic_name, image_encoding


# 将 人名 和 编码生成的128维向量 导入json文件

pic_name, image_encoding = load_pic()

face_dic = dict(map(lambda x, y: [x, y], pic_name, image_encoding))


class NpEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.integer):
            return int(obj)
        elif isinstance(obj, np.floating):
            return float(obj)
        elif isinstance(obj, np.ndarray):
            return obj.tolist()
        else:
            return super(NpEncoder, self).default(obj)


json_face = json.dumps(face_dic, cls=NpEncoder)

fileObject = open('./faceDataset.json', 'w')
fileObject.write(json_face)
print("json file has been successfully written")

read_json.py

### read_json.py

import json
import numpy as np


def load_json():
    with open("./faceDataset.json", 'r') as f:
        face_dict = json.load(f)
    # print(face_dict)

    pic_name = list(face_dict.keys())
    image_encoding_temp = list(face_dict.values())
    image_encoding = []
    for i in range(len(image_encoding_temp)):
        temp = np.array(image_encoding_temp[i])
        image_encoding.append(temp)

    return image_encoding, pic_name

facerec_from_webcam_faster.py

### facerec_from_webcam_faster.py

import face_recognition
import cv2
import numpy as np
from read_json import load_json

# Get a reference to webcam #0 (the default one)
video_capture = cv2.VideoCapture(0)
video_capture.set(3, 1080.0)

known_face_encodings, known_face_names = load_json()

face_locations = []
face_encodings = []
face_names = []
process_this_frame = True

while True:
    # Grab a single frame of video
    ret, frame = video_capture.read()

    # Resize frame of video to 1/4 size for faster face recognition processing
    small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)

    # Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses)
    rgb_small_frame = small_frame[:, :, ::-1]

    # Only process every other frame of video to save time
    if process_this_frame:
        # Find all the faces and face encodings in the current frame of video
        face_locations = face_recognition.face_locations(rgb_small_frame)
        face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)

        face_names = []
        for face_encoding in face_encodings:
            # See if the face is a match for the known face(s)
            matches = face_recognition.compare_faces(known_face_encodings, face_encoding)
            name = "Unknown"

            # # If a match was found in known_face_encodings, just use the first one.
            # if True in matches:
            #     first_match_index = matches.index(True)
            #     name = known_face_names[first_match_index]

            # Or instead, use the known face with the smallest distance to the new face
            face_distances = face_recognition.face_distance(known_face_encodings, face_encoding)
            best_match_index = np.argmin(face_distances)
            if matches[best_match_index]:
                name = known_face_names[best_match_index]

            face_names.append(name)

    process_this_frame = not process_this_frame

    # Display the results
    for (top, right, bottom, left), name in zip(face_locations, face_names):
        # Scale back up face locations since the frame we detected in was scaled to 1/4 size
        top *= 4
        right *= 4
        bottom *= 4
        left *= 4

        # Draw a box around the face
        cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)

        # Draw a label with a name below the face
        cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
        font = cv2.FONT_HERSHEY_DUPLEX
        cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)

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

    k = cv2.waitKey(1)

    # 点击右上角叉叉关闭摄像头窗口
    if cv2.getWindowProperty('Video', cv2.WND_PROP_AUTOSIZE) < 1:
        break
    if k == 27:
        break

# Release handle to the webcam
video_capture.release()
cv2.destroyAllWindows()

打包

利用pyinstaller打包,pyinstaller 可以将程序打包成一个exe文件也可以打包成一个文件夹的形式。这里使用后者。由于face_recognition中有4个模块无法自动打包,需要修改spec文件手动加入,pyinstaller打包会先生成spec文件,在根据spec文件进行相关操作,可以在spec文件中手动加入打包的东西和图标等相关操作,具体可参考https://pyinstaller.readthedocs.io/en/stable/.
在主程序文件夹下终端输入

>pyinstaller facerec_from_webcam_faster.py

文件夹会生成一个dist文件夹、一个build文件夹、一个spec文件,只保留spec文件,其他删除,打开spec文件,改成如下形式,路径要改一下(或者写一个text文件改后缀也行)

# -*- mode: python ; coding: utf-8 -*-
import sys
sys.setrecursionlimit(1000000)
block_cipher = None

face_models = [
('.\\face_recognition_models\\models\\dlib_face_recognition_resnet_model_v1.dat', './face_recognition_models/models'),
('.\\face_recognition_models\\models\\mmod_human_face_detector.dat', './face_recognition_models/models'),
('.\\face_recognition_models\\models\\shape_predictor_5_face_landmarks.dat', './face_recognition_models/models'),
('.\\face_recognition_models\\models\\shape_predictor_68_face_landmarks.dat', './face_recognition_models/models'),
]   # 手动打包的face_recognition模块,自己改路径,或者把face_recognition_models拖到当前文件夹下,这几行就不用改了
face_dataset=[
('./faceDataset.json','./')
]  # 手动把json文件打包
a = Analysis(['facerec_from_webcam_faster.py'], # 打包文件
             pathex=['F:\\PychamProject\\FaceRecognition_json'],  # 打包文件路径
             binaries=face_models,  # 这里
             datas=face_dataset,    # 这里
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          [],
          exclude_binaries=True,
          name='facerec_from_webcam_faster',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=False,
          icon = 'icon.ico'  # 图标 )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               upx_exclude=[],
               name='facerec_from_webcam_faster')

然后在spec文件路径下的终端输入

> pyinstaller facerec_from_webcam_faster.spec

搞定!

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
好的,下面是一个简单的基于face_recognition库的人脸识别方案代码示例: ```python import face_recognition import cv2 # 加载已知人脸的图像和名称 known_face_encodings = [] known_face_names = [] image1 = face_recognition.load_image_file("person1.jpg") image2 = face_recognition.load_image_file("person2.jpg") image3 = face_recognition.load_image_file("person3.jpg") known_face_encodings.append(face_recognition.face_encodings(image1)[0]) known_face_encodings.append(face_recognition.face_encodings(image2)[0]) known_face_encodings.append(face_recognition.face_encodings(image3)[0]) known_face_names = ["person1", "person2", "person3"] # 打开摄像头 cap = cv2.VideoCapture(0) while True: # 读取一帧图像 ret, frame = cap.read() # 将图像转换为RGB格式 rgb_frame = frame[:, :, ::-1] # 检测人脸 face_locations = face_recognition.face_locations(rgb_frame) face_encodings = face_recognition.face_encodings(rgb_frame, face_locations) # 遍历所有检测到的人脸 for face_encoding, face_location in zip(face_encodings, face_locations): # 尝试匹配人脸 matches = face_recognition.compare_faces(known_face_encodings, face_encoding) # 如果有匹配到的人脸,则取出其名称 if True in matches: match_index = matches.index(True) name = known_face_names[match_index] else: name = "unknown" # 绘制人脸矩形框和名称 top, right, bottom, left = face_location cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2) cv2.putText(frame, name, (left, top-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) # 显示图像 cv2.imshow('Face Recognition', frame) # 按下q键退出 if cv2.waitKey(1) & 0xFF == ord('q'): break # 释放摄像头和窗口 cap.release() cv2.destroyAllWindows() ``` 在这个代码示例中,我们使用face_recognition库加载了已知人脸的图像和名称,并使用cv2.VideoCapture()方法打开了摄像头。在每一帧图像中,我们使用face_recognition库检测人脸,并使用face_recognition.compare_faces()方法尝试匹配人脸。如果有匹配到的人脸,则取出其名称,并使用cv2.rectangle()和cv2.putText()方法绘制人脸矩形框和名称。最后,我们使用cv2.imshow()方法显示图像,并使用cv2.waitKey()方法等待用户按下q键退出程序。 值得注意的是,face_recognition库是一个基于dlib库的人脸识别库,其检测速度较慢,但是识别精度较高。在实际应用中,我们需要根据具体情况选择不同的人脸识别方法以达到更好的效果。 希望这个代码对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

T.Y.Bao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值