了解一套工具最好的方法是:動手完成一個現有的範例
了解一門技術最好的方法是:用那套技術完整做出一個自己的應用Get your hands dirty!
介紹完目前主流的API與相關平台後,還是要回頭來看看要如何自行寫程式完成一樣的功能。
前面提到過,使用OpenCV & Dlib來做人臉偵測,大概可以分為四種方式:
今天說這個
接下來就依序介紹各個方式吧。
註
:如同在第一天提到的,這個系列使用的主要語言是Python
,對Python不了解或有疑問的可以參考其他邦友發表的優質文章
這邊推薦兩種Python開發環境使用:
由於接下來的實作大部分都會圍繞在自行開發上,為了能夠更方便的整合專案,後續的開發環境都會使用PyCharm來作範例說明與實作,關於PyCharm的安裝與使用請參考邦幫忙其他相關文章
習慣上我喜歡稱呼這個方法叫哈爾特徵檢測
,
它以辨識速度極快、硬體需求低,常常會被應用在各種行動裝置或是樹莓派(Raspberry Pi)等硬體規格相對低階的裝置上。
這個方法主要是透過滑動檢測事先定義好的小矩形,由左上至右下,找尋人臉上明顯的特徵:如兩眼之間的鼻子區域通常比眼睛更亮,然後慢慢把非人臉區域排除。從而檢測出人臉真正區域
這個技術相關的原理在網路上都可以搜尋的到,這邊就讓我們直接開始實作吧!
打開PyCharm IDE,新增一個專案
(可不用) 點擊上方工具欄的「File」->「Settings」->「Project: your_project_name」->「Python Interpreter」,新增一個Python的虛擬運作環境
點選上方的"+"符號安裝套件
依序在搜尋框輸入下面的套件名稱,確認版本相同後,按下方的「Install Package」安裝套件
安裝需要一點時間...等待安裝都成功後,關閉視窗。在主視窗開啟下方的「Terminal」,輸入pip freeze
:
> pip freeze
確認你安裝的套件與版本是否與下面相同
cmake==3.21.2
dlib==19.22.1
imutils==0.5.4
numpy==1.21.2
opencv-contrib-python==4.5.3.56
接下來在新增的專案目錄下新增目錄:face_detection,專門放人臉偵測相關檔案用
再來新增一個Python檔案:opencv_haar_cascade.py,撰寫今天主程式
在新增的Python檔案內輸入以下內容 (相關程式碼說明在註解內):
# 匯入必要套件
import argparse
import ntpath
import os
import time
import cv2
import imutils
from imutils.video import WebcamVideoStream
detectors = {
"eye": os.path.sep.join([ntpath.dirname(cv2.__file__), 'data', 'haarcascade_eye.xml']),
"face": os.path.sep.join([ntpath.dirname(cv2.__file__), 'data', 'haarcascade_frontalface_default.xml'])
}
# 定義人臉偵測函數方便重複使用
def detect(gray, part="face"):
# 初始化Haar cascades函數
detector = cv2.CascadeClassifier(detectors[part])
# 根據選擇的模型偵測
rects = detector.detectMultiScale(gray, scaleFactor=1.05, minNeighbors=5, minSize=(15, 15),
flags=cv2.CASCADE_SCALE_IMAGE)
return rects
def main():
# 初始化arguments
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--part", type=str, choices=["eye", "face"], default="face", help="detect which part of face")
args = vars(ap.parse_args())
# 啟動WebCam
vs = WebcamVideoStream().start()
time.sleep(2.0)
start = time.time()
fps = vs.stream.get(cv2.CAP_PROP_FPS)
print("Frames per second using cv2.CAP_PROP_FPS : {0}".format(fps))
while True:
# 取得當前的frame,變更比例為寬300,並且轉成灰階圖片
frame = vs.read()
img = frame.copy()
img = imutils.resize(img, width=300)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 呼叫偵測函數,取得結果
rects = detect(gray, args["part"])
# 繪出偵測結果 (記得將偵測的座標轉回原本的frame大小)
ratio = frame.shape[1] / img.shape[1]
for rect in rects:
rect = rect * ratio
(x, y, w, h) = rect.astype("int")
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 標示FPS
end = time.time()
text = f"FPS: {str(int(1 / (end - start)))}"
cv2.putText(frame, text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
start = end
# 顯示影像
cv2.imshow("Frame", frame)
# 判斷是否案下"q";跳離迴圈
key = cv2.waitKey(1) & 0xff
if key == ord('q'):
break
# 清除畫面與結束WebCam
cv2.destroyAllWindows()
vs.stop()
if __name__ == '__main__':
main()
運行程式:
python face_detection/opencv_haar_cascade.py
或執行後,會開啟WebCam,並且顯示類似下面的節果:
你可以試著將啟動指令改成python face_detection/opencv_haar_cascade.py -p eye
跑看看會有什麼結果。
戴口罩基本上無法成功辨識,這是由於前面提到哈爾特徵檢測的作法是滑動視窗的限制,你可以試著比對戴上口罩前與戴上口罩後玩看看
一般WebCam的FPS為30 (你可以透過print(vs.stream.get(cv2.CAP_PROP_FPS))
檢查看看),透過哈爾特徵檢測處理寬為300px的影像還是可以有約28 ~ 32 fps;後續可以跟其他方法比較看看,這個速度算是非常快了 (在實際使用下幾乎感受不到延遲)
哈爾特徵檢測的false-positive (失敗偵測)結果會受程式碼39行的detectMultiScale()
參數影響:
[1.0, MAX_VALUE]
,越小檢測出的結果越多 (也需花費更多時間),通常會使用1.05 ~ 1.1
之間的數值正整數
,越小檢測的結果越多 (但失敗偵測的可能性也變大),通常會使用3 ~ 10
之間的數值(正整數, 正整數)
的格式,通常會從(30, 30)
開始使用,根據結果再調整cv2.CASCADE_SCALE_IMAGE
以上的參數的調整會非常容易改變最終的結果,這邊建議根據你實際執行的情況來做調整,順序建議為:minSize -> minNeighbors -> scaleFactor
OpenCV內建的檢測模型還有其他很多可以使用,如偵測眼睛、微笑、上半身、全身等等,可以參考程式碼20-21行的路徑目錄;有興趣可以到該目錄下看看
參考程式碼在這
就這樣,想到再補充。
明天見!
MFVideoFormat_RGB24(unsupported media type)
Traceback (most recent call last):
不好意思跑完出現這個要如何解決
File "C:/Users/ADMIN/PycharmProjects/pythonProject1/opencv_haar_cascade.py", line 43, in main
img = frame.copy()
AttributeError: 'NoneType' object has no attribute 'copy'
還有這個
這個問題我沒遇到過...不過你用關鍵字去找可能會找到這篇類似的狀況與解法。
希望有幫助到您。
好像是相機沒辦法開我是用usb相機