提示:
正如在其他答案中所说,发出轮廓像素列表可以实现为扫描线过程,在此过程中检查运行端点的 3x3 邻域。
此过程将以加扰的方式发出像素,作为需要存储和重新排序的一系列直接和反向弧。
另一种方法可以基于实现标准摩尔邻域算法的想法,该算法具有以所需顺序枚举轮廓像素的优势。
这个过程需要知道当前像素周围的 8 邻域配置,并且想法是在每次移动到另一个像素时更新这个邻域:我们维护包含当前像素的运行的索引以及行中两个面向运行的索引上面和下面。
每次移动到另一个像素时,我们都需要更新这三个索引,这将涉及排序运行列表中的短顺序搜索。这可以看作是对像素的伪随机访问机制,考虑到连续访问是强本地的并且可以被缓存。
更新:
在我使用的运行长度编码表示中,只有黑色运行被编码为三元组(X, Y, L)
。运行按行从上到下排序,然后从左到右连续排序。
为方便起见,我们可以切换到“线性寻址”方案,就好像所有图像行已经被一个接一个地附加,并且每个像素都由一个数字指定Z = X + Y.Nx
(其中Nx
是图像宽度)。
所以我们有一个黑色运行列表,白色运行隐含在两个连续的黑色运行之间。
在处理过程中,我们可以随时记住在当前像素之前或当前像素上开始的运行的索引(R[I].Z <= Z < R[I+1].Z
)。我们可以通过检查我们是在运行内部还是在运行与下一个之间(Z < R[I].Z + R[I].L
)来判断像素的颜色。
如果我们向左移动一个位置,则Z
减少一个1
,我们可能必须选择上一个运行 ( I--
)。
如果我们向上移动一个位置,则Z
减少一个位置,Nx
我们可能不得不回溯几次(I--
直到R[I].Z <= Z
再次)。
图片显示了当前像素及其 4 个相邻像素,以及黑色运行的“影响区”。我们可以类似地处理所有八个位移方向。
正如我们所看到的,每一步都需要进行一些操作,甚至等于连续运行的次数,这被认为是一个很小的值。使用这个概念,我们可以以合理的成本沿着任意路径遍历 RLC 表示,而无需重建整个位图。
由于 Moore Neighborhood 算法在轮廓长度上采用线性时间,因此基于此线性运行寻址的实现也将采用线性时间(对于每行有限数量的运行)。