目錄
- 1. 效果圖
- 2. 原理
- 2.1 Haar級聯(lián)是什么?
- 2.2 Haar級聯(lián)的問題與局限性
- 2.3 Haar級聯(lián)預(yù)訓(xùn)練的模型
- 3. 源碼
- 參考
這篇博客將介紹如何使用預(yù)訓(xùn)練好的OpenCV Haar級聯(lián)人臉、眼睛、嘴部檢測器,并將它們應(yīng)用于圖片及實(shí)時視頻流的檢測。
人臉檢測結(jié)果是最穩(wěn)定和準(zhǔn)確的。不幸的是,在許多情況下,眼睛檢測和嘴巴檢測結(jié)果是不可用的——對于面部特征/部分提取,強(qiáng)烈建議使用python,dlib,OpenCV提取眼睛,鼻子,嘴唇及下頜,dlib的檢測要比眼睛Haar級聯(lián),嘴巴Haar級聯(lián)本身更穩(wěn)定,甚至更快。
Haar級聯(lián)算法是OpenCV最流行的目標(biāo)檢測算法,主要優(yōu)點(diǎn)是速度太快了,盡管許多算法(如HOG+線性SVM、SSDs、更快的R-CNN、YOLO等等)比Haar級聯(lián)算法更精確。但如果需要純粹的速度,就是無法打敗OpenCV的Haar cascades。
Haar Cascades尤其是在資源受限的設(shè)備中工作時,當(dāng)無法使用更昂貴的計(jì)算對象檢測器時,效果顯著。Haar級聯(lián)的缺點(diǎn)是容易出現(xiàn)假陽性檢測,應(yīng)用于推理/檢測時需要進(jìn)行參數(shù)調(diào)整。
1. 效果圖
Haar級聯(lián)檢測的效果如下:
可以看到圖中有固定大小的面在移動,就可以“訓(xùn)練”分類器來識別圖像的給定區(qū)域是否包含人臉。
面部、眼睛、嘴部檢測效果圖如下:
有時候會有假陽性結(jié)果,如下圖:
可以看到檢測并不是最準(zhǔn)確的,臉部是準(zhǔn)確的,但嘴和眼睛級聯(lián)發(fā)生好幾個假陽性。當(dāng)眨眼時,有兩種情況發(fā)生:(1)眼睛區(qū)域不再被檢測到,或者(2)它被錯誤地標(biāo)記為嘴巴,在許多幀中往往有多個嘴巴檢測結(jié)果。
2. 原理
2.1 Haar級聯(lián)是什么?
Haar級聯(lián)檢測5個特征:邊緣特征、線特征、四角-矩形的特征,計(jì)算特征需要從黑色區(qū)域下的像素總和中減去白色區(qū)域下的像素總和。有趣的是,這些特征在人臉檢測中具有實(shí)際的重要性:
- 眼睛區(qū)域往往比臉頰區(qū)域暗。
- 鼻子區(qū)域比眼睛區(qū)域亮。
給定這五個矩形區(qū)域及其相應(yīng)的和差,就可以形成能夠?qū)θ四樀母鱾€部分進(jìn)行分類的特征。
Haar級聯(lián)的一些好處是,由于使用了積分圖像(也稱為求和面積表),它們在計(jì)算類似Haar的特征時非???。通過使用AdaBoost算法,它們對特征選擇也非常有效。最重要的是,它們可以檢測圖像中的人臉,而不考慮人臉的位置或比例。
2.2 Haar級聯(lián)的問題與局限性
Haar級聯(lián)檢測器的問題與局限主要有3點(diǎn):
- 需要最有效的正面圖像的臉;
- 容易出現(xiàn)誤報(bào)——Viola-Jones算法可以在沒有人臉的情況下輕松報(bào)告圖像中的人臉;
- 調(diào)優(yōu)OpenCV檢測參數(shù)會非常乏味。有時可以檢測出圖像中的所有人臉,有時會(1)圖像的區(qū)域被錯誤地分類為面部;(2)面部被完全遺漏時。
2.3 Haar級聯(lián)預(yù)訓(xùn)練的模型
OpenCV庫維護(hù)一個預(yù)先訓(xùn)練好的Haar級聯(lián)庫。包括:
- haarcascade_frontalface_default.xml:檢測面部
- haarcascade_eye.xml:檢測左眼和右眼
- haarcascade_smile.xml:檢測面部是否存在嘴部
- haarcascade_eye_tree_eyeglasses.xml:檢測是否帶墨鏡🕶
- haarcascade_frontalcatface.xml:檢測貓臉
- haarcascade_frontalcatface_extended.xml:檢測貓臉延伸
- haarcascade_frontalface_alt.xml:檢測貓臉屬性
- haarcascade_frontalface_alt_tree.xml
- haarcascade_frontalface_alt2.xml
- haarcascade_fullbody.xml:檢測全身
- haarcascade_lefteye_2splits.xml:檢測左眼
- haarcascade_licence_plate_rus_16stages.xml:檢測證件
- haarcascade_lowerbody.xml:檢測下半身
- haarcascade_profileface.xml
- haarcascade_righteye_2splits.xml:檢測右眼
- haarcascade_russian_plate_number.xml:檢測俄羅斯字母車牌號
- haarcascade_upperbody.xml:檢測上半身
還提供了其他經(jīng)過預(yù)訓(xùn)練的Haar級聯(lián),包括一個用于俄羅斯牌照,另一個用于貓臉檢測。
可以使用cv2.CascadeClassifer從磁盤加載預(yù)先訓(xùn)練好的Haar級聯(lián)檢測器:
detector = cv2.CascadeClassifier(path)
可以使用detectMultiScale對其進(jìn)行預(yù)測:
results = detector.detectMultiScale(
gray, scaleFactor=1.05, minNeighbors=5,
minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE)
3. 源碼
3.1 圖像檢測
# USAGE
# python opencv_haar_cascades_images.py --cascades cascades --image ml.jpg
# 導(dǎo)入必要的包
import argparse
import os # 不同系統(tǒng)路徑分隔符
import cv2 # opencv綁定
import imutils
# 構(gòu)建命令行參數(shù)及解析
# --cascades 級聯(lián)檢測器的路徑
ap = argparse.ArgumentParser()
ap.add_argument("-c", "--cascades", type=str, default="cascades",
help="path to input directory containing haar cascades")
ap.add_argument("-i", "--image", type=str, default="ml2.jpg",
help="path to input image")
args = vars(ap.parse_args())
# 初始化字典,并保存Haar級聯(lián)檢測器名稱及文件路徑
detectorPaths = {
"face": "haarcascade_frontalface_default.xml",
"eyes": "haarcascade_eye.xml",
"smile": "haarcascade_smile.xml",
}
# 初始化字典以保存多個Haar級聯(lián)檢測器
print("[INFO] loading haar cascades...")
detectors = {}
# 遍歷檢測器路徑
for (name, path) in detectorPaths.items():
# 加載Haar級聯(lián)檢測器并保存到map
path = os.path.sep.join([args["cascades"], path])
detectors[name] = cv2.CascadeClassifier(path)
# 從磁盤讀取圖像,縮放,并轉(zhuǎn)換灰度圖
print(args['image'])
image = cv2.imread(args["image"])
image = imutils.resize(image, width=500)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 使用合適的Haar檢測器執(zhí)行面部檢測
faceRects = detectors["face"].detectMultiScale(
gray, scaleFactor=1.05, minNeighbors=5, minSize=(30, 30),
flags=cv2.CASCADE_SCALE_IMAGE)
# 遍歷檢測到的所有面部
for (fX, fY, fW, fH) in faceRects:
# 提取面部ROI
faceROI = gray[fY:fY + fH, fX:fX + fW]
# 在面部ROI應(yīng)用左右眼級聯(lián)檢測器
eyeRects = detectors["eyes"].detectMultiScale(
faceROI, scaleFactor=1.1, minNeighbors=10,
minSize=(15, 15), flags=cv2.CASCADE_SCALE_IMAGE)
# 在面部ROI應(yīng)用嘴部檢測
smileRects = detectors["smile"].detectMultiScale(
faceROI, scaleFactor=1.1, minNeighbors=10,
minSize=(15, 15), flags=cv2.CASCADE_SCALE_IMAGE)
# 遍歷眼睛邊界框
for (eX, eY, eW, eH) in eyeRects:
# 繪制眼睛邊界框(紅色)
ptA = (fX + eX, fY + eY)
ptB = (fX + eX + eW, fY + eY + eH)
cv2.rectangle(image, ptA, ptB, (0, 0, 255), 2)
# 遍歷嘴部邊界框
for (sX, sY, sW, sH) in smileRects:
# 繪制嘴邊界框(藍(lán)色)
ptA = (fX + sX, fY + sY)
ptB = (fX + sX + sW, fY + sY + sH)
cv2.rectangle(image, ptA, ptB, (255, 0, 0), 2)
# 繪制面部邊界框(綠色)
cv2.rectangle(image, (fX, fY), (fX + fW, fY + fH),
(0, 255, 0), 2)
# 展示輸出幀
cv2.imshow("image", image)
cv2.waitKey(0)
# 清理工作
cv2.destroyAllWindows()
3.2 實(shí)時視頻流檢測
# USAGE
# python opencv_haar_cascades.py --cascades cascades
# 導(dǎo)入必要的包
import argparse
import os # 不同系統(tǒng)路徑分隔符
import time # sleep 2秒
import cv2 # opencv綁定
import imutils
from imutils.video import VideoStream # 訪問網(wǎng)絡(luò)攝像頭
# 構(gòu)建命令行參數(shù)及解析
# --cascades 級聯(lián)檢測器的路徑
ap = argparse.ArgumentParser()
ap.add_argument("-c", "--cascades", type=str, default="cascades",
help="path to input directory containing haar cascades")
args = vars(ap.parse_args())
# 初始化字典,并保存Haar級聯(lián)檢測器名稱及文件路徑
detectorPaths = {
"face": "haarcascade_frontalface_default.xml",
"eyes": "haarcascade_eye.xml",
"smile": "haarcascade_smile.xml",
}
# 初始化字典以保存多個Haar級聯(lián)檢測器
print("[INFO] loading haar cascades...")
detectors = {}
# 遍歷檢測器路徑
for (name, path) in detectorPaths.items():
# 加載Haar級聯(lián)檢測器并保存到map
path = os.path.sep.join([args["cascades"], path])
detectors[name] = cv2.CascadeClassifier(path)
# 初始化視頻流,允許攝像頭預(yù)熱2s
print("[INFO] starting video stream...")
vs = VideoStream(src=0).start()
time.sleep(2.0)
# 遍歷視頻流的每一幀
while True:
# 獲取視頻流的每一幀,縮放,并轉(zhuǎn)換灰度圖
frame = vs.read()
frame = imutils.resize(frame, width=500)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 使用合適的Haar檢測器執(zhí)行面部檢測
faceRects = detectors["face"].detectMultiScale(
gray, scaleFactor=1.05, minNeighbors=5, minSize=(30, 30),
flags=cv2.CASCADE_SCALE_IMAGE)
# 遍歷檢測到的所有面部
for (fX, fY, fW, fH) in faceRects:
# 提取面部ROI
faceROI = gray[fY:fY + fH, fX:fX + fW]
# 在面部ROI應(yīng)用左右眼級聯(lián)檢測器
eyeRects = detectors["eyes"].detectMultiScale(
faceROI, scaleFactor=1.1, minNeighbors=10,
minSize=(15, 15), flags=cv2.CASCADE_SCALE_IMAGE)
# 在面部ROI應(yīng)用嘴部檢測
smileRects = detectors["smile"].detectMultiScale(
faceROI, scaleFactor=1.1, minNeighbors=10,
minSize=(15, 15), flags=cv2.CASCADE_SCALE_IMAGE)
# 遍歷眼睛邊界框
for (eX, eY, eW, eH) in eyeRects:
# 繪制眼睛邊界框(紅色)
ptA = (fX + eX, fY + eY)
ptB = (fX + eX + eW, fY + eY + eH)
cv2.rectangle(frame, ptA, ptB, (0, 0, 255), 2)
# 遍歷嘴部邊界框
for (sX, sY, sW, sH) in smileRects:
# 繪制嘴邊界框(藍(lán)色)
ptA = (fX + sX, fY + sY)
ptB = (fX + sX + sW, fY + sY + sH)
cv2.rectangle(frame, ptA, ptB, (255, 0, 0), 2)
# 繪制面部邊界框(綠色)
cv2.rectangle(frame, (fX, fY), (fX + fW, fY + fH),
(0, 255, 0), 2)
# 展示輸出幀
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) 0xFF
# 按下‘q'鍵,退出循環(huán)
if key == ord("q"):
break
# 清理工作
cv2.destroyAllWindows()
vs.stop()
參考
https://www.pyimagesearch.com/2021/04/12/opencv-haar-cascades/
到此這篇關(guān)于超詳細(xì)注釋之OpenCV Haar級聯(lián)檢測器進(jìn)行面部檢測的文章就介紹到這了,更多相關(guān)OpenCV Haar內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!