基於OpenCV的人臉及笑臉檢測

基於OpenCV的人臉及笑臉檢測

寫在前面

你好,我是禪墨!

好久,沒見!要從一個玩笑說起

今天禪墨和小凱打賭:

小凱:這兒有一堆(200+)圖片,看誰能快速地挑出帶有笑臉的圖片

禪墨:就你?說賭約吧

小凱:你不是惦記K210嗎?就它了

禪墨:成交!給我一點時間。

準備工作

  1. 首先要快速地分揀出微笑的照片,就是進行人臉檢測
  2. 然後在人臉區域對特徵進行檢測,通過對比嘴型的特徵,找出笑臉
  3. 結果預覽

在這裏插入圖片描述

OpenCV haar分類器

圖片處理用什麼?當然是OpenCV啊

既然是檢測笑臉,如果通過特徵的方式,那就繞不開Hear特徵分類器

Haar-like特徵最早是由Papageorgiou等人用於物體檢測的數字圖像特徵,而ViolaJones在此基礎上,使用3種類型4種形式的特徵。

Haar特徵分爲三類:邊緣特徵、線性特徵、中心特徵和對角線特徵,組合成特徵模板。特徵模板內有白色和黑色兩種矩形,並定義該模板的特徵值爲白色矩形像素和減去黑色矩形像素和。Haar特徵值反映了圖像的灰度變化情況。例如:臉部的一些特徵能由矩形特徵簡單的描述,如:眼睛要比臉頰顏色要深,鼻樑兩側比鼻樑顏色要深,嘴巴比周圍顏色要深等。但矩形特徵只對一些簡單的圖形結構,如邊緣、線段較敏感,所以只能描述特定走向(水平、垂直、對角)的結構。
這類矩形特徵模板由兩個或多個全等的黑白矩形相鄰組合而成,而矩形特徵值是白色矩形的灰度值的和減去黑色矩形的灰度值的和,矩形特徵對一些簡單的圖形結構,如線段、邊緣比較敏感。如果把這樣的矩形放在一個非人臉區域,那麼計算出的特徵值應該和人臉特徵值不一樣,所以這些矩形就是爲了把人臉特徵量化,以區分人臉和非人臉。

如果自己找人臉訓練特徵的話,需要花費時間和大量的素材,那今天就採用OpenCV官方給出的訓練結果!

導入檢測器

face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_default.xml')
smile_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_smile.xml')

檢測過程

不管是檢測人臉還是檢測笑臉,都會用到 detectMultiScale() 函數進行標記

此函數的作用是,在輸入圖像中檢測不同尺寸的對象,返回包含對象的矩形框。

  1. image——輸入圖像
  2. scaleFactor——表示每輪檢測圖像齒輪減少的比例
  3. minNeighbors——指明對象要至少被檢測到幾次才能判定對象確實存在
  4. minSize——檢測對象的最小尺寸
  5. maxSize——檢測對象的最大尺寸
# 檢測臉部
faces = face_cascade.detectMultiScale(gray,
                            scaleFactor=1.1,
                            minNeighbors=5,
                            minSize=(30, 30),
                            flags=cv2.CASCADE_SCALE_IMAGE)
print('Detected ', len(faces), " face")

在人臉檢測之後,需要標記出人臉位置,然後在此位置內進行笑臉的檢測

# 標記位置
for (x, y, w, h) in faces:
    img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
    # cv2.circle(img, (int((x + x + w) / 2), int((y + y + h) / 2)), int(w / 2), (0, 255, 0), 1)
    roi_gray = gray[y: y + h, x: x + w]
    roi_color = img[y: y + h, x: x + w]
    
    #笑臉
    smile = smile_cascade.detectMultiScale(roi_gray,
                            scaleFactor=1.1,
                            minNeighbors=5,
                            minSize=(30, 30))
    for (sx, sy, sw, sh) in smile:
        cv2.rectangle(roi_color, (sx, sy), (sx + sw, sy + sh), (0, 255, 0), 2)

爲了更直觀的在圖片窗口反映結果,在左上角對結果進行標記

需要用到 putText() 函數

label = 'Result: Detected ' + str(len(faces)) +" faces !"
cv2.putText(img, label, (10, 20),
                        cv2.FONT_HERSHEY_COMPLEX,
                        0.3, (0, 0, 0), 1)

各參數依次是:圖片,添加的文字,左上角座標,字體,字體大小,顏色,字體粗細

輸出結果

在這裏插入圖片描述
在這裏插入圖片描述

有些問題

來看多人的

在這裏插入圖片描述
在這裏插入圖片描述

大家都發現了吧,會圈出一些不是笑臉的地方,特別有意思的是衣服上的達芬奇都能夠圈出來,說明還是訓練結果還是很好的
一方面可能與像素有關,另一方面也可能與訓練結果有關,個人猜測是特徵種類不夠多,特徵不太明顯

解決問題

爲什麼會出現這個呢,好吧,完全是我個人問題,爲了圖省事,detectMultiScale()函數沒有寫全,現在補上(已更新代碼塊)

需要注意的是不同的圖片需要調minNeighbors的值
如果想要做一個完整的,就仿照上面標記人臉數的方法判斷,
出人臉的跳出,具體怎麼搞就不多說了,
目前成功率95%以上
貼出正常狀態圖片

在這裏插入圖片描述
在這裏插入圖片描述

再來看美女

在這裏插入圖片描述
在這裏插入圖片描述

寫在後面

好了,今天就到這裏了,去擼K210了

關於那些問題,歡迎在評論區交流!

微信公衆號興趣路人甲在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章