使用opencv和face_recognition进行人脸识别

该代码包含人脸数据采集和人脸识别两部分。

import face_recognition
import cv2 as cv
import numpy as np
import time
import os
class Rec_frg(object):
    #定义全局变量
    def __init__(self):
        self.video_path = r"D:\pythonItems\opencv1\vodeo"
        self.image_data_path = r"D:\pythonItems\opencv1\reg_facedata"
        self.nums = 40
        self.name = []
        self.face_encodings = []
    # 定义函数:用于计算视屏时长
    def video_duration(self,filename):
        cap = cv.VideoCapture(filename)
        if cap.isOpened():
            rate = cap.get(5)
            frame_num = cap.get(7)
            duration = frame_num // rate * 30
            times = duration // 60
            return times
        return -1

    #定义方法:用于收集数据
    def image_datacolloct(self):
        waitKey_count = 0
        #显示该文件夹下的所有内容
        video_path = os.listdir(self.video_path)
        #分别显示每一个视屏
        for path_v in video_path:
            img_num = 1
            # 找到每个视屏的绝对路径
            p = r"{}".format(os.path.join(self.video_path,path_v))
            #调用函数计算视屏时长
            all_times = self.video_duration(p)
            #打开视屏
            capture = cv.VideoCapture(p)
            while True:
                have_landmasks = True
                # 构造保存图片时图片的名称
                name = path_v.split(".")[0] +"_"+ str(img_num)
                # 通过视屏名称,找出每个人的名字
                label_name = path_v.split(".")[0]
                #显示时频每一帧
                ret, frame = capture.read()
                #缩小视屏宽、高为原来的一般
                frame = cv.resize(frame, (0, 0), fx=0.5, fy=0.5)
                #将每一帧的BGR格式转换为RGB格式
                rgb_small_frame_data = frame[:, :, ::-1]
                if ret == False:
                    break
                #找出每一帧中人脸的位置
                face_location = face_recognition.face_locations(rgb_small_frame_data)
                #训练集面部特征编码
                if waitKey_count == 0:
                    face_encoding = face_recognition.face_encodings(rgb_small_frame_data,model= "large")
                    if len(face_encoding) == 0:
                        have_landmasks = False
                    else:
                        have_landmasks = True
                        #将np.array()类型转换为list类型
                        fs = face_encoding[0].tolist()
                        #将数据和标签添加到列表中
                        self.face_encodings.append(fs)
                        self.name.append(label_name)
                        #保存图片
                        cv.imwrite("D:/pythonItems/opencv1/reg_facedata/"+name+".jpg",frame)
                        img_num += 1
                #设置退出条件
                if img_num > self.nums:
                    break
                c = cv.waitKey(1)
                if c == 27:
                    break
                #设置人脸数据获取条件
                if len(face_location) > 0 and have_landmasks == True:
                    waitKey_count += 1
                    print("wait",waitKey_count)
                if waitKey_count == all_times - 1:
                    waitKey_count = 0
                cv.imshow("face", frame)
            #释放资源
            capture.release()
        #显示收集好的数据及标签
        print("location", self.face_encodings)
        print("name", self.name)
        #将数据和标签存入文件中用于识别时使用
        f_data = open("data.txt", "w")
        f_name = open("name.txt","w")
        f_data.write(str(self.face_encodings))
        f_name.write(str(self.name))
        #关闭文件
        f_data.close()
        f_name.close()
        #关闭所有窗口
        cv.destroyAllWindows()
    #定义方法:用于识别
    def face_dances(self,video_name):
        success = 0
        fail = 0
        known_face_encodings = []
        video_capture = cv.VideoCapture(video_name)
        #读取人脸编码数据和标签
        data_file = open("data.txt", "r")
        label_file = open("name.txt","r")
        data = eval(data_file.read())
        #将从文件中读取出的每一张人脸数据的类型转化为 np.array()类型
        for i in data:
            list_to_array = np.array(i)
            known_face_encodings.append(list_to_array)
        known_face_names = eval(label_file.read())
        #关闭文件
        data_file.close()
        label_file.close()

        # 初始化变量
        process_this_frame = True
        time1 = time.time()

        while True:
            face_names = []
            name_str = ""
            # 读取视屏每一帧
            ret, frame = video_capture.read()
            if ret == False:
                break
            # 将视屏款、高缩小一半
            frame = cv.resize(frame, (0, 0), fx=0.5, fy=0.5)

            # 将BGR格式转化为RGB
            rgb_small_frame = frame[:, :, ::-1]

            # 只处理每隔一帧的视频以节省时间
            if process_this_frame:
                # 定位所找到的人脸的位置
                face_locations = face_recognition.face_locations(rgb_small_frame)
                # 对面部特征进行编码
                face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations,model= "large")
                #循环每一个编码好的人脸
                for face_encoding in face_encodings:
                    # 由面部编码匹配人脸
                    matches = face_recognition.compare_faces(known_face_encodings, face_encoding,tolerance=0.5)
                   #计算 "Ture" 的个数
                    true_count = matches.count(True)
                    # print(matches)
                    # print(true_count)
                    #计算要识别的人脸和每个已知人脸之间的距离
                    face_distances = face_recognition.face_distance(known_face_encodings, face_encoding)
                    #找出最小距离的索引
                    best_match_index = np.argmin(face_distances)
                    #判断条件
                    if matches[best_match_index] == False or true_count < self.nums:
                        name = "Unknown"
                        #循环每一张人脸
                        for top, right, bottom, left in face_locations:
                            #画出人脸框
                            cv.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
                            fail += 1
                            # 画出标签背景框
                            cv.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv.FILLED)
                            font = cv.FONT_HERSHEY_DUPLEX
                            #显示标签
                            cv.putText(frame, name, (left + 6, bottom - 6), font, 0.6, (255, 255, 255), 2)
                            if fail == 10:
                                print("识别失败!")
                                fail = 0
                                #计算时间
                                time2 = time.time()
                                spend = time2 - time1
                                print("花费时长:", spend)
                                time1 = time.time()

                    else:
                        #找出距离最小人脸的名字
                        name = known_face_names[best_match_index]
                        face_names.append(name)
                        #将人脸和相应的标签合并,并循环每一张人脸
                        for (top, right, bottom, left),name in zip(face_locations,face_names):
                            # 画出人脸框
                            cv.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)
                            success += 1
                            # 画出标签背景框
                            cv.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 255, 0), cv.FILLED)
                            font = cv.FONT_HERSHEY_DUPLEX
                            #显示标签
                            cv.putText(frame, name, (left + 6, bottom - 6), font, 0.6, (255, 255, 255), 2)
                            if success == 10:
                                for name_one in face_names:
                                    name_str += name_one+"  "
                                print("    识别成功!")
                                print(f"{name_str} 欢迎光临!")
                                time2 = time.time()
                                spend = time2 - time1
                                print("花费时长:", spend)
                                time1 = time.time()
                                success = 0


            # 显示每一帧视屏
            cv.imshow('Video', frame)

            #按ESC键退出
            key = cv.waitKey(1)
            if key == 27:
                break

        # 释放视屏资源,并关闭所有窗口
        video_capture.release()
        cv.destroyAllWindows()


#程序入口
if __name__ == "__main__":
    answer = input("人脸采集请输入0,输入其他进行识别!")
    video1 = "test.mp4"
    video2 = "girl_test.mp4"
    #实例化类
    Facerecognition = Rec_frg()
    #判断采集还是识别
    if answer == "0":
        Facerecognition.image_datacolloct()
        Facerecognition.face_dances(video1)
    else:
        Facerecognition.face_dances(video1)

结果(只显示人脸识别部分):

使用opencv和face_recognition进行人脸识别_第1张图片
使用opencv和face_recognition进行人脸识别_第2张图片

你可能感兴趣的:(机器学习,opencv,计算机视觉,python)