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()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章