接上篇内容,继续对CALTag源码进行详细剖析~
3、 角点检测
为了方便说明,在此将一个自识别标记,也就是上一步骤保留的连通区域,称为一个quad。下面分析一下如何检测quad的四个角点。
首先找到该quad的外接最小矩形bbox, 二值化掩模mask,然后对mask边界加了3个像素的pad,目的是方便后面做形态学闭运算,运算完再去掉pad。然后找出边界轮廓上的点,计算他们的梯度方向,将这些梯度方向聚成4类,从而获得4个主要的边缘方向。然后分别对每一类的边界点进行线性拟合,得到4条拟合的直线。然后计算它们的交点就是角点。
然后有一个很重要的步骤,就是把这些角点按照逆时针进行排序,这对后面恢复角点、求对应关系至关重要。排序的方法是先求出四个角点的平均坐标,就是该quad的重心。然后分别求每个角点和该重心的向量,将这些向量转化为极坐标系,将极坐标系下的角度按照升序排列就是逆时针角点的顺序。极坐标下的角度如下:
上述步骤对应的代码是:
[isq,cnr,cnr0] = fitquad( R(i).BoundingBox, R(i).FilledImage, layout );
这样每个quad就会计算出四个伪角点(下图中四个红色十字),这样每个真实的角点周围就会有四个伪角点,那么如何根据这四个伪角点来计算真实角点坐标呢?
首先是根据距离聚类,然后取聚类中心的点作为初始角点saddles_0(下图中绿色圆圈),然后使用和opencv中一样的方法来寻找亚像素级精度的鞍点(下图中绿色十字)。也就是下面几句代码
[saddles] = cornerfinder_saddle_point( flipud(saddles_0), I, 11,11 );
[saddles,good] = cornerfinder_saddle_point( saddles, I, 9,9 );
saddles = flipud( saddles(:,good) );
结果见下图
4、 Code/ID提取和验证
要提取标记中的code,首先需要从图片中采样出code的二进制码。流程如下图。首先定义一个理想的单位方形(即代码中的unitSquare),对应下图中左侧的黑色方形。右侧图是图片中真实的quad。首先把unitSquare的四个角点映射到quad的四个角点&