【火爐煉AI】機器學習052-OpenCV構建人臉鼻子眼睛檢測器

煉丹老頑童發表於2019-03-02

【火爐煉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)
複製程式碼

通過對下面幾張圖片進行人臉檢測,得到的結果分別為:

【火爐煉AI】機器學習052-OpenCV構建人臉鼻子眼睛檢測器
【火爐煉AI】機器學習052-OpenCV構建人臉鼻子眼睛檢測器
【火爐煉AI】機器學習052-OpenCV構建人臉鼻子眼睛檢測器

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
複製程式碼
【火爐煉AI】機器學習052-OpenCV構建人臉鼻子眼睛檢測器

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

【火爐煉AI】機器學習052-OpenCV構建人臉鼻子眼睛檢測器

當然,還可以建立函式同時對鼻子和眼睛進行檢測,只需要對原來的鼻子檢測函式做少許修改即可。

########################小**********結###############################

1,此處使用Haar級聯構建了人臉,鼻子,眼睛檢測器,能夠很好的檢測到圖片,視訊流中的各個結構資訊。

2,從結果上可以看出,雖然能夠有效檢測,但是還有些人臉或鼻子,眼睛等難以被檢測到,此時可能要調整檢測函式detectMultiScale()的引數,如果調整引數仍然不理想,就需要修改特徵檢測級聯檔案cascade_file這個xml了。

#################################################################

注:本部分程式碼已經全部上傳到(我的github)上,歡迎下載。

參考資料:

1, Python機器學習經典例項,Prateek Joshi著,陶俊傑,陳小莉譯

相關文章