基於Python3.7和opencv的人臉識別(含資料收集,模型訓練)
前言
第一次寫部落格,有點緊張和興奮。廢話不多說,直接進入正題。如果你渴望使你的電腦能夠進行人臉識別;如果你不想了解什麼c++、底層演算法;如果你也不想買什麼樹莓派,安裝什麼幾個G的opencv;如果你和我一樣是個還沒入門的小白,但是想體驗一下人臉識別的魅力。那麼恭喜你,這篇文章就是為你準備的。讓我們開始吧!
一、需要準備的材料
1.一臺可以聯網的有攝像頭的電腦(手動滑稽)。
2.python3.7的安裝包
二、Python3.7及其第三方包的安裝
1.Python3.7的安裝
關於python3.7的安裝,網上有很多教程,請自行百度。
值得注意的是安裝時勾選新增環境變數,如果不新增,也可以,但要自己輸入相關檔案的絕對路徑。
2.第三方包的安裝準備
2.0本文采用pip進行安裝,若有過pip經驗的可以跳過這個部分。
2.1在開始選單欄搜尋dos,然後回車啟動命令提示符。
2.2在python3.7的Scripts資料夾中可以找到pip.exe。
2.3在命令提示符中輸入Scripts資料夾的絕對路徑
例:cd C:\\python3.7\Scripts
注:cd為Change directory,即更換目錄,cd後有空格。
2.4更換目錄成功後,輸入pip.exe,啟動pip,出現如下畫面說明啟動成功。
2.5 啟動pip後,就可以開始安裝Python的第三方包了,注意要讓電腦聯網。
3 第三方包的安裝
3.1opencv 的安裝,輸入:pip install opencv-python。
注:numpy與OpenCV繫結安裝,無需自己輸入命令。
3.2 pillow的安裝,輸入: pip install pillow
注:pillow為影象處理包。
3.3 contrib的安裝,輸入:pip instal opencv-contrib-python
注:筆者在contrib的安裝這裡花費了一些時間,網上說的那些很麻煩的辦法,讓我看的雲裡霧裡的。
contrib這個包用上面那個命令就可以安裝,它是用於訓練自己的人臉模型的一個OpenCV擴充套件包。
下圖為三個包的安裝過程截圖,由於我之前已經安裝過,會顯示包已存在。首次安裝會有進度條,成功後會有Successfully字樣。
三、人臉識別的程式實現
1.FaceDetection,人臉檢測
廢話不多說,先上程式碼
1 import numpy as np 2 import cv2 3 4 # 人臉識別分類器 5 faceCascade = cv2.CascadeClassifier(r'C:\python3.7\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml') 6 7 # 識別眼睛的分類器 8 eyeCascade = cv2.CascadeClassifier(r'C:\python3.7\Lib\site-packages\cv2\data\haarcascade_eye.xml') 9 10 # 開啟攝像頭 11 cap = cv2.VideoCapture(0) 12 ok = True 13 14 while ok: 15 # 讀取攝像頭中的影象,ok為是否讀取成功的判斷引數 16 ok, img = cap.read() 17 # 轉換成灰度影象 18 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 19 20 # 人臉檢測 21 faces = faceCascade.detectMultiScale( 22 gray, 23 scaleFactor=1.2, 24 minNeighbors=5, 25 minSize=(32, 32) 26 ) 27 28 # 在檢測人臉的基礎上檢測眼睛 29 for (x, y, w, h) in faces: 30 fac_gray = gray[y: (y+h), x: (x+w)] 31 result = [] 32 eyes = eyeCascade.detectMultiScale(fac_gray, 1.3, 2) 33 34 # 眼睛座標的換算,將相對位置換成絕對位置 35 for (ex, ey, ew, eh) in eyes: 36 result.append((x+ex, y+ey, ew, eh)) 37 38 # 畫矩形 39 for (x, y, w, h) in faces: 40 cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2) 41 42 for (ex, ey, ew, eh) in result: 43 cv2.rectangle(img, (ex, ey), (ex+ew, ey+eh), (0, 255, 0), 2) 44 45 cv2.imshow('video', img) 46 47 k = cv2.waitKey(1) 48 if k == 27: # press 'ESC' to quit 49 break 50 51 cap.release() 52 cv2.destroyAllWindows()
注:1.人臉識別分類器的路徑在不同的電腦上不同,一般來講,在python3.7\Lib\site-packages\cv2\data中,注意是絕對路徑,如果嫌目錄太長,可以將分類器和程式放在一起。
注:2.經過我的慎重考慮,我決定不放出我的人臉,請各位讀者自行嘗試,大概就是一個藍色的矩形框住你的臉,兩個綠色的矩形框住你的眼睛,按esc可退出。
2.FaceDataCollect,人臉資料收集
還是先上程式碼
1 import cv2 2 import os 3 # 呼叫筆記本內建攝像頭,所以引數為0,如果有其他的攝像頭可以調整引數為1,2 4 5 cap = cv2.VideoCapture(0) 6 7 face_detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') 8 9 face_id = input('\n enter user id:') 10 11 print('\n Initializing face capture. Look at the camera and wait ...') 12 13 count = 0 14 15 while True: 16 17 # 從攝像頭讀取圖片 18 19 sucess, img = cap.read() 20 21 # 轉為灰度圖片 22 23 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 24 25 # 檢測人臉 26 27 faces = face_detector.detectMultiScale(gray, 1.3, 5) 28 29 for (x, y, w, h) in faces: 30 cv2.rectangle(img, (x, y), (x+w, y+w), (255, 0, 0)) 31 count += 1 32 33 # 儲存影象 34 cv2.imwrite("Facedata/User." + str(face_id) + '.' + str(count) + '.jpg', gray[y: y + h, x: x + w]) 35 36 cv2.imshow('image', img) 37 38 # 保持畫面的持續。 39 40 k = cv2.waitKey(1) 41 42 if k == 27: # 通過esc鍵退出攝像 43 break 44 45 elif count >= 1000: # 得到1000個樣本後退出攝像 46 break 47 48 # 關閉攝像頭 49 cap.release() 50 cv2.destroyAllWindows()
注:1.在執行該程式前,請先建立一個Facedata資料夾並和你的程式放在一個資料夾下。
友情提示:請將程式和檔案打包放在一個叫人臉識別的資料夾下。可以把分類器也放入其中。
注:2.程式執行過程中,會提示你輸入id,請從0開始輸入,即第一個人的臉的資料id為0,第二個人的臉的資料id為1,執行一次可收集一張人臉的資料。
注:3.程式執行時間可能會比較長,可能會有幾分鐘,如果嫌長,可以將 #得到1000個樣本後退出攝像 這個註釋前的1000,改為100。
如果實在等不及,可按esc退出,但可能會導致資料不夠模型精度下降。
3.face_training,人臉資料訓練
1 import numpy as np 2 from PIL import Image 3 import os 4 import cv2 5 # 人臉資料路徑 6 path = 'Facedata' 7 8 recognizer = cv2.face.LBPHFaceRecognizer_create() 9 detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml") 10 11 def getImagesAndLabels(path): 12 imagePaths = [os.path.join(path, f) for f in os.listdir(path)] # join函式的作用? 13 faceSamples = [] 14 ids = [] 15 for imagePath in imagePaths: 16 PIL_img = Image.open(imagePath).convert('L') # convert it to grayscale 17 img_numpy = np.array(PIL_img, 'uint8') 18 id = int(os.path.split(imagePath)[-1].split(".")[1]) 19 faces = detector.detectMultiScale(img_numpy) 20 for (x, y, w, h) in faces: 21 faceSamples.append(img_numpy[y:y + h, x: x + w]) 22 ids.append(id) 23 return faceSamples, ids 24 25 26 print('Training faces. It will take a few seconds. Wait ...') 27 faces, ids = getImagesAndLabels(path) 28 recognizer.train(faces, np.array(ids)) 29 30 recognizer.write(r'face_trainer\trainer.yml') 31 print("{0} faces trained. Exiting Program".format(len(np.unique(ids))))
注:1.第8行的LBPHFaceRecognizer_create()為contrib中的函式,筆者之前自己摸索時,沒有安裝此包,因此卡了很久,印象深刻。
注:2.執行該程式前,請在人臉識別資料夾下建立face_trainer資料夾。
4.face_recognition 人臉檢測
1 import cv2 2 3 recognizer = cv2.face.LBPHFaceRecognizer_create() 4 recognizer.read('face_trainer/trainer.yml') 5 cascadePath = "haarcascade_frontalface_default.xml" 6 faceCascade = cv2.CascadeClassifier(cascadePath) 7 font = cv2.FONT_HERSHEY_SIMPLEX 8 9 idnum = 0 10 11 names = ['Allen', 'Bob'] 12 13 cam = cv2.VideoCapture(0) 14 minW = 0.1*cam.get(3) 15 minH = 0.1*cam.get(4) 16 17 while True: 18 ret, img = cam.read() 19 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 20 21 faces = faceCascade.detectMultiScale( 22 gray, 23 scaleFactor=1.2, 24 minNeighbors=5, 25 minSize=(int(minW), int(minH)) 26 ) 27 28 for (x, y, w, h) in faces: 29 cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) 30 idnum, confidence = recognizer.predict(gray[y:y+h, x:x+w]) 31 32 if confidence < 100: 33 idnum = names[idnum] 34 confidence = "{0}%".format(round(100 - confidence)) 35 else: 36 idnum = "unknown" 37 confidence = "{0}%".format(round(100 - confidence)) 38 39 cv2.putText(img, str(idnum), (x+5, y-5), font, 1, (0, 0, 255), 1) 40 cv2.putText(img, str(confidence), (x+5, y+h-5), font, 1, (0, 0, 0), 1) 41 42 cv2.imshow('camera', img) 43 k = cv2.waitKey(10) 44 if k == 27: 45 break 46 47 cam.release() 48 cv2.destroyAllWindows()
注:1. 11行的names中儲存人的名字,若該人id為0則他的名字在第一位,id位1則排在第二位,以此類推。
注:2. 最終效果為一個綠框,框住人臉,左上角為紅色的人名,左下角為黑色的概率。
四、結語,參考文獻,與擴充套件閱讀
1.結語
真是不容易啊,第一次寫部落格,終於寫完了。說一說初衷吧,當初我本想做一個電腦的人臉解鎖。我的想法是,手機都有人臉解鎖,電腦也可以做。
但我認為,我並不能真的實現,一是我不知道怎樣鎖住電腦,雖然我可以用python的easygui去模仿一個登陸介面,輸入密碼解鎖,然而,我清楚,
我並不能真正的鎖住電腦,所以我就放棄了這個計劃。如果有大神可以做到,請務必在評論區留言,我迫切的希望知道該怎樣做。
說一說我寫這篇部落格的目的吧,我當初一路走來,在網上搜到的大多是CSDN上的部落格,且大多為人臉檢測,並沒有人臉識別,資料收集和模型訓練。
僅有的幾篇也都講得雲裡霧裡,實在水平有限,看不懂。於是,我萌生了寫一篇給小白看的人臉識別的部落格的想法,本來打算在csdn上寫,
但由於種種原因,我選擇了部落格園。
2.參考文獻與擴充套件閱讀
在這裡,我要感謝樹莓派實驗室的一篇文章,我的大部分程式碼都來源於此,對想要做深入瞭解的讀者,可以參考此文,以下是連結
在此以一個問題結尾,為什麼網上沒有詳細的關於如何在電腦上實現人臉識別的教程,而卻有在樹莓派上的詳細教程呢?這不是上升了一個門檻嗎?
也許是我沒找到?這是我寫這篇教程的初衷之一。