上一節講到人臉檢測,如今講一下人臉識別。具體是經過程序採集圖像並進行訓練,而且基於這些訓練的圖像對人臉進行動態識別。算法
人臉識別前所須要的人臉庫能夠經過兩種方式得到:1.本身從視頻獲取圖像 2.從人臉數據庫免費得到可用人臉圖像,如ORL人臉庫(包含40我的每人10張人臉,總共400張人臉),ORL人臉庫中的每一張圖像大小爲92x112。若要對這些樣本進行人臉識別必需要在包含人臉的樣本圖像上進行人臉識別。這裏提供本身準備圖像識別出本身的方法。數據庫
1.採集人臉信息:經過攝像頭採集人臉信息,10張以上便可,把圖像大小調整爲92x112,保存在一個指定的文件夾,文件名後綴爲.png數組
def generator(data): ''' 打開攝像頭,讀取幀,檢測該幀圖像中的人臉,並進行剪切、縮放 生成圖片知足如下格式: 1.灰度圖,後綴爲 .png 2.圖像大小相同 params: data:指定生成的人臉數據的保存路徑 ''' name=input('my name:') #若是路徑存在則刪除路徑 path=os.path.join(data,name) if os.path.isdir(path): shutil.rmtree(path) #建立文件夾 os.mkdir(path) #建立一個級聯分類器 face_casecade=cv2.CascadeClassifier('../haarcascades/haarcascade_frontalface_default.xml') #打開攝像頭 camera=cv2.VideoCapture(0) cv2.namedWindow('Dynamic') #計數 count=1 while(True): #讀取一幀圖像 ret,frame=camera.read() if ret: #轉換爲灰度圖 gray_img=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) #人臉檢測 face=face_casecade.detectMultiScale(gray_img,1.3,5) for (x,y,w,h) in face: #在原圖上繪製矩形 cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2) #調整圖像大小 new_frame=cv2.resize(frame[y:y+h,x:x+w],(92,112)) #保存人臉 cv2.imwrite('%s/%s.png'%(path,str(count)),new_frame) count+=1 cv2.imshow('Dynamic',frame) #按下q鍵退出 if cv2.waitKey(100) & 0xff==ord('q'): break camera.release() cv2.destroyAllWindows()
該程序運行後會在指定的data路徑下建立一個你輸入的人名的文件夾用於存放採集到的圖像,在這裏我輸入了wjy,結果如圖app
2.人臉識別ide
OpenCV有3中人臉識別方法,分別基於三個不一樣算法,分別爲Eigenfaces,Fisherfaces和Local Binary Pattern Histogram函數
這些方法都有相似的一個過程,即先對數據集進行訓練,對圖像或視頻中的人臉進行分析,而且從兩個方面肯定:1.是否識別到對應的目標,2.識別到的目標的置信度,在實際中經過閾值進行篩選,置信度高於閾值的人臉將被丟棄字體
這裏介紹一下利用特徵臉即Eigenfaces進行人臉識別算法,特徵臉法本質上就是PCA降維,基本思路是先把圖像灰度化,轉化爲單通道,再將它首位相接轉換爲列向量,假設圖像的大小是20*20的,那麼這個向量就是400維,可是維度過高算法複雜度也會升高,因此須要降維,再使用簡單排序便可spa
#載入圖像 讀取ORL人臉數據庫,準備訓練數據 def LoadImages(data): ''' 加載圖片數據用於訓練 params: data:訓練數據所在的目錄,要求圖片尺寸同樣 ret: images:[m,height,width] m爲樣本數,height爲高,width爲寬 names:名字的集合 labels:標籤 ''' images=[] names=[] labels=[] label=0 #遍歷全部文件夾 for subdir in os.listdir(data): subpath=os.path.join(data,subdir) #print('path',subpath) #判斷文件夾是否存在 if os.path.isdir(subpath): #在每個文件夾中存放着一我的的許多照片 names.append(subdir) #遍歷文件夾中的圖片文件 for filename in os.listdir(subpath): imgpath=os.path.join(subpath,filename) img=cv2.imread(imgpath,cv2.IMREAD_COLOR) gray_img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #cv2.imshow('1',img) #cv2.waitKey(0) images.append(gray_img) labels.append(label) label+=1 images=np.asarray(images) #names=np.asarray(names) labels=np.asarray(labels) return images,labels,names #檢驗訓練結果 def FaceRec(data): #加載訓練的數據 X,y,names=LoadImages(data) #print('x',X) model=cv2.face.EigenFaceRecognizer_create() model.train(X,y) #打開攝像頭 camera=cv2.VideoCapture(0) cv2.namedWindow('Dynamic') #建立級聯分類器 face_casecade=cv2.CascadeClassifier('../haarcascades/haarcascade_frontalface_default.xml') while(True): #讀取一幀圖像 #ret:圖像是否讀取成功 #frame:該幀圖像 ret,frame=camera.read() #判斷圖像是否讀取成功 #print('ret',ret) if ret: #轉換爲灰度圖 gray_img=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) #利用級聯分類器鑑別人臉 faces=face_casecade.detectMultiScale(gray_img,1.3,5) #遍歷每一幀圖像,畫出矩形 for (x,y,w,h) in faces: frame=cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2) #藍色 roi_gray=gray_img[y:y+h,x:x+w] try: #將圖像轉換爲寬92 高112的圖像 #resize(原圖像,目標大小,(插值方法)interpolation=,) roi_gray=cv2.resize(roi_gray,(92,112),interpolation=cv2.INTER_LINEAR) params=model.predict(roi_gray) print('Label:%s,confidence:%.2f'%(params[0],params[1])) ''' putText:給照片添加文字 putText(輸入圖像,'所需添加的文字',左上角的座標,字體,字體大小,顏色,字體粗細) ''' cv2.putText(frame,names[params[0]],(x,y-20),cv2.FONT_HERSHEY_SIMPLEX,1,255,2) except: continue cv2.imshow('Dynamic',frame) #按下q鍵退出 if cv2.waitKey(100) & 0xff==ord('q'): break camera.release() cv2.destroyAllWindows()
在程序中,咱們用cv2.face.EigenFaceRecognizer_create()建立人臉識別的模型,經過圖像數組和對應標籤數組來訓練模型,該函數有兩個重要的參數,1.保留主成分的數目,2.指定的置信度閾值,爲一個浮點型。code
下面就是基本重複人臉檢測的相關操做,經過檢測到視頻中的人臉進行人臉識別,有以下兩個步驟:視頻
1.將檢測到的人臉圖像調整爲92x112,即須要和訓練的圖像的尺寸相同
2.調用predict()函數進行人臉預測,該函數會返回兩個元素的數組,第一個是識別個體的標籤,第二個是置信度,越小匹配度越高,0表示徹底匹配,須要瞭解的是不一樣算法的置信度評分機制不一樣。
附上結果圖
這裏附上所有源代碼「
# -*- coding: utf-8 -*- """ Created on Sat Oct 27 11:43:47 2018 @author: Administrator """ ''' 調用opencv的庫實現人臉識別 ''' import cv2 import numpy as np import os import shutil #採集本身的人臉數據 def generator(data): ''' 打開攝像頭,讀取幀,檢測該幀圖像中的人臉,並進行剪切、縮放 生成圖片知足如下格式: 1.灰度圖,後綴爲 .png 2.圖像大小相同 params: data:指定生成的人臉數據的保存路徑 ''' name=input('my name:') #若是路徑存在則刪除路徑 path=os.path.join(data,name) if os.path.isdir(path): shutil.rmtree(path) #建立文件夾 os.mkdir(path) #建立一個級聯分類器 face_casecade=cv2.CascadeClassifier('../haarcascades/haarcascade_frontalface_default.xml') #打開攝像頭 camera=cv2.VideoCapture(0) cv2.namedWindow('Dynamic') #計數 count=1 while(True): #讀取一幀圖像 ret,frame=camera.read() if ret: #轉換爲灰度圖 gray_img=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) #人臉檢測 face=face_casecade.detectMultiScale(gray_img,1.3,5) for (x,y,w,h) in face: #在原圖上繪製矩形 cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2) #調整圖像大小 new_frame=cv2.resize(frame[y:y+h,x:x+w],(92,112)) #保存人臉 cv2.imwrite('%s/%s.png'%(path,str(count)),new_frame) count+=1 cv2.imshow('Dynamic',frame) #按下q鍵退出 if cv2.waitKey(100) & 0xff==ord('q'): break camera.release() cv2.destroyAllWindows() #載入圖像 讀取ORL人臉數據庫,準備訓練數據 def LoadImages(data): ''' 加載圖片數據用於訓練 params: data:訓練數據所在的目錄,要求圖片尺寸同樣 ret: images:[m,height,width] m爲樣本數,height爲高,width爲寬 names:名字的集合 labels:標籤 ''' images=[] names=[] labels=[] label=0 #遍歷全部文件夾 for subdir in os.listdir(data): subpath=os.path.join(data,subdir) #print('path',subpath) #判斷文件夾是否存在 if os.path.isdir(subpath): #在每個文件夾中存放着一我的的許多照片 names.append(subdir) #遍歷文件夾中的圖片文件 for filename in os.listdir(subpath): imgpath=os.path.join(subpath,filename) img=cv2.imread(imgpath,cv2.IMREAD_COLOR) gray_img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #cv2.imshow('1',img) #cv2.waitKey(0) images.append(gray_img) labels.append(label) label+=1 images=np.asarray(images) #names=np.asarray(names) labels=np.asarray(labels) return images,labels,names #檢驗訓練結果 def FaceRec(data): #加載訓練的數據 X,y,names=LoadImages(data) #print('x',X) model=cv2.face.EigenFaceRecognizer_create() model.train(X,y) #打開攝像頭 camera=cv2.VideoCapture(0) cv2.namedWindow('Dynamic') #建立級聯分類器 face_casecade=cv2.CascadeClassifier('../haarcascades/haarcascade_frontalface_default.xml') while(True): #讀取一幀圖像 #ret:圖像是否讀取成功 #frame:該幀圖像 ret,frame=camera.read() #判斷圖像是否讀取成功 #print('ret',ret) if ret: #轉換爲灰度圖 gray_img=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) #利用級聯分類器鑑別人臉 faces=face_casecade.detectMultiScale(gray_img,1.3,5) #遍歷每一幀圖像,畫出矩形 for (x,y,w,h) in faces: frame=cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2) #藍色 roi_gray=gray_img[y:y+h,x:x+w] try: #將圖像轉換爲寬92 高112的圖像 #resize(原圖像,目標大小,(插值方法)interpolation=,) roi_gray=cv2.resize(roi_gray,(92,112),interpolation=cv2.INTER_LINEAR) params=model.predict(roi_gray) print('Label:%s,confidence:%.2f'%(params[0],params[1])) ''' putText:給照片添加文字 putText(輸入圖像,'所需添加的文字',左上角的座標,字體,字體大小,顏色,字體粗細) ''' cv2.putText(frame,names[params[0]],(x,y-20),cv2.FONT_HERSHEY_SIMPLEX,1,255,2) except: continue cv2.imshow('Dynamic',frame) #按下q鍵退出 if cv2.waitKey(100) & 0xff==ord('q'): break camera.release() cv2.destroyAllWindows() if __name__=='__main__': data='./face' #generator(data) FaceRec(data)
2018.10.28