将高度图映射到基于网格的轮廓格式

18

我有一个二维高度地图,格式如下:

06 36 39 42 43 55 ... 
37 40 43 43 45 46 ...
40 43 44 45 46 48 ...
44 44 46 47 48 50 ...
41 44 45 47 48 48 ...
...

我需要将其重新映射为基于格林的轮廓格式(以便可以进一步映射为精灵)

. . . . | . . 
. . . . \ . . 
. . . / / . . 
. . . | . . . 
. . . | . . . 
. / - / . . . 

这里的 . 表示平坦区域,|- 表示直立的悬崖,/\ 表示悬崖的拐角 (每个字符都代表两种不同的可能性)。

我尝试了标准的 marching squares 方法,但发现只采样3个相邻点会导致很多问题,因为它会过度加载相邻的情况。 (请注意下方不合适的额外直立悬崖)

. . . . | . \ 
. . . . \ \ .
. . . / / - .
. . . | - . .
. . . | . . .
. / - / . . .

我希望能得到一些算法/方法的参考,以帮助处理这种情况。我知道使用某种深度优先搜索的轮廓线走访是一种选项,但尚未尝试过,并且宁愿把它留作最后的选择。还有一些特征的表示问题,例如是否包括仅为1个元素的崖壁脊或者只是忽略它们。另一种选择是通过生成的轮廓并使它们平滑地拟合在一起,但这似乎太hacky了...


Marching square的情况会相互覆盖,我已经设置了优先级以确保平地不会覆盖悬崖,但仍然存在错误。使用阈值完全没有问题,问题在于选择正确的情况。有时算法可能正在尝试做正确的事情,而我只是缺乏表示符号来理解它。 - Sash
1
你查看了关于这个主题的Wikipedia简介吗?(该文章还描述了您在此情况下似乎需要的_边缘细化_。)我曾经使用Sobel算子获得过相当不错的结果(如果您的图片没有噪声,这对您也应该有效)。这个SO问题也提到了一个能够给出良好结果的算法。 - Alexander Pavlov
2
为什么不能采样所有8个邻居?(如果可用) - Jay
gis.stackexchange.com上的大佬们可能能够帮助您解决这个问题。 - Mr_Chimp
你能否使用Sobel滤波器(或其他边缘检测滤波器)并处理输出,将滤波器输出值替换为“。”,“-”,“|”,“/”和“\”? - higuaro
显示剩余2条评论
1个回答

1

创建一个插值/最佳拟合函数。您的模型应该是一个二维多项式(在xy中),其次数“刚刚好”:不要太高,以至于您会过度拟合所有内容,但也不要太低,以至于您会失去细节。

现在您有一个可以通过设置f(x,y)= height来切片的数学函数。这个方程的解是等高线。现在根据您是否能够解析地解决问题,您有两个选择。

  • 假设你无法用解析方法求解,你仍然可以轻松地追踪出曲线的近似值:
    • 首先将网格涂为白色,如果 f(x,y)>height 就涂成黑色。注意所有的“过渡”区域,在一个大约小于 1 的网格内有黑白交替的部分:这些正方形是等高线所在的位置。
    • 随机选择一个转换正方形,然后在大约小于 1 的网格半径内搜索 f(x,y)==height,以找到曲线上的点。在那个点(不一定在网格上)我们计算梯度∇f(x,y) = (∂f/∂x, ∂f/∂y)(向上的矢量)。我们将其旋转 90 度,以便朝着等高线的方向。我们非常缓慢地(步长比网格小得多)追踪等高线。这将带领我们绕过等高线的全部轮廓。
    • 每次我们在这个迹线中通过一个网格盒子时,我们根据平均梯度指向的方向标记它为 {|,-,/} 中的任意一个(我们还必须将未标记的相邻箱子标记为 .;见 [*])。
    • 请注意,可能仍然会剩下过渡网格盒子!例如,如果你有两个山丘,你将填入一个圆圈,但等高线是两个圆圈。在另一个随机的(未标记的)“转换”网格盒子上重复上述过程(这就是为什么我们需要 [*],否则我们可能会专注于已经考虑过的区域的邻居)。重复直到没有更多未标记的“转换”网格盒子。
    • 对于每个要绘制成等高线的 height 级别,请做这个步骤,然后完成。
  • 你可能能够像解析锥体一样解决它,但这很可能不太可能,并超出了这个问题的范围。如果你能求出曲线,你可以使用各种技术将其“网格化”(例如参数化它,然后沿着等高线走,使用大约半个网格的步长,注意最近的邻居)。

如果您的轮廓之一与另一个重叠,那么您的轮廓高度间距太小了。如果您对给定的轮廓不满意,那么可能性集合 {-,|,/,} 太小了。


我认为最佳拟合函数对点的顺序非常敏感。如果它们都在一条直线上(唯一的X坐标),那就没问题,但如果是一个闭合轮廓形状,那就行不通了。 - Wouter Lievens
@WouterLievens: 我从未建议过最佳匹配函数;那样做会很糟糕。在第一段中,我特别建议他/她选择“一个二维多项式,其次数是‘刚好’的:不要太高,否则你会过度拟合所有内容,但也不要太低,以至于你失去了细节”。 - ninjagecko
我明白了,我只是不明白你将如何对这些点进行排序。如果他可以对它们进行排序,那么他也可以连接这些点并使其平滑。 - Wouter Lievens
@WouterLievens:对轮廓进行排序是通过沿着垂直于梯度的向量进行操作,该向量在提到(∂f/∂y, -∂f/∂x)时进行描述。 - ninjagecko
曲线所追踪的是等高线。 - ninjagecko
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接