【火爐煉AI】機器學習052-OpenCV構建人臉鼻子眼睛檢測器
(本文所使用的Python庫和版本號: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2,opencv-python 3.4.2)
有兩個重要的概念需要澄清一下:人臉檢測:是指檢測影像或視訊中是否存在人臉,以及定位人臉的具體位置,人臉識別:確定影像或視訊中的人臉是張三還是李四還是其他某人。故而人臉檢測是人臉識別的基礎和前提條件。
在這一章我們來學習如何用OpenCV構建人臉檢測器,鼻子檢測器和眼睛檢測器。
1. 構建人臉檢測器
前面提到過,人臉檢測器是確定影像中人臉位置的過程,我們將用Haar級聯來構建人臉檢測器。Haar級聯通過在多個尺度上從影像中提取大量的簡單特徵來實現,這些簡單特徵包括有邊,角,線,矩形特徵等,然後通過建立一系列簡單的分類器來做訓練。
Haar級聯是一個基於Haar特徵的級聯分類器,所謂級聯分類器,是把多個弱分類器串聯成一個強分類器的過程,弱分類器是指效能受限,預測準確度不太高的分類器,所以此處的串聯實際上就是機器學習中的Boost方法,即整合方法。所以Haar分類器 = Haar-like特徵 + 積分圖方法 + AdaBoost + 級聯。關於Haar-like特徵和積分圖的概念,可以參考博文:淺析人臉檢測之Haar分類器方法.
1.1 對單張圖片進行人臉檢測
# 構建單張圖片的人臉檢測器
def img_face_detector(img_path,face_cascade_file):
image=cv2.imread(img_path)
face_cascade=cv2.CascadeClassifier(face_cascade_file)
if face_cascade.empty():
raise IOError(`Unable to load the face cascade classifier xml file!`)
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
face_rects=face_cascade.detectMultiScale(gray,1.3,5)
# 在檢測到的臉部周圍畫矩形框
for (x,y,w,h) in face_rects:
cv2.rectangle(image,(x,y),(x+w,y+h),(0,0,255),3)
return image
複製程式碼
# 測試一下這個人臉檢測器:
image1=img_face_detector(`E:PyProjectsDataSetFireAI/face1.jpg`,
`E:PyProjectsDataSetFireAIcascade_files/haarcascade_frontalface_alt.xml`)
image1=cv2.cvtColor(image1,cv2.COLOR_BGR2RGB)
plt.imshow(image1)
複製程式碼
通過對下面幾張圖片進行人臉檢測,得到的結果分別為:
1.2 對視訊流進行人臉檢測
視訊流的本質其實就是圖片,將圖片按照一定的每秒幀率fps播放出來即可。故而我們在對視訊進行分析時,需要從視訊流中捕獲圖片,對圖片進行分析。
# 對視訊流進行人臉檢測
def video_face_detector(face_cascade_file):
face_cascade=cv2.CascadeClassifier(face_cascade_file)
if face_cascade.empty():
raise IOError(`Unable to load the face cascade classifier xml file!`)
capture=cv2.VideoCapture(0)
while True:
_,frame=capture.read() # 捕獲當前幀
gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
face_rects=face_cascade.detectMultiScale(gray,1.3,5)
# 在檢測到的臉部周圍畫矩形框
for (x,y,w,h) in face_rects:
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),3)
cv2.imshow(`Video Face Detector`, frame)
key=cv2.waitKey(1) # 按ESC退出檢測
if key==27:
break
capture.release()
cv2.destroyAllWindows()
複製程式碼
2. 構建鼻子檢測器
2.1 對單張圖片進行鼻子檢測
# 構建單張圖片的鼻子檢測器
def img_nose_detector(img_path,face_cascade_file,nose_cascade_file,show_face=True):
image=cv2.imread(img_path)
face_cascade=cv2.CascadeClassifier(face_cascade_file)
if face_cascade.empty():
raise IOError(`Unable to load the face cascade classifier xml file!`)
nose_cascade=cv2.CascadeClassifier(nose_cascade_file)
if nose_cascade.empty():
raise IOError(`Unable to load the nose cascade classifier xml file!`)
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
face_rects=face_cascade.detectMultiScale(gray,1.3,5)
# 在檢測到的臉部周圍畫矩形框
for (x,y,w,h) in face_rects:
if show_face: cv2.rectangle(image,(x,y),(x+w,y+h),(0,0,255),3)
roi=gray[y:y+h,x:x+w]
nose_rects=nose_cascade.detectMultiScale(roi,1.3,5)
for (x_nose,y_nose,w_nose,h_nose) in nose_rects:
cv2.rectangle(image,(x+x_nose,y+y_nose),(x+x_nose+w_nose,y+y_nose+h_nose),
(0,255,0),3)
break # 一張臉上只能有一個鼻子,故而此處break
return image
複製程式碼
2.2 對視訊流進行鼻子檢測
同樣的,對視訊流進行鼻子檢測的程式碼為:
# 對視訊流進行鼻子檢測
def video_nose_detector(face_cascade_file,nose_cascade_file):
face_cascade=cv2.CascadeClassifier(face_cascade_file)
if face_cascade.empty():
raise IOError(`Unable to load the face cascade classifier xml file!`)
nose_cascade=cv2.CascadeClassifier(nose_cascade_file)
if nose_cascade.empty():
raise IOError(`Unable to load the nose cascade classifier xml file!`)
capture=cv2.VideoCapture(0)
while True:
_,frame=capture.read() # 捕獲當前幀
gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
face_rects=face_cascade.detectMultiScale(gray)
# 在檢測到的臉部周圍畫矩形框
for (x,y,w,h) in face_rects:
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),3)
roi=gray[y:y+h,x:x+w]
nose_rects=nose_cascade.detectMultiScale(roi,1.3,5)
for (x_nose,y_nose,w_nose,h_nose) in nose_rects:
cv2.rectangle(frame,(x+x_nose,y+y_nose),(x+x_nose+w_nose,y+y_nose+h_nose),
(0,255,0),3)
break # 一張臉上只能有一個鼻子,故而此處break
cv2.imshow(`Video Face Detector`, frame)
key=cv2.waitKey(1) # 按ESC退出檢測
if key==27:
break
capture.release()
cv2.destroyAllWindows()
複製程式碼
同樣的,可以構建對單張圖片和視訊流的眼睛檢測器,具體程式碼可以看(我的github)
當然,還可以建立函式同時對鼻子和眼睛進行檢測,只需要對原來的鼻子檢測函式做少許修改即可。
########################小**********結###############################
1,此處使用Haar級聯構建了人臉,鼻子,眼睛檢測器,能夠很好的檢測到圖片,視訊流中的各個結構資訊。
2,從結果上可以看出,雖然能夠有效檢測,但是還有些人臉或鼻子,眼睛等難以被檢測到,此時可能要調整檢測函式detectMultiScale()的引數,如果調整引數仍然不理想,就需要修改特徵檢測級聯檔案cascade_file這個xml了。
#################################################################
注:本部分程式碼已經全部上傳到(我的github)上,歡迎下載。
參考資料:
1, Python機器學習經典例項,Prateek Joshi著,陶俊傑,陳小莉譯