1. 程式人生 > >基於Python3.7和opencv的人臉識別(含資料收集,模型訓練)

基於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.參考文獻與擴充套件閱讀

在這裡,我要感謝樹莓派實驗室的一篇文章,我的大部分程式碼都來源於此,對想要做深入瞭解的讀者,可以參考此文,以下是連結

http://shumeipai.nxez.com/2018/03/09/real-time-face-recognition-an-end-to-end-project-with-raspberry-pi.html

在此以一個問題結尾,為什麼網上沒有詳細的關於如何在電腦上實現人臉識別的教程,而卻有在樹莓派上的詳細教程呢?這不是上升了一個門檻嗎?

也許是我沒找到?這是我寫這篇教程的初衷之一。