[ OpenCV ] 利用 OpenCV進行臉部辨識
之前寫了捕捉臉部的 Code後,就變得有點貪心了,想說試著看看能不能分類 Twice的成員。
先利用上一篇 "利用 OpenCV抓取臉部數據",捕捉要訓練用的臉部圖片。
很殘酷的是,用同樣的參數抓取大量格式不一的網路圖片時,應該會有很多圖片的臉部捕捉錯誤,可能需要手工移除錯誤的圖片,目前我也沒有有效的方法去解決這個問題。有招的大大拜託不要留招。
開始之前,我的資料夾結構如下
一個都不認識?沒關係,讓 OpenCV介紹給你認識。
雖然不知道對 OpenCV的學習系統有沒有影響,但還是把資料的順序打亂一下好了。
(用 os.walk來找資料夾中的文件並不是很有效率,比較好的做法可以使用 glob。文中雖然不是寫得很聰明,但這是小弟學習的過程,所以就沒有更新代碼了,有需要的朋友試著自己動手改吧。)
OpenCV提供了三種辨識用的演算法,分別是
為了比較一下三種算法的差異,所以把每個模型都拿來訓練一下。
利用 cv2.putText在圖片上進行標注,其參數依序如下
遺憾的是,OpenCV似乎沒有辦法支援中文字型的輸出,如果各位大大有招,拜託教一下。
完成後,先試試看有沒有辦法辨識子瑜女神

看來 LBPH辨識錯誤了,再來試試 Twice和愉快伙伴們?
看來在這個分類器眼中,似乎沒有愉快伙伴,幾乎什麼人都可以是 Twice。
有可能是資料量太少,或是 Training Data解析度差異太大等原因。說實話,我也不曉得。
所以對不起摟,目前這個分類器沒有辦法介紹 Twice成員。之後有機會再來寫個用其他深度學習模塊的分類器好了。
雖然這三個模型都沒有辦法準確的辨識 Twice,但還是儲存一下好了。
儲存時,副檔名可以選擇 yml或是 xml。
先利用上一篇 "利用 OpenCV抓取臉部數據",捕捉要訓練用的臉部圖片。
很殘酷的是,用同樣的參數抓取大量格式不一的網路圖片時,應該會有很多圖片的臉部捕捉錯誤,可能需要手工移除錯誤的圖片,目前我也沒有有效的方法去解決這個問題。有招的大大拜託不要留招。
開始之前,我的資料夾結構如下
. ├── cascades │ └── haarcascade_frontalface_default.xml ├── Chaeyoung │ └── ... ├── Dahyun │ └── ... ├── Jeongyeon │ └── ... ├── Jihyo │ └── ... ├── Mina │ └── ... ├── Momo │ └── ... ├── Nayeon │ └── ... ├── Sana │ └── ... ├── Tzuyu │ └── ... └── facial_recognition.py裡面放著類似這樣的圖,大約每個成員都有40張左右的數據。









import os import cv2 import numpy as np import random names = ['Nayeon', 'Jeongyeon', 'Momo', 'Sana', 'Jihyo', 'Mina', 'Dahyun', 'Chaeyoung', 'Tzuyu'] x,y = [],[] for idx,member in enumerate(names): for fileNames in os.walk("./%s" % member): for fileName in fileNames[-1]: if fileName == '.DS_Store': pass else: img = cv2.imread(str("./"+member+"/"+fileName), cv2.IMREAD_GRAYSCALE) x.append(img) y.append(idx) data = list(zip(x, y)) random.shuffle(data) data_np = np.array(data) x = data_np[:,0].tolist() y = data_np[:,1].tolist()先把成員的名字建立成 list,再將每個成員的名字和檔案名稱加工成路徑,再利用 OpenCV讀取檔案加入 Training Data的 list,並同時建立 y作為 Label。
雖然不知道對 OpenCV的學習系統有沒有影響,但還是把資料的順序打亂一下好了。
(用 os.walk來找資料夾中的文件並不是很有效率,比較好的做法可以使用 glob。文中雖然不是寫得很聰明,但這是小弟學習的過程,所以就沒有更新代碼了,有需要的朋友試著自己動手改吧。)
OpenCV提供了三種辨識用的演算法,分別是
- Eigenfaces
- Fisherfaces
- Local Binary Pattern Histogram ( LBPH )
為了比較一下三種算法的差異,所以把每個模型都拿來訓練一下。
model_EigenFaces = cv2.face.createEigenFaceRecognizer() model_EigenFaces.train(np.asarray(x), np.asarray(y)) model_FisherFaces = cv2.face.createFisherFaceRecognizer() model_FisherFaces.train(np.asarray(x), np.asarray(y)) model_LBPH = cv2.face.createLBPHFaceRecognizer() model_LBPH.train(np.asarray(x), np.asarray(y))建立模型後,用這些模型來辨識,經 OpenCV辨識出的臉吧。
face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml') def detect(filename): img = cv2.imread(filename) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.3, 5, minSize=(100,100)) for (x,y,w,h) in faces: img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) roi = gray[y:y+h, x:x+w] try: roi = cv2.resize(roi, (200,200), interpolation=cv2.INTER_LINEAR) params = model_EigenFaces.predict(roi) print("Label: %s, Confidence: %.2f" % (params[0], params[1])) cv2.putText(img, names[params[0]], (x,y-35), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,0,0), 2) except: cv2.putText(img, 'Happy partner', (x,y-35), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,0,0), 2) try: roi = cv2.resize(roi, (200,200), interpolation=cv2.INTER_LINEAR) params = model_FisherFaces.predict(roi) print("Label: %s, Confidence: %.2f" % (params[0], params[1])) cv2.putText(img, names[params[0]], (x,y-20), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,255,0), 2) except: cv2.putText(img, 'Happy partner', (x,y-20), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,255,0), 2) try: roi = cv2.resize(roi, (200,200), interpolation=cv2.INTER_LINEAR) params = model_LBPH.predict(roi) print("Label: %s, Confidence: %.2f" % (params[0], params[1])) cv2.putText(img, names[params[0]], (x,y-5), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,0,255), 2) except: cv2.putText(img, 'Happy partner', (x,y-5), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,0,255), 2) cv2.imwrite('./face_tzuyu.png', img) print('Working with %s' % filename) detect('tzuyu.jpg')接著把辨識出來的臉,先用 "try" 試看看有沒有辦法辨認是哪位成員,如果辨識成功就會在附近標注名字。若辨識失敗,就會標注 "Happy partner"。
利用 cv2.putText在圖片上進行標注,其參數依序如下
- 要被標注的圖片
- 標注的文字
- 位置
- 字型
- 字體大小
- 字體顏色
- 字體粗細
遺憾的是,OpenCV似乎沒有辦法支援中文字型的輸出,如果各位大大有招,拜託教一下。
完成後,先試試看有沒有辦法辨識子瑜女神


看來 LBPH辨識錯誤了,再來試試 Twice和愉快伙伴們?


結果挺令人失望了,幾乎全部辨識錯誤,連愉快伙伴都被辨識為 Twice的成員。
會不會任誰的臉都會被辨識為 Twice的成員呢?
為了測試模型,所以做了以下實驗性的嘗試,Once和其他照片中的粉絲請不要生氣。






有可能是資料量太少,或是 Training Data解析度差異太大等原因。說實話,我也不曉得。
所以對不起摟,目前這個分類器沒有辦法介紹 Twice成員。之後有機會再來寫個用其他深度學習模塊的分類器好了。
雖然這三個模型都沒有辦法準確的辨識 Twice,但還是儲存一下好了。
儲存時,副檔名可以選擇 yml或是 xml。
model_EigenFaces.save('twice_model_EigenFaces.yml') model_FisherFaces.save('twice_model_FisherFaces.yml') model_LBPH.save('twice_model_LBPH.yml')要在讀取已訓練的數據時,先建立一個相對應的模型,再讀取 yml檔或 xml檔。
model_EigenFaces_new = cv2.face.createEigenFaceRecognizer() model_EigenFaces_new.load('twice_model_EigenFaces.yml') model_FisherFaces_new = cv2.face.createFisherFaceRecognizer() model_FisherFaces_new.load('twice_model_FisherFaces.yml') model_LBPH_new = cv2.face.createLBPHFaceRecognizer() model_LBPH_new.load('twice_model_LBPH.yml')
留言
張貼留言