OpenCV3计算机视觉:Python实现 读书笔记-第五章

第五章

人脸检测和识别

Haar级联
  • Haar级联具有尺度不变性(不同尺度的两幅图像也有相似特征)
  • OpenCV的Haar级联不具有旋转不变形
  • 类Harr特征是一种用于实现实时人脸跟踪的特征,每个类Haar特征都描述了相邻图像区域的对比模式
  • 图像的特征集合称为级联
获取Harr级联数据
  • OpenCV源代码的副本中文件夹:data/haarcascades包含了OpenCV所有人脸检测的XML文件,可检测图像、视频、摄像头所得图像的人脸(需要正面,直立的人脸图像)
使用OpenCV人脸检测
对图片进行人脸检测
import cv2

filename = './5_1.jpg'

def detect(filename):
    face_cascade = cv2.CascadeClassifier('./cascades/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('Detected!')
    cv2.imshow('Detected!',img)
    cv2.waitKey(0)

detect(filename)
视频中的人脸检测
import cv2
def detect():
    # 加载Haar级联文件
    face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')
    eye_cascade = cv2.CascadeClassifier('./cascades/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 ) # 在源图像中画框

            img = frame[y:y+h , x:x+w]
            roi_gray = gray[y:y+h , x:x+w]

            # 人脸检测时,后两个参数默认即可,但眼睛是一个比较小的人脸特征,且鼻子等的随机阴影都会产生假阳性
            #通过限制对人眼搜索的最小尺寸40*40像素,可去除所有假阳性
            eyes = eye_cascade.detectMultiScale( roi_gray , 1.03 , 5 , 0 , (40,40) )
            for ( ex , ey , ew , eh ) in eyes:
                cv2.rectangle( img , (ex,ey) , (ex+ew , ey+eh) , (0,255,0) , 2 ) # 人眼区域画框

        cv2.imshow("camera",frame)
        if cv2.waitKey( 5 ) & 0xff == ord("q"): # 等待键盘事件(每5ms),q退出
            break

    camera.release()
    cv2.destroyAllWindows()
if __name__ == "__main__":
    detect()

[注]:灰度图像中进行人脸检测,源图像中画框(涉及两张图片)

人脸识别
  • OpenCV的三种人脸识别方法:Eigenfaces , Fisherfaces , Local Binary Pattern Histogram(LBPH)
    • LBPH是唯一允许模型样本人脸和检测到的人脸在形状,大小可以不同的人脸识别算法
生成人脸识别数据
  • 打开摄像头获取人脸并存储为.pgm格式
import cv2

def generate():
    face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')
    #eye_cascade = cv2.CascadeClassifier('/cascades/haarcascade_eye.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:
            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('./data/at/jm/%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()
生成.csv文件
  • 基于逗号分隔值的(.CSV)文件,根据ID记录样本图像路径(最后的数字表示ID)
def generate_csv(id=0): #在csv文件中加入用户id条目
    count = 0
    fout = open('a.csv', 'w', encoding='utf-8')
    for i in range(21):
        fout.write('jm/%s.pgm;'%str(i))
        fout.write('%s'%str(id))
        fout.write('\n')

if __name__ == "__main__":
    generate_csv()
加载数据识别人脸
  • 基于Eigenfaces的人脸识别
    • 书中的实现未用到.csv,所有就自己改动了一下,但是写的比较僵硬。
    • 先给出根目录,然后加上.csv文件中的每个.pgm图像的路径,得到完整路径并读取图片加入图像数组中,截取.csv的每个条目分号后位数(ID),加入标签数组中。
import cv2
import os
import sys
import numpy as np
import csv

def parse_csv(): # 逐行解析csv文件
    csv_file = open("./a.csv")
    csv_lines = csv.reader(csv_file)
    path = []
    tot = 0
    for line in csv_lines:
        path.append(line)
        tot += 1
    return path

def read_images(root):
    path = parse_csv()
    X , y = [] , [] # x: 图像数组  y: 标签数组
    i = 0
    tot = len(path)
    while i < tot :
        pic_path = root + path[i][0][0:-2]    #获取用户图片集完整路径
        #print(pic_path)
        try:
            im = cv2.imread(pic_path, cv2.IMREAD_GRAYSCALE)
            if im is not None:
                im = cv2.resize(im, (200, 200))
            else:
                continue

            X.append(np.asarray(im, dtype=np.uint8))
            id = path[i][0].split(';')[1:]
           # print(id)
            y.append(id)    # ID
        except IOError as e:
            print("I/O error({0}):{1}".format(e.errno, e.strerror))
        except:
            print("Unexpected error:", sys.exc_info()[0])
            raise
        i += 1
    return [X,y]

def face_rec():
    filepath = 'F:/pyCharm/cv/chapter5/data/at/'
    names = ['Dave','Jane','Jack']

    [X,y] = read_images(filepath)

    y = np.asarray( y , dtype=np.int32 )

    model = cv2.face.EigenFaceRecognizer_create()   # 基于Eigenfaces的人脸识别
   # model = cv2.face.LBPHFaceRecognizer_create()   # 基于LBPH的人脸识别
    model.train( np.asarray(X) , np.asarray(y) )    # train()中传入图像数组,标签数组(ID)

    face_cascade = cv2.CascadeClassifier('F:\pyCharm\cv\chapter5\cascades\haarcascade_frontalface_default.xml')
    camera = cv2.VideoCapture(0)
    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) 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
    camera.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    face_rec()

猜你喜欢

转载自blog.csdn.net/FrankAx/article/details/104929450