Python 使用Opencv实现人脸识别

本人新书《玩转Python网络爬虫》,可在天猫、京东等商城搜索查阅,项目深入浅出,适合爬虫初学者或者是已经有一些网络爬虫编写经验,但希望更加全面、深入理解Python爬虫的开发人员。
这里写图片描述

———-欢迎加入学习交流QQ群:657341423


要实现人面识别,首先安装opencv的opencv_contrib组件。首先在https://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv下载相关组件。
这里写图片描述
在CMD窗口下先卸载原有的opencv,然后安装opencv_contrib的安装包。

pip uninstall opencv_python-3.4.1-cp35-cp35m-win_amd64.whl
pip install opencv_python-3.4.1+contrib-cp35-cp35m-win_amd64.whl

完成上述安装后,接着实现人面识别,首先装备人面资料,如图所示:
这里写图片描述
文件夹alin和xyjw是分别存放人物头像图片,分别代表人物alin和xyjw,图片格式为pgm格式。
由于一开始是没有人物头像图片,于是,我们先用人面检测获取人物头像图片,代码如下:

import cv2
def get_face_data():
    # 加载Haar级联数据文件,用于检测人面
    face_cascade = cv2.CascadeClassifier('cascades/haarcascade_frontalface_default.xml')
    eye_cascade = cv2.CascadeClassifier('./cascades/haarcascade_eye.xml')
    camera = cv2.VideoCapture(0)
    count = 1
    while True:
        ret, frame = camera.read()
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 人面识别。detectMultiScale参数说明:
        # gray: 进行检测的图像, 这里是转换后的。
        # scaleFactor: 官网文档说是每次图片缩小的比例, 其实可以这么理解, 距离相机不同的距离, 物体大小是不一样的, 在物体大小不一致的情况下识别一个东西是不方便的, 这就需要进行多次的缩放, 这就是这个参数的作用。
        # minNeighbors: 可以理解为每次检测时, 对检测点(Scale)周边多少有效点同时检测, 因为可能选取的检测点大小不足而导致遗漏。
        # minSize: 检测点的最小值, 或者说就是检测点的最终值。
        faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5, minSize=(5,5))
        # 画出面部位置
        for (x, y, w, h) in faces:
            img = cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
            # 根据检查的位置截取图片并调整截取后的图片大小
            f = cv2.resize(gray[y:y+h, x:x+w], (200, 200))
            # 保存图片
            cv2.imwrite('auto/alin/%s.pgm' %(str(count)),f)
            count += 1
        cv2.imshow('pic', frame)
        # 停止程序
        if cv2.waitKey(120) & 0xff == ord('q'):
            break
    camera.release()
    cv2.destroyAllWindows()

if __name__=='__main__':
    get_face_data()

人面图片的数据获取后,我们利用这些数据实现人面识别,其功能代码如下:

import sys,os,cv2
import numpy as np
# 加载面部资料
def read_images(path, sz=None):
    """Reads the images in a given folder, resizes images on the fly if size is given.
    Args:
        path: 人面数据所在的文件路径
        sz: 图片尺寸设置
    Returns:
        A list [X,y]
            X: 图片信息
            y: 图片的读取顺序
    """
    c = 0
    X,y = [], []
    for dirname, dirnames, filenames in os.walk(path):
        for subdirname in dirnames:
            subject_path = os.path.join(dirname, subdirname)
            for filename in os.listdir(subject_path):
                filepath = os.path.join(subject_path, filename)
                im = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)
                if (sz is not None):
                    im = cv2.resize(im, sz)
                X.append(np.asarray(im, dtype=np.uint8))
                y.append(c)
            c = c+1
    return [X,y]

# 面部识别
def face_rec():
    names = ['Alin', 'XyJw', 'Jack']
    [X, y] = read_images('E:\\auto\\')
    # 创建识别模型,使用EigenFace算法识别,Confidence评分低于4000是可靠
    # model = cv2.face.EigenFaceRecognizer_create()
    # 创建识别模型,使用LBPHFace算法识别,Confidence评分低于50是可靠
    # model = cv2.face.LBPHFaceRecognizer_create()
    # 创建识别模型,使用FisherFace算法识别,Confidence评分低于4000是可靠
    model = cv2.face.FisherFaceRecognizer_create()
    # 训练模型
    # train函数参数:images, labels,两参数必须为np.array格式,而且labels的值必须为整型
    model.train(np.array(X), np.array(y))
    # 开启摄像头
    camera = cv2.VideoCapture(0)
    # 加载Haar级联数据文件,用于检测人面
    face_cascade = cv2.CascadeClassifier('cascades/haarcascade_frontalface_default.xml')
    while (True):
        # 检测摄像头的人面
        read, img = camera.read()
        faces = face_cascade.detectMultiScale(img, 1.3, 5)
        # 将检测的人面进行识别处理
        for (x, y, w, h) in faces:
            # 画出人面所在位置并灰度处理
            img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            roi = gray[x:x + w, y:y + h]

            # 将检测的人面缩放200*200大小,用于识别
            # cv2.INTER_LINEAR是图片变换方式,其余变换方式如下:
            # INTER_NN - 最近邻插值。
            # INTER_LINEAR - 双线性插值(缺省使用)
            # INTER_AREA - 使用象素关系重采样。当图像缩小时候,该方法可以避免波纹出现。
            # INTER_CUBIC - 立方插值。
            roi = cv2.resize(roi, (200, 200), interpolation=cv2.INTER_LINEAR)

            # 检测的人面与模型进行匹配识别
            params = model.predict(roi)
            print("Label: %s, Confidence: %.2f" % (params[0], params[1]))
            # 将识别结果显示在摄像头上
            # cv2.FONT_HERSHEY_SIMPLEX 定义字体
            # cv2.putText参数含义:图像,文字内容, 坐标 ,字体,大小,颜色,字体厚度
            # 如果要输出中文字,可参考https://blog.csdn.net/m0_37606112/article/details/78511381
            cv2.putText(img, names[params[0]], (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)

        cv2.imshow("camera", img)
        if cv2.waitKey(120) & 0xff == ord("q"):
            break
    cv2.destroyAllWindows()


if __name__ == "__main__":
    face_rec()

函数read_images是分别读取文件夹alin和xyjw的图片数据和文件夹读取顺序。文件夹读取顺序是先读取alin的图片数据,然后在读取xyjw的图片数据,最后将两者的图片数据写入列表,因此这里存在一个先后顺序问题。

函数face_rec是调用函数read_images,因此函数read_images的返回值与变量names的值要一一对应,比如函数read_images的返回值第一个人面数据是alin,变量names的第一个值为alin。否则对应不上就会将名字写错。

人面识别也是通过摄像头来获取人物头像,然后根据算法与文件夹alin和xyjw的头像进行匹配对比。匹配成功会返回Label和Confidence,其中Label代表资料加载顺序,即函数read_images读取文件夹alin和xyjw的读取顺序。Confidence是识别评分,每种算法有一定的范围值,符合范围值才算匹配成功。


参考资料:OpenCV 3计算机视觉 Python语言实现第二版

猜你喜欢

转载自blog.csdn.net/huangzhang_123/article/details/80623771