最近学习图像处理,用到OpenCV的detectMultiScale方法检测人脸,但是对它的参数的含义不太理解,于是各种查资料和测试效果,下面把学习的过程和个人理解总结一下。
我用的是python3.6 + PyCharm,并且安装了OpenCV及相关的库。
然后下载Haar级联的XML,放在代码工程目录下。
下载地址:https://download.csdn.net/download/leaf_zizi/12667450
再借用《浪姐》的一张人脸图片,像素300*200。
import cv2
# 读取照片,转换成灰度图
img1 = cv2.imread("langjie.jpg")
gray_img = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY)
# 将级联算法加载到一个变量中
haar_face_cascade = cv2.CascadeClassifier(
'haar\haarcascade_frontalface_alt.xml')
# 识别图像中的人脸,返回所有人脸的矩形框向量组
# scaleFactor 为了检测到不同大小的目标,通过scalefactor参数把图像长宽同时按照一定比例(默认1.1)逐步缩小,
# 然后检测,这个参数设置的越大,计算速度越快,但可能会错过了某个大小的人脸。
# minNeighbors 构成检测目标的相邻矩形的最小个数,默认值是3
faces = haar_face_cascade.detectMultiScale(gray_img, scaleFactor=1.1,
minNeighbors=3)
# 在图像中画上矩形框
for (x, y, w, h) in faces:
cv2.rectangle(img1, (x, y), (x + w, y + h), (0, 255, 0), 1)
# 显示结果
cv2.imshow("Final_detected_image", img1)
cv2.waitKey(0)
看一下识别的效果,发现有两个人脸没有识别到,作为一个“较真儿”的人,我需要研究一下detectMultiScale参数的含义。
detectMultiScale(image[, scaleFactor[, minNeighbors[, flags[, minSize[, maxSize]]]]]) -> objects
@brief Detects objects of different sizes in the input image. The detected objects are returned as a list of rectangles.
此方法的任务是检测不同大小的对象,并返回矩形的列表。
@param image Matrix of the type CV_8U containing an image where objects are detected.
被检测的图片,需要转换为灰度图
@param scaleFactor Parameter specifying how much the image size is reduced at each image scale.
scaleFactor 是重点,直接翻译就是“指定每次图像缩小的比例”,后面再说我的理解。
@param minNeighbors Parameter specifying how many neighbors each candidate rectangle should have to retain it.
minNeighbors 也是重点,翻译为:指定每个候选矩形有多少个“邻居”,后面详说。
@param flags Parameter with the same meaning for an old cascade as in the function cvHaarDetectObjects. It is not used for a new cascade.
flag参数与旧的级联方法cvHaarDetectObjects中一样,新的级联中不用。(没用到这个参数)
@param minSize Minimum possible object size. Objects smaller than that are ignored.
@param maxSize Maximum possible object size. Objects larger than that are ignored. If `maxSize == minSize` model is evaluated on single scale.
minSize和maxSize 设置检测对象的最大最小值,低于minSize和高于maxSize的话就不会检测出来。
这里面最关键的两个参数就是scaleFactor和minNeighbors,我是通过一段英文解释来理解的,先来看一下:
Haar cascade classifier works with a sliding window approach. If you look at the cascade files you can see a size parameter which usually a pretty small value like 20 20. This is the smallest window that cascade can detect. So by applying a sliding window approach, you slide a window through out the picture than you resize it and search again until you can not resize it further. So with every iteration haar's cascaded classifier true outputs are stored. So when this window is slided in picture resized and slided again; it actually detects many many false positives. You can check what it detects by giving minNeighbors 0.
So there are a lot of face detection because of resizing the sliding window and a lot of false positives too. So to eliminate false positives and get the proper face rectangle out of detections, neighborhood approach is applied. It is like if it is in neighborhood of other rectangles than it is ok, you can pass it further. So this number determines the how much neighborhood is required to pass it as a face rectangle.
So by increasing this number you can eliminate false positives but be careful, by increasing it you can also lose true positives too.
我就不直接翻译了,说一下我的理解:
大概意思是Haar cascade的工作原理是一种“滑动窗口”的方法,通过在图像中不断的“滑动检测窗口”来匹配人脸。
因为图像的像素有大有小,图像中的人脸因为远近不同也会有大有小,所以需要通过scaleFactor参数设置一个缩小的比例,对图像进行逐步缩小来检测,这个参数设置的越大,计算速度越快,但可能会错过了某个大小的人脸。
其实可以根据图像的像素值来设置此参数,像素大缩小的速度就可以快一点,通常在1~1.5之间。
那么,经过多次的迭代,实际会检测出很多很多个人脸,这一点可以通过把minNeighbors 设为0来验证。
所以呢,minNeighbors参数的作用就来了,只有其“邻居”大于等于这个值的结果才认为是正确结果。
首先scaleFactor=1.1(默认值),分别设置minNeighbors=0,1,3(默认为3),看一下输出结果。
minNeighbors=0,每个人脸都识别出来了,特别的是孟佳(左3)被识别出2次,李斯(右二上)被识别出1次:
minNeighbors=1,李斯没识别出来,因为她的识别结果中没有“邻居”:
minNeighbors=3,孟佳也没有识别出来,因为她的识别结果中只有1个“邻居”:
此时,对minNeighbors是不是有了形象的认识了。
因为我的图像只有300*200像素,而每次缩小1.1倍,所以导致识别出的结果较少。下面我让scaleFactor=1.03,minNeighbors=0,1,3,你会发现,当scaleFactor=1.03时,每个人脸被识别的次数都比上一组测试要多,因为每次缩小的比例小,迭代的次数就多了。看一下输出结果:
scaleFactor=1.03,minNeighbors=0:
scaleFactor=1.03,minNeighbors=1:
scaleFactor=1.03,minNeighbors=3:
参考:
《Python机器学习和图像处理实战》
https://stackoverflow.com/questions/22249579/opencv-detectmultiscale-minneighbors-parameter