专栏地址:『youcans 的图像处理学习课』
文章目录:『youcans 的图像处理学习课 - 总目录』
基于 Haar 特征的级联分类器是 Paul Viola 在论文”Rapid Object Detection using a Boosted Cascade of Simple Features”中提出的一种目标检测方法。
Haar 级联分类器在每一级的节点中,使用 AdaBoost 算法学习一个高检测率低拒绝率的多层分类器。其特点是:
使用 Haar-like 输入特征,对矩形图像区域的和或者差进行阈值化。
使用积分图像计算 45°旋转区域的像素和,加速 Haar-like 输入特征的计算。
使用统计 Boosting 来创建二分类(人脸/非人脸)的分类器节点(高通过率,低拒绝率)。
将弱分类器并联组合起来,构成筛选式级联分类器。
各级的 Boosting 分类器对于有人脸的检测窗口都能通过,同时拒绝一小部分非人脸的检测窗口,并将通过的检测窗口传给下一个分类器。依次类推,最后一个分类器将几乎所有非人脸的检测窗口都拒绝掉,只剩下有人脸的检测窗口。因此,只要检测窗口区域通过了所有各级 Boosting 分类器,则认为检测窗口中有人脸。
在实际应用中输入图片的尺寸较大,需要进行多区域、多尺度的检测。多区域是要遍历图片的不同位置,多尺度是为了检测图片中不同大小的人脸。
在 Haar 级联分类人脸检测器中,主要利用了人脸的结构化特征:
通过这 5 个矩形区域的明暗关系,就可以形成对人脸的各个部分的判别特征。例如在下图中,第一个特征检测眼部和上脸颊之间的强度差异,第二个特征检测双眼的间距。
Haar 人脸检测训练很高,但对侧脸的检测性能较差。
OpenCV 中定义了级联分类器类 cv::CascadeClassifier。在 Python 语言中,使用接口函数 cv.CascadeClassifier() 从文件创建分类器。
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
成员函数 cv.CascadeClassifier.load() 从文件加载级联分类器模型,成员函数 cv.CascadeClassifier.read() 从FileStorage 节点读取分类器,成员函数 cv.CascadeClassifier.empty()检测分类器是否加载成功。
成员函数 cv.CascadeClassifier.detectMultiScale() 用于执行对图像进行目标检测,成员函数 cv.CascadeClassifier.convert()
参数说明:
参数说明:
(1)返回值 objects 是形如 (N,4) 的Numpy数组,每行有 4个元素 (x, y, width, height) 表示矩形框的左上顶点坐标 (x,y) 和宽度 width、高度 height。
(2)加载的级联分类器模型文件,扩展名为 .xml。
OpenCV 提供了级联分类器的训练方法,也可以直接下载预训练模型后使用 load() 方法加载模型。
OpenCV 提供的 Haar 级联检测器的预训练模型位于 OpenCV 安装包的 \data\haarcascades
文件夹,或者从 【GitHub】opencv/data at 4.x 下载。
OpenCV 提供的 haar 级联检测器的预训练模型包括:
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, 上身
使用 Haar 级联检测器检测图片中的人脸的步骤:
(1)创建一个 CascadeClassifier 级联分类器对象,使用 load() 方法从 .xml 文件加载级联分类器模型。
(2)读取待检测的图片。
(3)使用 detectMultiScale() 方法检测图片,返回检测到的面部或眼睛的边界矩形。
(4)将检测到的边界矩形绘制到检测图片上。
使用 Haar 级联检测器检测图片中的人脸。
import numpy as np
import cv2 as cv
if __name__ == '__main__':
# (6) 使用 Haar 级联分类器 预训练模型 检测人脸
# 读取待检测的图片
img = cv.imread("../images/img_group_02.jpg", flags=1)
print(img.shape)
# 加载 Haar 级联分类器 预训练模型
model_path = "../data/haarcascade_frontalface_alt2.xml"
face_detector = cv.CascadeClassifier(model_path) #
# 使用级联分类器检测人脸
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)
# 绘制人脸检测框
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 级联检测器可以对人脸检出率较高,但有一定的错检率,即有些检测结果中并不是人脸。
人眼检测的方法与人脸检测方法相同,只是使用了不同的预训练模型,例如 haarcascade_eye.xml。
由于眼睛比人脸的尺寸小,因此减小了检测函数 detectMultiScale() 的参数 minSize=(20, 20), maxSize。
import numpy as np
import cv2 as cv
if __name__ == '__main__':
# (7) 使用 Haar 级联分类器 预训练模型 检测人眼
# 读取待检测的图片
img = cv.imread("../images/img_group_01.jpg", flags=1)
print(img.shape)
# 加载 Haar 级联分类器 预训练模型
model_path = "../data/haarcascade_eye.xml"
eye_detector = cv.CascadeClassifier(model_path) #
# 使用级联分类器检测人脸
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)
# 绘制人脸检测框
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()
为了提高检测效率,可以先检测人脸,再在人类窗口内检测人眼,不仅可以提高检测效率,而且可以提高检测精度。
import numpy as np
import cv2 as cv
if __name__ == '__main__':
# (8) 使用 Haar 级联分类器 预训练模型 检测人脸和人眼
# 读取待检测的图片
img = cv.imread("../images/img_group_01.jpg", flags=1)
print(img.shape)
# 加载 Haar 级联分类器 预训练模型
face_path = "../data/haarcascade_frontalface_alt2.xml" # 人脸检测器
face_detector = cv.CascadeClassifier(face_path) #
eye_path = "../data/haarcascade_eye.xml" # 人眼检测器
eye_detector = cv.CascadeClassifier(eye_path) #
# 使用级联分类器检测人脸
faces = face_detector.detectMultiScale(img, scaleFactor=1.1, minNeighbors=2,
minSize=(30, 30), maxSize=(300, 300))
print(faces.shape) # (15, 4)
# 绘制人脸检测框
for x, y, width, height in faces:
cv.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
# 在人脸区域内检测人眼
roi = img[y:y + height, x:x + width] # 提取人脸
# 检测人眼
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()
首先启动摄像头或读取视频文件,读取视频帧。然后将视频帧转换为灰度图像,使用 cascade级联检测器检测人脸。对于检测到的人脸,都加上一个矩形框。
import numpy as np
import cv2 as cv
if __name__ == '__main__':
# (9) 使用 Haar 级联分类器检测视频流
# 加载 Haar 级联分类器 预训练模型
face_path = "../data/haarcascade_frontalface_default.xml" # 人脸检测器
face_detector = cv.CascadeClassifier(face_path) #
# 创建视频读取/捕获对象
vedioRead = "../images/Megamind.avi" # 读取视频文件的路径
videoCap = cv.VideoCapture(vedioRead) # 实例化 VideoCapture 类
frameNum = 0 # 视频帧数初值
# ret, frame = videoCap.read() # 读取一帧图像
# print("frame: ", frame.shape) # (528, 720, 3)
timef = 40 # 设置抽帧间隔
plt.figure(figsize=(9, 5.6))
while videoCap.isOpened(): # 检查视频捕获是否成功
ret, frame = videoCap.read() # 读取一帧图像, (528, 720, 3)
if ret is True:
frameNum += 1 # 读取视频的帧数
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) # 灰度处理
# 使用级联分类器检测人脸
faces = face_detector.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=2,
minSize=(50, 50), maxSize=(300, 300))
# 绘制人脸检测框
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) # 目标识别视频
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() # 关闭读取视频文件
cv.destroyAllWindows() # 关闭显示窗口
plt.tight_layout()
plt.show()
版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/130423104)
Copyright 2022 youcans, XUPT
欢迎关注 『youcans 的 OpenCV 学习课』 系列,持续更新