今天先实现作者提供的思路的第二步
一、轮廓检测 findContours();
在这里要找轮廓出来,要先对图片腐蚀再膨胀,不过进行轮廓检测都要这样做吧?
这里我给出我认为是常用的一个用法:
vector<vector<Point> > contours0;
vector<Vec4i> hierarchy;
findContours(thresh, contours0, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point());
- 先定义一个 二维的point数组,用来保存边缘的点集合,它保存的东西就像是
假设有5个轮廓,那么contours0的行就有5行,
但是每个轮廓里有多少个点呢?这是不确定的,具体情况具体分析
因为可能第一个轮廓有五个点,第二个轮廓有100个点,等等。
所以这里假设第一个轮廓两个点,第二个轮廓三个点,以此类推
然后contours0就包含以下的东西(注意:为方便我把不同点都写成(x.y)实际上是什么点要看情况):
contours0={
{(x,y),(x,y),},//第一组轮廓
{(x,y),(x,y),(x,y)},//第二组轮廓
{(x,y),(x,y),(x,y),(x,y)},//第三组轮廓
{(x,y),(x,y),(x,y),(x,y),(x,y)},//第四组轮廓
{(x,y),(x,y),(x,y),(x,y),(x,y),(x,y)}//第五组轮廓
} - hierarchy
看看上面我给出的那个链接内容,可以看到关于这个参数的解释
但是在这个例子中,并没有用到它,所以也要具体情况具体分析,在这个例子中,它只是为了findContours()这个函数得以进行才被创造出来的。但我知道它肯定有用,不过因为我才疏学浅,还不明白它的用处。 - 其他参数看我给出的链接就好了。
- 调用findContours(),把检测出的轮廓的点放在了contours0这个“二维数组”里。
二、多边形逼近 approxPolyDP();
个人看法:
我对这个函数的作用还不太了解,因为它的作用在本例子中还不太明显,所以在本例中可有可无???
我的理解:
这个函数应该是通过设置 double epsilon 这个参数来对findContours()找到的轮廓的点进行取舍,比如说:
epsilon我设为10,
在第某个轮廓中,里面有100个点,但是它是这样排布的:
20个点(这20个点隔的距离小于10,后同) ———隔了5个距离———40个点———隔了20个距离———40个点
然后经过approxPolyDP()函数之后后面的40个点就被舍弃了。
2018/5/21 15:36:54
增加验证:approxPolyDP()函数验证
三、多边形筛选
这个就是通过contourArea()函数实现的
因为在一幅图中找到了很多轮廓,但是只有我们想要的这个轮廓有一些特征会和其他轮廓区别开来,在本例中,面积就是这么一个特征,通过寻找最大面积的轮廓来找到数独的边框!
四、找到了数独的边框之后,我们画它出来看看是不是想要找的!
通过drawContours()可以很方便的就把轮廓画出来了。
但是!我,是一个不将就的人,为了直接对轮廓的点操作,我还写了一个画框的方法,其实也很简单
for (int i = 0; i < contours[index].size(); i++)
{
if (i + 1 >= contours[index].size())
line(src, contours[index][i], contours[index][0], (0, 0, 255),4,8);
else
line(src, contours[index][i], contours[index][i+1], (0, 0, 255),4,8);
}
五、参考
1. 关于findContours():
findContours 函数参数详解
OpenCV 的轮廓检测 findContours 分析(层次结构)