只用opencv-python进行人脸识别,比face_recognition识别正确率高!完整代码!!!

这篇文章的话题依然是人脸识别,不过仅仅使用了opencv-python以及opencv-contrib-python这两个包,而且就我做的测试用例来看识别的正确率比face_recognition还要更高,话不多说,咱们这就开始。

人脸检测

要想做人脸识别,人脸检测必须是要做的,毕竟识别也得你检测到人脸之后才能辨别。那么如何检测到人脸呢?提取出图像的细节对产生稳定分类结果很重要,这些提取的结果被称为特征,专业的表述为:从图像数据中提取特征。虽然任意像素都可以能影响多个特征,但特征应该比像素少得多。两个图像的相似程度可以通过它们对应特征的欧氏距离来度量。 Haar 特征是一种用于实现实时人脸跟踪的征。每一个 Haar 特征都描述了相邻图像区域的对比模式。例如,边、顶点和细线都能生成具有判别性的特征。获取 Haar 特征的方法有很多种,这里我用的是安装opencv以后opencv安装目录里的部分xml文件获取的,如果你不想安装opencv的话,也可以到文末直接下载我打包好的文件。如果你已经安装了opencv,找到你的安装目录,一般如下图:


接着打开sources/data/haarcascades文件夹,你会看到下图:

我提供的资源就是上图所示的所有xml文件,不用再在电脑上安装opencv了。默认的人脸检测器是haarcascade_frontalface_default.xml。当然这个是可以更改的,使用的方法如下:

face_detector = cv2.CascadeClassifier('D:/OPENCV/sources/data/haarcascades/haarcascade_frontalface_default.xml')

for i in range(len(person_list)):

    person_name = os.listdir("faces/" + "person_" + str(i + 1))

    img_path = "faces/" + "person_" + str(i + 1) + "/" + person_name[0]

    # opencv人脸检测

    PIL_img = Image.open(img_path).convert('L')

    img_numpy = np.array(PIL_img, 'uint8')

    faces = face_detector.detectMultiScale(img_numpy)

    #print(len(faces))

    for x,y,w,h in faces:

        face_sampes.append(img_numpy[y:y+h, x:x+w])

        ids.append(i + 1)

face_sampes,ids是训练数据用到的两个参数,face_sampes是人脸特征矩阵,ids是每个人脸对应的id。

训练数据

这部分比较简单,如果有异常应该是未安装opencv-contrib-python导致的,直接上代码了。

opencv_recognizer = cv2.face.LBPHFaceRecognizer_create()

opencv_recognizer.train(face_sampes, np.array(ids))

opencv_recognizer.write('train/train.yml')

执行完代码之后会在当前目录生成train.yml文件,人脸识别的时候会用到。

人脸识别

相信大家都已经看到了我在训练数据时使用的代码,其中opencv_recognizer是比较重要的,当然其实是cv2.face.LBPHFaceRecognizer_create()比较重要。这个人脸识别主要用的是LBPH算法**。它将检测到的人脸分为小单元,并将其与模型中的对应单元进行比较,对每个区域的匹配值产生一个直方图。由于这种方法的灵活性,LBPH是唯一允许模型样本人脸和检测到的人脸在形状、大小上可以不同的人脸识别算法。具体的用法见以下代码。

opencv_recognizer.read('train/train.yml')

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

new_faces = face_detector.detectMultiScale(gray)

for x, y, w, h in new_faces:

        cv2.rectangle(img, (x,y), (x+w, y+h), (0, 255, 0), 2)

        id, confidence = opencv_recognizer.predict(gray[y:y+h, x:x+w])

        cv2.putText(img, face_names[id-1]+str(int(confidence)), (x + 6, y + h - 6), font, 1.0, (255, 255, 255), 1)

识别的主体在predict方法中,它的返回值一个是id,一个是置信度。id是与人脸一一对应的,好的置信度要低于50,越小越好。高于80的置信度都是较差的。然后由于我可以根据id得到人的姓名,所以我可以直接把人名实时显示在摄像头视频中,如何做到的欢迎移步这里看我的人脸照片目录结构,谢谢大家。

完整代码附上:

import cv2

import os

import numpy as np

from PIL import Image

face_detector = cv2.CascadeClassifier('D:/OPENCV/sources/data/haarcascades/haarcascade_frontalface_default.xml')

face_sampes = []

ids = []

font = cv2.FONT_HERSHEY_DUPLEX

face_names = []

person_list = os.listdir("faces/")

for i in range(len(person_list)):

    person_name = os.listdir("faces/" + "person_" + str(i + 1))

    img_path = "faces/" + "person_" + str(i + 1) + "/" + person_name[0]

    face_names.append(person_name[0][:person_name[0].index(".")])

    # opencv人脸检测

    PIL_img = Image.open(img_path).convert('L')

    img_numpy = np.array(PIL_img, 'uint8')

    faces = face_detector.detectMultiScale(img_numpy)

    for x,y,w,h in faces:

        face_sampes.append(img_numpy[y:y+h, x:x+w])

        ids.append(i + 1)

opencv_recognizer = cv2.face.LBPHFaceRecognizer_create()

opencv_recognizer.train(face_sampes, np.array(ids))

opencv_recognizer.write('train/train.yml')

camera = cv2.VideoCapture(0)

while True:

    success, img = camera.read()

    opencv_recognizer.read('train/train.yml')

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    new_faces = face_detector.detectMultiScale(gray)

    for x, y, w, h in new_faces:

        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)

        id, confidence = opencv_recognizer.predict(gray[y:y + h, x:x + w])

        cv2.putText(img, face_names[id - 1] + str(int(confidence)), (x + 6, y + h - 6), font, 1.0, (255, 255, 255), 1)

    cv2.imshow('camera', img)

    cv2.waitKey(0)

    cv2.destroyAllWindows()


你可能感兴趣的:(只用opencv-python进行人脸识别,比face_recognition识别正确率高!完整代码!!!)