OpenCV+Python 人脸识别 | Haar级联(检测)& Eigenfaces算法(识别)

本文包括两部分:人脸检测、人脸识别。其中人脸检测主要采用了Haar级联分类器,采用Eigenfaces算法实现了人脸识别。

注:环境为OpenCV3与Python3.6。


目录:


人脸检测

首先,看下Haar级联分类器,Haar特征都描述了相邻图像区域的对比模式。例如,边、顶点和细线都能生成具有判别性的特征。

  • 具有尺度不变性;
  • 不具有旋转不变性。

OpenCV3有个data/haarcascades文件夹,包含了所有OpenCV的人脸检测XML文件。

  • haarcascade_eye.xml
  • haarcascade_eye_tree_eyeglasses.xml
  • haarcascade_frontalcatface.xml
  • haarcascade_frontalcatface_extended.xml
  • haarcascade_frontalface_alt.xml
  • haarcascade_frontalface_alt_tree.xml
  • haarcascade_frontalface_alt2.xml
  • haarcascade_frontalface_default.xml
  • haarcascade_fullbody.xml
  • haarcascade_lefteye_2splits.xml
  • haarcascade_licence_plate_rus_16stages.xml
  • haarcascade_lowerbody.xml
  • haarcascade_profileface.xml
  • haarcascade_righteye_2splits.xml
  • haarcascade_russian_plate_number.xml
  • haarcascade_smile.xml
  • haarcascade_upperbody.xml

detectMultiScale(gray,
1.3, # scaleFactor图像的压缩率
5 # minNeighbors人脸矩形保留近邻数目的最小值
)

根据检测结果,可以看到,OpenCV人脸检测效果好像并不太好。


这里写图片描述

静态图片检测

OpenCV自带的haarcascade_frontalface_default.xml,在cv2/data/目录下能找到,或者直接使用EveryThing类似的检索工具磁盘检索一下。

static_face_detect.py

# -*- coding: utf-8 -*-
import cv2

def detect(filename):
    face_cascade = cv2.CascadeClassifier(
            r'C:\AppInstall\Anaconda3\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml')

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

    faces = face_cascade.detectMultiScale(gray,1.3,5)

    for (x,y,w,h) in faces:
        img = cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0),2)

    cv2.namedWindow('Person Detected!')
    cv2.imshow('Person Detected!',img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

if __name__ == '__main__':
    detect(r'C:\Users\qingdujun\Desktop\huge.jpg')

视频流实时检测

视频流实时检测与静态图片技术差不多,只不过多了一个视频帧读取的过程。当然,以下也检测了一下眼睛的位置。

video_face_detect.py

# -*- coding: utf-8 -*-
import cv2

def detect():
    face_cascade = cv2.CascadeClassifier(
            r'C:\AppInstall\Anaconda3\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml')
    eye_cascade = cv2.CascadeClassifier(
            r'C:\AppInstall\Anaconda3\Lib\site-packages\cv2\data\haarcascade_eye.xml')

    camera = cv2.VideoCapture(0)
    while(True):
        ret,frame = camera.read()
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        #检测人脸
        faces = face_cascade.detectMultiScale(gray, 1.3,5)
        for(x,y,w,h) in faces:
            cv2.rectangle(frame, (x,y), (x+w, y+h), (255,0,0),2)
        #检测眼睛
        eyes = eye_cascade.detectMultiScale(gray,1.3,5)
        for (ex,ey,ew,eh) in eyes:
            cv2.rectangle(frame, (ex,ey),(ex+ew,ey+eh),(0,255,0),2)

        cv2.imshow('camera',frame)

        if cv2.waitKey(1000//12) & 0xff == ord('q'):
            break
    camera.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    detect()

人脸识别

OpenCV3 有三种人脸识别 的方法,它们分别是:

  • Eigenfaces
  • Fisherfaces
  • Local Binary Pattern Histogram(LBPH)

以下演示一下Eigenfaces算法。其他算法只需要修改一下model即可,当然也需要一些小调整。

提示:Windows下,如果使用pip install opencv-python安装OpenCV可能会cv2.face找不到,需要使用pip install opencv-contrib-python重新安装。

采集人脸数据

采集不同人脸时,注意修改cv2.imwrite(r'./data/at/David/%s.pgm' % str(count), f)此处的名称David

generate_face_from_video.py

# -*- coding: utf-8 -*-
import cv2

def generate():
    face_cascade = cv2.CascadeClassifier(
            r'C:\AppInstall\Anaconda3\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml')

    camera = cv2.VideoCapture(0)
    count = 0
    while (True):
        ret, frame = camera.read()
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 检测人脸
        faces = face_cascade.detectMultiScale(gray, 1.3, 5)
        for (x, y, w, h) in faces:
            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(r'./data/at/David/%s.pgm' % str(count), f)
            count += 1

        cv2.imshow("camera", frame)

        if cv2.waitKey(1000 // 12) & 0xff == ord("q"):
            break

    camera.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    generate()

你应该先创建好文件夹,按照下图目录格式。

这里写图片描述

Eigenfaces算法人脸识别

首先,载入图片并将其与Label一一对应。比如,读取David文件夹时,c=0不变化,当读取第二个人脸所在文件夹时c+1,以此类推,最终将c作为下标,显示names[]值。人脸识别包括两个过程,

  • 对采集好的人脸进行训练
  • 对新采集的人脸进行预测

在main中,你应该传入路径r'./data/at/',read_images函数才能正常运行。

face_recognition.py

# -*- coding: utf-8 -*-
import cv2,os,sys
import numpy as np

def read_images(path, sz = None):
    c = 0
    X, y = [], []

    for dirname, dirnames, filenames in os.walk(path):
        for subdirname in dirnames:
            subject_path = os.path.join(dirname, subdirname)#./data/at/*
            for filename in os.listdir(subject_path):
                try:
                    if not filename.endswith('.pgm'):
                        continue
                    filepath = os.path.join(subject_path, filename)
                    im = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)
                    if sz is not None:
                        im = cv2.resize(im,(200,200))
                    X.append(np.asarray(im, dtype=np.uint8))
                    y.append(c)
                except:
                    print("Unexpected error:",sys.exc_info()[0])
            c = c + 1
    return [X, y]

def face_rec(img_path):
    names = ['David','Guan-h','Type-q']
    [X,y] = read_images(img_path)
    y = np.asarray(y, dtype=np.int32)
    model = cv2.face.EigenFaceRecognizer_create()
#    model = cv2.face.EigenFaceRecognizer()
    #pip install opencv-contrib-python
    model.train(np.asarray(X), np.asarray(y))

    camera = cv2.VideoCapture(0)
    face_cascade = cv2.CascadeClassifier(
            r'C:\AppInstall\Anaconda3\Lib\site-packages\cv2\data\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]
            try:
                roi = cv2.resize(roi, (200, 200), interpolation=cv2.INTER_LINEAR)
                params = model.predict(roi)
                print("Label: %s, Confidence: %.2f" % (params[0], params[1]))
                cv2.putText(img, names[params[0]], (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2)
            except:
                continue
        cv2.imshow("camera", img)
        if cv2.waitKey(1000 // 12) & 0xff == ord('q'):
            break
    cv2.destroyAllWindows()

if __name__ == "__main__":
    face_rec(r'./data/at/')

References:
[1] 刘波[译]. OpenCV 3计算机视觉:Python语言实现(原书第2版)[M]. 北京:机械工业出版社, 2016.


@qingdujun
2018-5-28 于 北京 怀柔

猜你喜欢

转载自blog.csdn.net/u012339743/article/details/80470563