opencv(人脸检测和识别)

Opencv的人脸检测函数,定义了具体可跟踪对象类型的数据文件。

Haar级联分类器,通过对比分析相邻图像区域来判断给定图像或子图像与已知对象是否匹配。

两个图像的相似程度可以通过它们对应特征的欧式距离来度量。距离可能以空间坐标或颜色坐标来定义。类Haar特征是一种用于实现实时人脸跟踪的特征。每个类Haar特征都描述了相邻图像区域的对比模式。例如,边,顶点和细线都能生成具有判断性的特征。

Haar级联级具有尺度不变性,换句话说,它在尺度变化上具有鲁棒性。但是,opencv的Haar级联不具有旋转不变性。

在opencv源代码的副本中会有一个文件夹data/haarcascades,该文件夹包括了所有opencv的人脸检测的xml文件,这些文件可用于检测静止图像,视频和摄像头所得到图像中的人脸。

在开始写代码之前,先要下载opencv源代码包:
这里写图片描述
静态图像中的人脸检测:

import cv2 as cv

filename = 'D:/timg.jpg'

face_cascade = cv.CascadeClassifier('D:/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
//注意用绝对路径就不会报错
img = cv.imread(filename)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
    img = cv.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)

cv.namedWindow('Vikings Detected')
cv.imshow('Vikings Detected', img)
cv.waitKey(0)


图片检测人脸只是开胃菜,真正让我感兴趣的是视频或摄像头下的人脸识别,废话少说:

当然第一步是先学会视频中人脸检测,代码如下:

import numpy as np
import cv2

face_cascade = cv2.CascadeClassifier('D:/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
cap = cv2.VideoCapture(0)
while True:
    ret,img = cap.read()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)
    for (x,y,w,h) in faces:
        cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
    cv2.imshow('img',img)       
    if cv2.waitKey(1) &0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

效果就自己尝试吧。

接下来开始人脸识别了:

1.生成人脸识别数据,代码如下:

扫描二维码关注公众号,回复: 2935311 查看本文章
import cv2
import os

def generate(dirname):

    face_cascade = cv2.CascadeClassifier('D:/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
    eye_cascade = cv2.CascadeClassifier('D:/opencv/sources/data/haarcascades/haarcascade_eye.xml')
    //带眼镜的时候可以用下面这个
    //eye_cascade = cv2.CascadeClassifier('D:/opencv/sources/data/haarcascades/haarcascade_eye_tree_eyeglasses.xml')

    //创建目录
    if(not os.path.isdir(dirname)):
        os.makedirs(dirname) 

    //打开摄像头进行人脸图像采集
    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:
            img = cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2)
            //重设置图像尺寸 200*200
            f = cv2.resize(gray[y:y+h, x:x+w], (200, 200))
            cv2.imwrite(dirname+'/%s.pgm' % str(count), f)
            print(count)
            count += 1

        cv2.imshow("camera", frame)
        if cv2.waitKey(100) & 0xff == ord("q"):
            break
        //下面是你想要多少张图片就停止
        elif count > 20:
            break

    camera.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    generate("D:/data/lijiale") //你生成的图片放在的电脑中的地方

这是我运行上面代码的结果:

2.有了人脸数据后,接下来的是基于Eigenfaces的人脸识别,代码如下:

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)
            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 = ['lijiale']
    [X,y] = read_images(img_path)
    y = np.asarray(y, dtype=np.int32)
    model = cv2.face.EigenFaceRecognizer_create()
    model.train(np.asarray(X), np.asarray(y))

    camera = cv2.VideoCapture(0)
    face_cascade = cv2.CascadeClassifier(
            r'D:/opencv/sources/data/haarcascades/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'D:/data/')  //人脸数据路径img_path

运行上面代码的效果:

遗憾的是我没有尝试收集多人的人脸数据,然后实现多人识别的效果(这个现在没有很空闲,等有时间再来尝试吧,预留个位置以后敲写完整),而且上面只是基于Eigenfaces的人脸识别,当然以后也会尝试下面剩下的两种方法。
opencv3 有三种人脸识别的方法,它们分别基于三种不同的算法:Eigenfaces, Fisherfaces,Local Binary Patter Histogram ( LBPH ) 。这三种方法都有类似的过程,即都是使用了分好类的训练数据集(人脸数据库,每一个人都有很多样本)来进行训练,对图像或视频中检测到的人脸进行分析,并从两方面来确定:是否识别到目标;目标真正被识别到的置信度的度量,也称为置信度评分。
关于Eigenfaces, Fisherfaces,Local Binary, Patter Histogram ( LBPH ) 详解可以自己查阅
最后要补充的一个地方是我在学习过程中有些在有了人脸数据以后要生成csv文件,代码也在这里给出来:

import sys
import os.path

# This is a tiny script to help you creating a CSV file from a face
# database with a similar hierarchie:
#
#  philipp@mango:~/facerec/data/at$ tree
#  .
#  |-- README
#  |-- s1
#  |   |-- 1.pgm
#  |   |-- ...
#  |   |-- 10.pgm
#  |-- s2
#  |   |-- 1.pgm
#  |   |-- ...
#  |   |-- 10.pgm
#  ...
#  |-- s40
#  |   |-- 1.pgm
#  |   |-- ...
#  |   |-- 10.pgm
#

if __name__ == "__main__":

    #if len(sys.argv) != 2:
    #    print "usage: create_csv <base_path>"
    #    sys.exit(1)

    #BASE_PATH=sys.argv[1]
    BASE_PATH="D:/data/lijiale"

    SEPARATOR=";"

    fh = open("D:/data/lijiale/at.txt",'w')

    label = 0
    for dirname, dirnames, filenames in os.walk(BASE_PATH):
        for subdirname in dirnames:
            subject_path = os.path.join(dirname, subdirname)
            for filename in os.listdir(subject_path):
                abs_path = "%s/%s" % (subject_path, filename)
                print ("%s%s%d" % (abs_path, SEPARATOR, label))
                fh.write(abs_path)
                fh.write(SEPARATOR)
                fh.write(str(label))
                fh.write("\n")      
            label = label + 1
    fh.close()

这个代码是opencv源码包里面自带的,你需要的是改下路径。
感谢你们的支持,如需转载请标注作者。

猜你喜欢

转载自blog.csdn.net/mrjiale/article/details/81190139