OpenCV Haar级联检测器进行面部检测的示例分析
OpenCV Haar级联检测器进行面部检测的示例分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
1. 效果图
Haar级联检测的效果如下:
可以看到图中有固定大小的面在移动,就可以"训练"分类器来识别图像的给定区域是否包含人脸。
面部、眼睛、嘴部检测效果图如下:
有时候会有假阳性结果,如下图:
可以看到检测并不是最准确的,脸部是准确的,但嘴和眼睛级联发生好几个假阳性。当眨眼时,有两种情况发生:(1)眼睛区域不再被检测到,或者(2)它被错误地标记为嘴巴,在许多帧中往往有多个嘴巴检测结果。
2. 原理
2.1 Haar级联是什么?
Haar级联检测5个特征:边缘特征、线特征、四角-矩形的特征,计算特征需要从黑色区域下的像素总和中减去白色区域下的像素总和。有趣的是,这些特征在人脸检测中具有实际的重要性:
眼睛区域往往比脸颊区域暗。
鼻子区域比眼睛区域亮。
给定这五个矩形区域及其相应的和差,就可以形成能够对人脸的各个部分进行分类的特征。
Haar级联的一些好处是,由于使用了积分图像(也称为求和面积表),它们在计算类似Haar的特征时非常快。通过使用AdaBoost算法,它们对特征选择也非常有效。最重要的是,它们可以检测图像中的人脸,而不考虑人脸的位置或比例。
2.2 Haar级联的问题与局限性
Haar级联检测器的问题与局限主要有3点:
需要最有效的正面图像的脸;
容易出现误报--Viola-Jones算法可以在没有人脸的情况下轻松报告图像中的人脸;
调优OpenCV检测参数会非常乏味。有时可以检测出图像中的所有人脸,有时会(1)图像的区域被错误地分类为面部;(2)面部被完全遗漏时。
2.3 Haar级联预训练的模型
OpenCV库维护一个预先训练好的Haar级联库。包括:
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:检测上半身
还提供了其他经过预训练的Haar级联,包括一个用于俄罗斯牌照,另一个用于猫脸检测。
可以使用cv2.CascadeClassifer从磁盘加载预先训练好的Haar级联检测器:
detector = cv2.CascadeClassifier(path)
可以使用detectMultiScale对其进行预测:
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# 导入必要的包import argparseimport os # 不同系统路径分隔符import cv2 # opencv绑定import imutils# 构建命令行参数及解析# --cascades 级联检测器的路径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级联检测器名称及文件路径detectorPaths = { "face": "haarcascade_frontalface_default.xml", "eyes": "haarcascade_eye.xml", "smile": "haarcascade_smile.xml",}# 初始化字典以保存多个Haar级联检测器print("[INFO] loading haar cascades...")detectors = {}# 遍历检测器路径for (name, path) in detectorPaths.items(): # 加载Haar级联检测器并保存到map path = os.path.sep.join([args["cascades"], path]) detectors[name] = cv2.CascadeClassifier(path)# 从磁盘读取图像,缩放,并转换灰度图print(args['image'])image = cv2.imread(args["image"])image = imutils.resize(image, width=500)gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 使用合适的Haar检测器执行面部检测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应用左右眼级联检测器 eyeRects = detectors["eyes"].detectMultiScale( faceROI, scaleFactor=1.1, minNeighbors=10, minSize=(15, 15), flags=cv2.CASCADE_SCALE_IMAGE) # 在面部ROI应用嘴部检测 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: # 绘制嘴边界框(蓝色) 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 实时视频流检测
# USAGE# python opencv_haar_cascades.py --cascades cascades# 导入必要的包import argparseimport os # 不同系统路径分隔符import time # sleep 2秒import cv2 # opencv绑定import imutilsfrom imutils.video import VideoStream # 访问网络摄像头# 构建命令行参数及解析# --cascades 级联检测器的路径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级联检测器名称及文件路径detectorPaths = { "face": "haarcascade_frontalface_default.xml", "eyes": "haarcascade_eye.xml", "smile": "haarcascade_smile.xml",}# 初始化字典以保存多个Haar级联检测器print("[INFO] loading haar cascades...")detectors = {}# 遍历检测器路径for (name, path) in detectorPaths.items(): # 加载Haar级联检测器并保存到map path = os.path.sep.join([args["cascades"], path]) detectors[name] = cv2.CascadeClassifier(path)# 初始化视频流,允许摄像头预热2sprint("[INFO] starting video stream...")vs = VideoStream(src=0).start()time.sleep(2.0)# 遍历视频流的每一帧while True: # 获取视频流的每一帧,缩放,并转换灰度图 frame = vs.read() frame = imutils.resize(frame, width=500) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 使用合适的Haar检测器执行面部检测 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应用左右眼级联检测器 eyeRects = detectors["eyes"].detectMultiScale( faceROI, scaleFactor=1.1, minNeighbors=10, minSize=(15, 15), flags=cv2.CASCADE_SCALE_IMAGE) # 在面部ROI应用嘴部检测 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: # 绘制嘴边界框(蓝色) 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'键,退出循环 if key == ord("q"): break# 清理工作cv2.destroyAllWindows()vs.stop()
关于OpenCV Haar级联检测器进行面部检测的示例分析问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。