我遇到了一个算法,它找到了一个图形的轮廓,但是我很难证明它为什么有效,我有点理解它的工作原理,但我无法推导出来我自己使用的公式。
这是算法:
假设我们有一个二进制图像(图中为黑色,背景为白色)。所有像素都存储在二进制矩阵中,其中1为白色,0为黑色。
0)找到第一个黑色像素(例如,如果它是一个正方形,那么它位于左上角)。
1)设置Lx = x和Ly = y(第一个像素的坐标),并且Rx = x-1和Ry = y。同时保留2个常数firstX = x和firstY = y(稍后我们将需要它们)。
2)计算Tx = Rx + Ly - Ry和Ty = Ry + Rx - Lx。
3)执行以下循环:
do {
if (m[Tx][Ty] == 0) {
Lx = Tx;
Ly = Ty;
m2[Tx][Ty] = 0;
} else {
Rx = Tx;
Ry = Ty;
}
if (Lx == Rx || Ly == Ry) {
Tx = Rx + Ly - Ry;
Ty = Ry + Rx - Lx;
} else {
Ty = (Ly + Ry - Lx + Rx) / 2;
Tx = (Lx + Rx + Ly - Ry) / 2;
}
} while (Tx != firstX || Ty != firstY);
在上面的代码中, m 是原始图像, m2 是仅包含轮廓的图像。
我试图想象它是如何工作的,这就是我得到的:
显然,它正在进行某种曲折运动,以便在边缘上获得这些零点并确定轮廓。
所以,我的问题是,这是一个已知的算法吗?这些公式究竟是如何得出的:
Tx = Rx + Ly - Ry;
Ty = Ry + Rx - Lx;
和
Ty = (Ly + Ry - Lx + Rx) / 2;
Tx = (Lx + Rx + Ly - Ry) / 2;
答案 0 :(得分:2)
<强>提示强>:
在整个执行过程中,R,L和T是直接的8个邻居(在Moore意义上)。
算法重复地将T分配给R和L中的一个,这取决于T处的值,使得L总是在黑色像素上而R在白色上。然后它通过围绕R旋转RL来重新计算T.
暂时假设Rx=Ry=0
;那么如果L是4邻居(Tx,Ty):=(Ly,-Lx)
,则旋转90°;否则,(Tx,Ty):=((Lx+Ly)/2,((Ly-Lx)/2)
,旋转45°。此规则如下所示:
初始配置是图中的左上角,L是第一个黑色像素。鉴于进展规则,很明显该算法将遵循链(8个连接像素的序列)。
事实上,对于R的位置,人们围绕它旋转L,直到找到黑色像素;然后将R移动到该像素。这是名为Radial Sweep的过程。
我们可以用等效的形式重写它(重命名R=B
,L=W
,并将Rot
定义为上面的轮换规则。)
B, W= B0, LeftOf(B0)
do
while Rot(B, W) is White
W= Rot(B, W)
B= Rot(B, W)
while B != B0
仍然要证明
链被关闭(我们将回到起始像素),
它是斑点的轮廓(链中的每个像素都有黑色和白色的邻居),
没有错过任何像素。
更确切地说,L跟随内部轮廓,而R跟随外部轮廓(和T跟随外部轮廓)。