專欄地址:『youcans 的圖像處理學(xué)習(xí)課』
文章目錄:『youcans 的圖像處理學(xué)習(xí)課 - 總目錄』
4. Haar 級(jí)聯(lián)分類器
基于 Haar 特征的級(jí)聯(lián)分類器是 Paul Viola 在論文”Rapid Object Detection using a Boosted Cascade of Simple Features”中提出的一種目標(biāo)檢測(cè)方法。
Haar 級(jí)聯(lián)分類器在每一級(jí)的節(jié)點(diǎn)中,使用 AdaBoost 算法學(xué)習(xí)一個(gè)高檢測(cè)率低拒絕率的多層分類器。其特點(diǎn)是:
-
使用 Haar-like 輸入特征,對(duì)矩形圖像區(qū)域的和或者差進(jìn)行閾值化。
-
使用積分圖像計(jì)算 45°旋轉(zhuǎn)區(qū)域的像素和,加速 Haar-like 輸入特征的計(jì)算。
-
使用統(tǒng)計(jì) Boosting 來(lái)創(chuàng)建二分類(人臉/非人臉)的分類器節(jié)點(diǎn)(高通過(guò)率,低拒絕率)。
-
將弱分類器并聯(lián)組合起來(lái),構(gòu)成篩選式級(jí)聯(lián)分類器。
各級(jí)的 Boosting 分類器對(duì)于有人臉的檢測(cè)窗口都能通過(guò),同時(shí)拒絕一小部分非人臉的檢測(cè)窗口,并將通過(guò)的檢測(cè)窗口傳給下一個(gè)分類器。依次類推,最后一個(gè)分類器將幾乎所有非人臉的檢測(cè)窗口都拒絕掉,只剩下有人臉的檢測(cè)窗口。因此,只要檢測(cè)窗口區(qū)域通過(guò)了所有各級(jí) Boosting 分類器,則認(rèn)為檢測(cè)窗口中有人臉。
在實(shí)際應(yīng)用中輸入圖片的尺寸較大,需要進(jìn)行多區(qū)域、多尺度的檢測(cè)。多區(qū)域是要遍歷圖片的不同位置,多尺度是為了檢測(cè)圖片中不同大小的人臉。
在 Haar 級(jí)聯(lián)分類人臉檢測(cè)器中,主要利用了人臉的結(jié)構(gòu)化特征:
- 與臉頰相比,眼部顏色較深
- 與眼睛相比,鼻梁區(qū)域較為明亮
- 眼睛、嘴巴、鼻子的位置較為固定
通過(guò)這 5 個(gè)矩形區(qū)域的明暗關(guān)系,就可以形成對(duì)人臉的各個(gè)部分的判別特征。例如在下圖中,第一個(gè)特征檢測(cè)眼部和上臉頰之間的強(qiáng)度差異,第二個(gè)特征檢測(cè)雙眼的間距。
Haar 人臉檢測(cè)訓(xùn)練很高,但對(duì)側(cè)臉的檢測(cè)性能較差。
5. Haar 人臉/人眼檢測(cè)器
5.1 OpenCV 中的級(jí)聯(lián)分類器
OpenCV 中定義了級(jí)聯(lián)分類器類 cv::CascadeClassifier。在 Python 語(yǔ)言中,使用接口函數(shù) cv.CascadeClassifier() 從文件創(chuàng)建分類器。
cv.CascadeClassifier(filename)
cv.CascadeClassifier.load(filename[, ]) → retval
cv.CascadeClassifier.read(node[, ]) → retval
cv.CascadeClassifier.empty([, ]) → retval
cv.CascadeClassifier.convert(oldcascade, newcascade[, ]) → retval
cv.CascadeClassifier.detectMultiScale(image[, scaleFactor=1.1, minNeighbors=3, flags=0, minSize=Size(), maxSize=Size()]) → objects
成員函數(shù) cv.CascadeClassifier.load() 從文件加載級(jí)聯(lián)分類器模型,成員函數(shù) cv.CascadeClassifier.read() 從FileStorage 節(jié)點(diǎn)讀取分類器,成員函數(shù) cv.CascadeClassifier.empty()檢測(cè)分類器是否加載成功。
成員函數(shù) cv.CascadeClassifier.detectMultiScale() 用于執(zhí)行對(duì)圖像進(jìn)行目標(biāo)檢測(cè),成員函數(shù) cv.CascadeClassifier.convert()
參數(shù)說(shuō)明:
- filename:加載分類器模型的文件路徑和名稱,字符串。
- image:待檢測(cè)的輸入圖像,CV_8U 格式。
- scaleFactor:搜索窗口的縮放比例,默認(rèn)值為1.1。
- minNeighbors:表示構(gòu)成檢測(cè)目標(biāo)的相鄰矩形的最小個(gè)數(shù),默認(rèn)值為 3。
- flags:版本兼容標(biāo)志,默認(rèn)值為 0。
- minSize:檢測(cè)目標(biāo)的最小尺寸,元組 (h,w)。
- maxSize:檢測(cè)目標(biāo)的最大尺寸,元組 (h,w)。
- objects:返回值,檢測(cè)目標(biāo)的矩形邊界框 ,是形如 (N,4) 的Numpy數(shù)組。
參數(shù)說(shuō)明:
(1)返回值 objects 是形如 (N,4) 的Numpy數(shù)組,每行有 4個(gè)元素 (x, y, width, height) 表示矩形框的左上頂點(diǎn)坐標(biāo) (x,y) 和寬度 width、高度 height。
(2)加載的級(jí)聯(lián)分類器模型文件,擴(kuò)展名為 .xml。
5.2 Haar 級(jí)聯(lián)檢測(cè)器的預(yù)訓(xùn)練模型
OpenCV 提供了級(jí)聯(lián)分類器的訓(xùn)練方法,也可以直接下載預(yù)訓(xùn)練模型后使用 load() 方法加載模型。
OpenCV 提供的 Haar 級(jí)聯(lián)檢測(cè)器的預(yù)訓(xùn)練模型位于 OpenCV 安裝包的 \data\haarcascades
文件夾,或者從 【GitHub】opencv/data at 4.x 下載。
OpenCV 提供的 haar 級(jí)聯(lián)檢測(cè)器的預(yù)訓(xùn)練模型包括:
haarcascade_eye.xml, 眼睛
haarcascade_eye_tree_eyeglasses.xml, 戴眼鏡的眼睛
haarcascade_frontalcatface.xml, 正面貓臉
haarcascade_frontalcatface_extended.xml, 正面貓臉
haarcascade_frontalface_alt.xml, 正面人臉
haarcascade_frontalface_alt2.xml, 正面人臉
haarcascade_frontalface_alt_tree.xml, 正面人臉
haarcascade_frontalface_default.xml, 正面人臉
haarcascade_fullbody.xml, 人體
haarcascade_lefteye_2splits.xml, 左眼
haarcascade_license_plate_rus_16stages.xml,
haarcascade_lowerbody.xml,
haarcascade_profileface.xml,
haarcascade_righteye_2splits.xml, 右眼
haarcascade_russian_plate_number.xml,
haarcascade_smile.xml, 笑臉
haarcascade_upperbody.xml, 上身
5.3 人臉檢測(cè)/人眼檢測(cè)的實(shí)現(xiàn)步驟
使用 Haar 級(jí)聯(lián)檢測(cè)器檢測(cè)圖片中的人臉的步驟:
(1)創(chuàng)建一個(gè) CascadeClassifier 級(jí)聯(lián)分類器對(duì)象,使用 load() 方法從 .xml 文件加載級(jí)聯(lián)分類器模型。
(2)讀取待檢測(cè)的圖片。
(3)使用 detectMultiScale() 方法檢測(cè)圖片,返回檢測(cè)到的面部或眼睛的邊界矩形。
(4)將檢測(cè)到的邊界矩形繪制到檢測(cè)圖片上。
例程 17_6:使用 Haar 級(jí)聯(lián)檢測(cè)器檢測(cè)人臉
使用 Haar 級(jí)聯(lián)檢測(cè)器檢測(cè)圖片中的人臉。
import numpy as np
import cv2 as cv
if __name__ == '__main__':
# (6) 使用 Haar 級(jí)聯(lián)分類器 預(yù)訓(xùn)練模型 檢測(cè)人臉
# 讀取待檢測(cè)的圖片
img = cv.imread("../images/img_group_02.jpg", flags=1)
print(img.shape)
# 加載 Haar 級(jí)聯(lián)分類器 預(yù)訓(xùn)練模型
model_path = "../data/haarcascade_frontalface_alt2.xml"
face_detector = cv.CascadeClassifier(model_path) # <class 'cv2.CascadeClassifier'>
# 使用級(jí)聯(lián)分類器檢測(cè)人臉
faces = face_detector.detectMultiScale(img, scaleFactor=1.1, minNeighbors=1,
minSize=(30, 30), maxSize=(300, 300))
print(faces.shape) # (17, 4)
print(faces[0]) # (x, y, width, height)
# 繪制人臉檢測(cè)框
for x, y, width, height in faces:
cv.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
# 顯示圖片
cv.imshow("faces", img)
cv.waitKey(0)
cv.destroyAllWindows()
Haar 級(jí)聯(lián)檢測(cè)器可以對(duì)人臉檢出率較高,但有一定的錯(cuò)檢率,即有些檢測(cè)結(jié)果中并不是人臉。
例程 17_7:使用 Haar 級(jí)聯(lián)檢測(cè)器檢測(cè)人眼
人眼檢測(cè)的方法與人臉檢測(cè)方法相同,只是使用了不同的預(yù)訓(xùn)練模型,例如 haarcascade_eye.xml。
由于眼睛比人臉的尺寸小,因此減小了檢測(cè)函數(shù) detectMultiScale() 的參數(shù) minSize=(20, 20), maxSize。
import numpy as np
import cv2 as cv
if __name__ == '__main__':
# (7) 使用 Haar 級(jí)聯(lián)分類器 預(yù)訓(xùn)練模型 檢測(cè)人眼
# 讀取待檢測(cè)的圖片
img = cv.imread("../images/img_group_01.jpg", flags=1)
print(img.shape)
# 加載 Haar 級(jí)聯(lián)分類器 預(yù)訓(xùn)練模型
model_path = "../data/haarcascade_eye.xml"
eye_detector = cv.CascadeClassifier(model_path) # <class 'cv2.CascadeClassifier'>
# 使用級(jí)聯(lián)分類器檢測(cè)人臉
eyes = eye_detector.detectMultiScale(img, scaleFactor=1.1, minNeighbors=1,
minSize=(20, 20), maxSize=(100, 100))
print(eyes.shape) # (51, 4)
print(eyes[0]) # (x, y, width, height)
# 繪制人臉檢測(cè)框
for x, y, width, height in eyes:
cv.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
# 顯示圖片
cv.imshow("Haar_Cascade", img)
# cv.imwrite("../images/imgSave3.png", img)
cv.waitKey(0)
cv.destroyAllWindows()
例程 17_8:使用 Haar 級(jí)聯(lián)檢測(cè)器檢測(cè)人臉和人眼
為了提高檢測(cè)效率,可以先檢測(cè)人臉,再在人類窗口內(nèi)檢測(cè)人眼,不僅可以提高檢測(cè)效率,而且可以提高檢測(cè)精度。
import numpy as np
import cv2 as cv
if __name__ == '__main__':
# (8) 使用 Haar 級(jí)聯(lián)分類器 預(yù)訓(xùn)練模型 檢測(cè)人臉和人眼
# 讀取待檢測(cè)的圖片
img = cv.imread("../images/img_group_01.jpg", flags=1)
print(img.shape)
# 加載 Haar 級(jí)聯(lián)分類器 預(yù)訓(xùn)練模型
face_path = "../data/haarcascade_frontalface_alt2.xml" # 人臉檢測(cè)器
face_detector = cv.CascadeClassifier(face_path) # <class 'cv2.CascadeClassifier'>
eye_path = "../data/haarcascade_eye.xml" # 人眼檢測(cè)器
eye_detector = cv.CascadeClassifier(eye_path) # <class 'cv2.CascadeClassifier'>
# 使用級(jí)聯(lián)分類器檢測(cè)人臉
faces = face_detector.detectMultiScale(img, scaleFactor=1.1, minNeighbors=2,
minSize=(30, 30), maxSize=(300, 300))
print(faces.shape) # (15, 4)
# 繪制人臉檢測(cè)框
for x, y, width, height in faces:
cv.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
# 在人臉區(qū)域內(nèi)檢測(cè)人眼
roi = img[y:y + height, x:x + width] # 提取人臉
# 檢測(cè)人眼
eyes = eye_detector.detectMultiScale(roi, scaleFactor=1.1, minNeighbors=1,
minSize=(20, 20), maxSize=(80, 80))
# 繪制人眼
for ex, ey, ew, eh in eyes:
cv.rectangle(img, (x+ex, y+ey), (x+ex+ew, y+ey+eh), (255, 0, 0), 2)
# 顯示圖片
cv.imshow("Haar_Cascade", img)
# cv.imwrite("../images/imgSave4.png", img)
cv.waitKey(0)
cv.destroyAllWindows()
例程 17_9:使用 Haar 級(jí)聯(lián)分類器進(jìn)行視頻人臉檢測(cè)
首先啟動(dòng)攝像頭或讀取視頻文件,讀取視頻幀。然后將視頻幀轉(zhuǎn)換為灰度圖像,使用 cascade級(jí)聯(lián)檢測(cè)器檢測(cè)人臉。對(duì)于檢測(cè)到的人臉,都加上一個(gè)矩形框。
import numpy as np
import cv2 as cv
if __name__ == '__main__':
# (9) 使用 Haar 級(jí)聯(lián)分類器檢測(cè)視頻流
# 加載 Haar 級(jí)聯(lián)分類器 預(yù)訓(xùn)練模型
face_path = "../data/haarcascade_frontalface_default.xml" # 人臉檢測(cè)器
face_detector = cv.CascadeClassifier(face_path) # <class 'cv2.CascadeClassifier'>
# 創(chuàng)建視頻讀取/捕獲對(duì)象
vedioRead = "../images/Megamind.avi" # 讀取視頻文件的路徑
videoCap = cv.VideoCapture(vedioRead) # 實(shí)例化 VideoCapture 類
frameNum = 0 # 視頻幀數(shù)初值
# ret, frame = videoCap.read() # 讀取一幀圖像
# print("frame: ", frame.shape) # (528, 720, 3)
timef = 40 # 設(shè)置抽幀間隔
plt.figure(figsize=(9, 5.6))
while videoCap.isOpened(): # 檢查視頻捕獲是否成功
ret, frame = videoCap.read() # 讀取一幀圖像, (528, 720, 3)
if ret is True:
frameNum += 1 # 讀取視頻的幀數(shù)
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) # 灰度處理
# 使用級(jí)聯(lián)分類器檢測(cè)人臉
faces = face_detector.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=2,
minSize=(50, 50), maxSize=(300, 300))
# 繪制人臉檢測(cè)框
for x, y, width, height in faces:
cv.rectangle(frame, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
cv.imshow('frame', frame) # 目標(biāo)識(shí)別視頻
if (frameNum%timef==0 and 1<=frameNum//timef<= 6): # 判斷抽幀條件
plt.subplot(2, 3, frameNum//timef), plt.axis('off')
plt.title("{}. Face detector (f={})".format(frameNum//timef, frameNum))
plt.imshow(cv.cvtColor(frame, cv.COLOR_BGR2RGB))
if cv.waitKey(10)&0xFF == 27: # 按 'Esc' 退出
break
else:
print("Can't receive frame at frameNum {}.".format(frameNum))
break
print("frameNum: ", frameNum)
# 釋放資源
videoCap.release() # 關(guān)閉讀取視頻文件
cv.destroyAllWindows() # 關(guān)閉顯示窗口
plt.tight_layout()
plt.show()
版權(quán)聲明:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-467224.html
youcans@xupt 原創(chuàng)作品,轉(zhuǎn)載必須標(biāo)注原文鏈接:(https://blog.csdn.net/youcans/article/details/130423104)
Copyright 2022 youcans, XUPT
歡迎關(guān)注 『youcans 的 OpenCV 學(xué)習(xí)課』 系列,持續(xù)更新文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-467224.html
到了這里,關(guān)于【youcans 的圖像處理學(xué)習(xí)課】23. 人臉檢測(cè):Haar 級(jí)聯(lián)檢測(cè)器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!