基於OpenCV的人臉及笑臉檢測
寫在前面
你好,我是禪墨!
好久,沒見!要從一個玩笑說起
今天禪墨和小凱打賭:
小凱:這兒有一堆(200+)圖片,看誰能快速地挑出帶有笑臉的圖片
禪墨:就你?說賭約吧
小凱:你不是惦記K210嗎?就它了
禪墨:成交!給我一點時間。
準備工作
- 首先要快速地分揀出微笑的照片,就是進行人臉檢測
- 然後在人臉區域對特徵進行檢測,通過對比嘴型的特徵,找出笑臉
- 結果預覽
OpenCV haar分類器
圖片處理用什麼?當然是OpenCV啊
既然是檢測笑臉,如果通過特徵的方式,那就繞不開Hear特徵分類器
Haar-like特徵最早是由Papageorgiou等人用於物體檢測的數字圖像特徵,而Viola和Jones在此基礎上,使用3種類型4種形式的特徵。
Haar特徵分爲三類:邊緣特徵、線性特徵、中心特徵和對角線特徵,組合成特徵模板。特徵模板內有白色和黑色兩種矩形,並定義該模板的特徵值爲白色矩形像素和減去黑色矩形像素和。Haar特徵值反映了圖像的灰度變化情況。例如:臉部的一些特徵能由矩形特徵簡單的描述,如:眼睛要比臉頰顏色要深,鼻樑兩側比鼻樑顏色要深,嘴巴比周圍顏色要深等。但矩形特徵只對一些簡單的圖形結構,如邊緣、線段較敏感,所以只能描述特定走向(水平、垂直、對角)的結構。
這類矩形特徵模板由兩個或多個全等的黑白矩形相鄰組合而成,而矩形特徵值是白色矩形的灰度值的和減去黑色矩形的灰度值的和,矩形特徵對一些簡單的圖形結構,如線段、邊緣比較敏感。如果把這樣的矩形放在一個非人臉區域,那麼計算出的特徵值應該和人臉特徵值不一樣,所以這些矩形就是爲了把人臉特徵量化,以區分人臉和非人臉。
如果自己找人臉訓練特徵的話,需要花費時間和大量的素材,那今天就採用OpenCV官方給出的訓練結果!
導入檢測器
face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_default.xml')
smile_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_smile.xml')
檢測過程
不管是檢測人臉還是檢測笑臉,都會用到 detectMultiScale() 函數進行標記
此函數的作用是,在輸入圖像中檢測不同尺寸的對象,返回包含對象的矩形框。
- image——輸入圖像
- scaleFactor——表示每輪檢測圖像齒輪減少的比例
- minNeighbors——指明對象要至少被檢測到幾次才能判定對象確實存在
- minSize——檢測對象的最小尺寸
- 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了
關於那些問題,歡迎在評論區交流!
微信公衆號:興趣路人甲