什么是人臉識別
人臉識別,是基于人的臉部特征信息進行身份識別的一種生物識別技術(shù)。用攝像機或攝像頭采集含有人臉的圖像或視頻流,并自動在圖像中檢測和跟蹤人臉,進而對檢測到的人臉進行臉部識別的一系列相關(guān)技術(shù),通常也叫做人像識別、面部識別。
目前的人臉識別技術(shù)已經(jīng)非常成熟了,還發(fā)展成3D人臉識別。而且現(xiàn)在各大廠商也都提供了人臉識別的API接口供我們調(diào)用,可以說幾行代碼就可以完成人臉識別。但是人臉識別的根本還是基于圖像處理。在Python中最強大的圖像處理庫就是OpenCV。
OpenCV簡介
OpenCV是一個基于BSD許可(開源)發(fā)行的跨平臺計算機視覺庫,可以運行在Linux、Windows、Android和Mac OS操作系統(tǒng)上。OpenCV可用于開發(fā)實時的圖像處理、計算機視覺以及模式識別程序。它輕量級而且高效——由一系列 C 函數(shù)和少量 C++ 類構(gòu)成,同時提供了Python、Ruby、MATLAB等語言的接口,實現(xiàn)了圖像處理和計算機視覺方面的很多通用算法。
OpenCV基本使用
安裝
pip install opencv-python # 基礎(chǔ)庫pip install opencv-contrib-python # 擴展庫pip install opencv-python-headless
讀取圖片
讀取和顯示圖片是最基本的操作了,OpenCV當(dāng)中使用imread和imshow實現(xiàn)該操作
import cv2 as cv# 讀取圖片,路徑不能含有中文名,否則圖片讀取不出來image = cv.imread(‘1111.jpg’)# 顯示圖片cv.imshow(‘image’, image)# 等待鍵盤輸入,單位是毫秒,0表示無限等待cv.waitKey(0)# 因為最終調(diào)用的是C++對象,所以使用完要釋放內(nèi)存cv.destroyAllWindows()
將圖片轉(zhuǎn)為灰度圖
OpenCV中數(shù)百中關(guān)于不同色彩控件之間轉(zhuǎn)換的方法。目前最常用的有三種:灰度、BGR、HSV。
灰度色彩空間是通過去除彩色信息來講圖片轉(zhuǎn)換成灰階,灰度圖會大量減少圖像處理中的色彩處理,對人臉識別很有效。
BGR每個像素都由一個三元數(shù)組來表示,分別代碼藍(lán)、綠、紅三種顏色。python中還有一個庫PIL,讀取的圖片通道是RGB,其實是一樣的,只是顏色順序不一樣
HSV,H是色調(diào),S是飽和度,V是黑暗的程度
將圖片轉(zhuǎn)換為灰度圖
import cv2 as cv# 讀取圖片,路徑不能含有中文名,否則圖片讀取不出來image = cv.imread(‘1111.jpg’)# cv2讀取圖片的通道是BGR,# PIL讀取圖片的通道是RGB# code選擇COLOR_BGR2GRAY,就是BGR to GRAYgray_image = cv.cvtColor(image, code=cv.COLOR_BGR2GRAY)# 顯示圖片cv.imshow(‘image’, gray_image)# 等待鍵盤輸入,單位是毫秒,0表示無限等待cv.waitKey(0)# 因為最終調(diào)用的是C++對象,所以使用完要釋放內(nèi)存cv.destroyAllWindows()
繪制矩形
image = cv.imread(‘1111.jpg’)x, y, w, h = 50, 50, 80, 80# 繪制矩形cv.rectangle(image, (x, y, x+w, y+h), color=(0, 255, 0), thickness=2)# 繪制圓形cv.circle(image, center=(x + w//2, y + h//2), radius=w//2, color=(0, 0, 255), thickness=2)cv.imshow(‘image’, image)cv.waitKey(0)cv.destroyAllWindows()
人臉檢測
人臉檢測實際上是對圖像提取特征,Haar特征是一種用于實現(xiàn)實時人臉跟蹤的特征。每個Haar特征都描述了相鄰圖像區(qū)域的對比模式。比如邊、定點和細(xì)線都能生成具有判別性的特征。OpenCV給我們提供了Haar特征數(shù)據(jù),在cv2/data目錄下,使用特征數(shù)據(jù)的方法def detectMultiScale(self, image, scaleFactor=None, minNeighbors=None, flags=None, minSize=None, maxSize=None)
scaleFactor: 指定每個圖像比例縮小多少圖像
minNeighbors: 指定每個候選矩形必須保留多少個鄰居,值越大說明精度要求越高
minSize:檢測到的最小矩形大小
maxSize: 檢測到的最大矩形大小
檢測圖片中人臉
import osimport cv2 as cvdef face_detect_demo(image): # 將圖片轉(zhuǎn)換為灰度圖 gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) # 加載特征數(shù)據(jù) face_detector = cv.CascadeClassifier(os.path.join(cv.data.haarcascades, ‘haarcascade_frontalface_default.xml’)) faces = face_detector.detectMultiScale(gray) for x, y, w, h in faces: cv.rectangle(image, (x, y), (x + w, y + h), color=(0, 255, 0), thickness=2)# 讀取圖片,路徑不能含有中文名,否則圖片讀取不出來image = cv.imread(‘2222.jpg’)face_detect_demo(image)# 顯示圖片cv.imshow(‘image’, image)# 等待鍵盤輸入,單位是毫秒,0表示無限等待cv.waitKey(0)# 因為最終調(diào)用的是C++對象,所以使用完要釋放內(nèi)存cv.destroyAllWindows()
采用默認(rèn)參數(shù),檢測人臉數(shù)據(jù)不全,需要調(diào)整detectMultiScale函數(shù)的參數(shù),調(diào)整為faces = face_detector.detectMultiScale(gray, scaleFactor=1.02, minNeighbors=3)
我們發(fā)現(xiàn)除了檢測到人臉數(shù)據(jù),還有一些其他的臟數(shù)據(jù),這個時候可以打印檢測出的人臉數(shù)據(jù)位置和大小
faces = face_detector.detectMultiScale(gray, scaleFactor=1.02, minNeighbors=3)for x, y, w, h in faces: print(x, y, w, h) # 打印每一個檢測到的數(shù)據(jù)位置和大小 cv.rectangle(image, (x, y), (x + w, y + h), color=(0, 255, 0), thickness=2)
從大小中我們看到最大的兩個矩形,剛好是人臉數(shù)據(jù),其余都是臟數(shù)據(jù),那么繼續(xù)修改函數(shù)參數(shù)faces = face_detector.detectMultiScale(gray, scaleFactor=1.02, minNeighbors=3, minSize=(80, 80))
檢測視頻中人臉
視頻就是一張一張的圖片組成的,在視頻的幀上面重復(fù)這個過程就能完成視頻中的人臉檢測了。視頻讀取OpenCV為我們提供了函數(shù)VideoCapture,參數(shù)可以是視頻文件或者0(表示調(diào)用攝像頭)
import cv2 as cv# 人臉檢測def face_detect_demo(image): try: # 將圖片轉(zhuǎn)換為灰度圖 gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) # 加載特征數(shù)據(jù) face_detector = cv.CascadeClassifier(os.path.join(cv.data.haarcascades, ‘haarcascade_frontalface_default.xml’)) faces = face_detector.detectMultiScale(gray) for x, y, w, h in faces: print(x, y, w, h) cv.rectangle(image, (x, y), (x + w, y + h), color=(0, 255, 0), thickness=2) except Exception as e: passcap = cv.VideoCapture(‘人臉識別.mp4’)while cap.isOpened(): flag, frame = cap.read() face_detect_demo(frame) cv.imshow(‘result’, frame) if ord(‘q’) == cv.waitKey(5): breakcap.realse()cv.destroyAllWindows()
這個我們是做的人臉識別,怎么把愛好都識別了,這么先進嗎?很顯然這不太符合我們的要求,愛好只能藏在心里,你給我檢測出來就不行了。所以我們必須要進行優(yōu)化處理。OpenCV為我們提供了一個機器學(xué)習(xí)的小模塊,我們可以訓(xùn)練它,讓它只識別我們需要的部分,不要亂猜測。
訓(xùn)練數(shù)據(jù)
訓(xùn)練數(shù)據(jù)就是我們把一些圖片交給訓(xùn)練模型,讓模型熟悉她,這樣它就能更加準(zhǔn)確的識別相同的圖片。訓(xùn)練的數(shù)據(jù)一般我們可以從網(wǎng)上搜索:人臉識別數(shù)據(jù)庫,或者從視頻中保存美幀的數(shù)據(jù)作為訓(xùn)練集。所有的人臉識別算法在他們的train()函數(shù)中都有兩個參數(shù):圖像數(shù)組和標(biāo)簽數(shù)組。這些標(biāo)簽標(biāo)示進行識別時候的人臉I(yè)D,根據(jù)ID可以知道被識別的人是誰。
獲取訓(xùn)練集
從視頻中每隔5幀截取一個圖片,保存成圖片
import cv2cap = cv2.VideoCapture(‘人臉識別.mp4’)number = 100count = 1while cap.isOpened() and number 》 0: flag, frame = cap.read() if not flag: break if count % 5 == 0: # 按照視頻圖像中人臉的大體位置進行裁剪,只取人臉部分 img = frame[70:280, 520:730] cv2.imwrite(‘data/{}.png’.format(number), img) number -= 1 count += 1cap.release()cv2.destroyAllWindows()
使用LBPH訓(xùn)練模型
def getImageAndLabels(path_list): faces = [] ids = [] image_paths = [os.path.join(path_list, f) for f in os.listdir(path_list) if f.endswith(‘.png’)] face_detector = cv.CascadeClassifier(os.path.join(cv.data.haarcascades, ‘haarcascade_frontalface_default.xml’)) for image in image_paths: img = cv.imread(image) gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) faces = face_detector.detectMultiScale(gray) _id = int(os.path.split(image)[1].split(‘?!?]) for x, y, w, h in faces: faces.append(gray[y:y+h, x:x+w]) ids.append(_id) return faces, idsfaces, ids = getImageAndLabels(‘data’)# 訓(xùn)練recognizer = cv.face.LBPHFaceRecognizer_create()recognizer.train(faces, np.array(ids))# 保存訓(xùn)練特征recognizer.write(‘trains/trains.yml’)
基于LBPH的人臉識別
LBPH將檢測到的人臉分為小單元,并將其與模型中的對應(yīng)單元進行比較,對每個區(qū)域的匹配值產(chǎn)生一個直方圖。調(diào)整后的區(qū)域中調(diào)用predict函數(shù),該函數(shù)返回兩個元素的數(shù)組,第一個元素是所識別的個體標(biāo)簽,第二個元素是置信度評分。所有的算法都有一個置信度評分閾值,置信度評分用來衡量圖像與模型中的差距,0表示完全匹配。LBPH有一個好的識別參考值要低于50?;静襟E為:
cv.VideoCapture讀取視頻
Haar算法檢測人臉數(shù)據(jù)
基于LBPH訓(xùn)練集得到準(zhǔn)確人臉數(shù)據(jù),并輸出標(biāo)記此人是誰
按置信度取準(zhǔn)確度高的人臉標(biāo)記出來
import osimport cv2 as cvdef face_detect_demo(image): try: global number # 將圖片轉(zhuǎn)換為灰度圖 gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) # 加載特征數(shù)據(jù) faces = face_detector.detectMultiScale(gray, scaleFactor=1.02, minNeighbors=3) for x, y, w, h in faces: # 獲取置信度,大于80表示取值錯誤 _id, confidence = recognizer.predict(gray[y:y + h, x:x + w]) if confidence 《 80: cv.rectangle(image, (x, y), (x + w, y + h), color=(0, 255, 0), thickness=2) except Exception as e: passdef check_face(): cap = cv.VideoCapture(‘人臉識別.mp4’) while cap.isOpened(): flag, frame = cap.read() if not flag: break face_detect_demo(frame) cv.imshow(‘img’, frame) cv.waitKey(2) cv.destroyAllWindows()if __name__ == ‘__main__’: # 加載訓(xùn)練數(shù)據(jù)文件 recognizer = cv.face.LBPHFaceRecognizer_create() recognizer.read(‘trains/trains.yml’) face_detector = cv.CascadeClassifier(os.path.join(cv.data.haarcascades, ‘haarcascade_frontalface_default.xml’)) check_face()
總結(jié)
通過上面一步步的學(xué)習(xí),你是不是對OpenCV人臉識別有個基本的認(rèn)識了呢?但是我們也看到了,整個人臉識別的主要算法還是基于Haar,而且準(zhǔn)確度并不是特別高,主要是會檢測出很多非人臉的數(shù)據(jù)。LBPH是讓我們給某個人臉進行標(biāo)記,告訴我們他是誰,并沒有提高實際的檢測準(zhǔn)確度?,F(xiàn)在機器學(xué)習(xí)是非?;鸨模贠penCV的機器學(xué)習(xí)人臉識別也精確度也很高,下次我們在來對比幾種機器學(xué)習(xí)人臉識別的庫。
-
算法
+關(guān)注
關(guān)注
23文章
4606瀏覽量
92811 -
模型
+關(guān)注
關(guān)注
1文章
3220瀏覽量
48803 -
人臉識別
+關(guān)注
關(guān)注
76文章
4011瀏覽量
81846
發(fā)布評論請先 登錄
相關(guān)推薦
評論