人脸检测完成后,我们需要将检测到的人脸进行框选,那么就需要轮廓检测了。
不讨论过多的算法方面的东西(因为实在不太懂),我这次直接使用了opencv中的
findContours()函数。
直接说这段代码吧,我们会在其中看到这么一句:
这个就是opencv内置的轮廓检测的函数,
这里一定要注意,在网上看到的大多数教程这个函数的返回值都是两个,
但是由于版本问题,我使用的其实返回了三个值,即使第一个值很少用,
但是如果不接就会报错: ValueError: too many values to unpack
返回值:
(1)基本用不到,处理的图像;
(2)轮廓的点集,在opencv中,轮廓就是一系列点的集合;
(3)各层轮廓的索引;
主要参数:
(1)二值图,一定是二值图,所以我们需要对图像进行预处理。
我这里其实之前传进去需要处理的就是一副黑白图,但是不知道为什么还会报错,所以
就把黑白图依然进行下述处理。
这个处理过程是原地处理,所以如果后续需要原图,那么最好copy()一下。
(2)第二个参数是轮廓的检索方式
CV_RETR_EXTERNAL:
表示只检测外轮廓;
CV_RETR_LIST:
检测的轮廓不建立等级关系;
CV_RETR_CCOMP:
建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。
如果内孔内还有一个连通物体,这个物体的边界也在顶层;
CV_RETR_TREE:
建立一个等级树结构的轮廓;
(3)第三个参数是轮廓的近似方法
CV_CHAIN_APPROX_NONE:
存储所有的轮廓点,相邻的两个点的像素位置差不超过1;
CV_CHAIN_APPROX_SIMPLE:
压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,
例如一个矩形轮廓只需4个点来保存轮廓信息;
CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法。
获取轮廓后,我们只要对返回的点集,也就是第二个参数进行遍历,每次遍历得到一个contour,
如果想要对其进行处理,比如标记等等,或者是在其中选出需要的轮廓(比如最大的轮廓)。
在循环中处理逻辑即可。
下面的代码是对获取到的轮廓区域内的像素点进行统计投票,
如果满足条件的像素点数大于总像素点数的八分之三,返回0,否则返回1。
通过分析,还发现rectangle函数的框选区域把标记框也标记进去了,
而且轮廓线上左宽为2像素,下右宽为1像素,需要精确内部区域的一定要把框所占数量去掉。