需求:
如下图所示,如何获得检测视野中最大的四边形框体和相机的偏转角度?
方案:
由于是室内环境,光线变化不是很灵敏,其次,检测对象都是黄色,考虑用颜色空间YCrCb(肤色检测中首选的方案)过滤掉背景后,只留下四边形框体和边线。
观察到每个框体都有内外两个轮廓,所以用检测内轮廓的方法能够有效的过滤出检测对象,即都是四边形框体;然后根据框体的面积大小筛选出视野中最大的四边形。
剩下的工作就是根据两直线相交求四个顶点,计算出中心点,与图像中心点连线得到偏转角度。
一、颜色空间转换
opencv常用的样色空间包括RGB,HSV和*YCrCb等。*YCrCb颜色空间广泛的用于视频压缩和图像压缩方案,不能算是纯粹的颜色空间,因为它是BGR颜色空间的一种解码方式。
- Y表示亮度
- Cr:RGB空间R通道和Y差值
- Cb:RGB空间B通道和
首先来了解一下opencv提供的API
void cvtColor(InputArray src,OutputArray dst,int code,int dstCn=0);
paraemters:
- 第一个参数:InputArray类型的src,表示输入的图像矩阵
- 第二个参数:OutputArray类型的dst,表示输出的图像矩阵
- 第三个参数:int类型的code,表示颜色转换标识符
- 第四个参数目标图像的通道数,该参数为0时,目标图像根据源图像的通道数和具体操作自动决定。
在BGR图像与YCrCb图像之间的转换,此时的标识code便是
COLOR_BGR2YCrCb
COLOR_RGB2YCrCb
COLOR_YCrCb2BGR
COLOR_YCrCb2RGB
得到的效果如下图所示:
二、获取内轮廓
输入一幅图像,如果是仅仅是查找最大的轮廓,那么问题也比较简单了,直接找出所有的轮廓,然后根据轮廓的面积,遍历查找出最大的轮廓即可。如果是找最大的外轮廓,那么问题也比较简单,Contour retrieval mode有参数,CV_RETR_EXTERNAL:只检索最外面的轮廓。r然而对于最大的内轮廓,opencv并没有提供这样的接口。
mode - 轮廓检索模式
- CV.RETR_EXTERNAL - 仅检索外轮廓,并为所有轮廓设置层级结构。
- CV.RETR_LIST - 检索轮廓但不建立任何层次关系。
- CV.RETR_CCOMP - 检索所有轮廓并将它们组织成两级层次结构。上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
- CV.RETR_TREE - 检索所有轮廓并建立等级树结构的轮廓。
这里只能自己写一个函数,这个函数的原理就是:
1.找出所有的轮廓,包含内轮廓和外轮廓;
2.仅找出外轮廓;
3.删除所有轮廓中的外轮廓,即得到内轮廓
4.找出内轮廓中的最大轮廓
主要用到了opencv中以下几个函数:
- findContours
- contourArea //主要用于计算图像轮廓的面积
- approxPolyDP //对图像轮廓点进行多边形拟合
得到的效果如下图所示:
三、LSD直线检测
这里的直线检测算法用的是LSD,LSD是一种局部提取的算法,运行速度比霍夫线变换Hough要快。但是由于局部检测算法自增长的特点,对于长线段被遮挡、局部模糊等原因经常割裂为多条直线。为了将割裂的线段合并,笔者自己做了另外的处理,大致如下:
- Construct a window (bounding rectangle) around a
line1
. line2
angle is close enough toline1
's and at least one point ofline2
is insideline1
's bounding rectangle
Often a long linear feature in the image that is quite weak will end up recognized (HoughP, LSD) by a set of line segments with considerable gaps between them. To alleviate this, our bounding rectangle is constructed around line extended in both directions, where extension is defined by a fraction of original line width.
- remove small lines
- partion via partioning function
- build point clouds out of each equivalence classes
- fit line to each equilavence class point cloud
得到的效果如下图所示:
展望:
对于单一场景下的框体检测,文中所提到的算法应该是足够了,稳定性测试也有保证。
但是考虑到场景变化,或者框体不一致等情况,后续还需要加入深度学习能更加稳定的检测到视野中的长方形框体,再用RGB-D camera替代Monocular camera,姿态估计能更加准确。
ps 附上一篇博客Fast and Accurate Document Detection for Scanning,仅供参考。
2019-05-01·CHINA
By Z