我正在编写一个基于 voronoi 的世界生成器,在其中我区分山脉、湖泊、森林和海洋等地理特征。
每个特征都有一个id,以便识别和引用。我使用洪水填充算法来确定细胞属于什么特征。
我已经意识到了一些类似的情况,我想把一个特征分割成多个更小的特征。最直接的例子是两个大森林被一条狭长的森林带连接起来。实际上,它应该被视为两个森林,在狭长地带周围彼此分开,但我的填充算法只是穿过,并将所有东西都标记为一个大森林的一部分。
我想最终给它们贴上“西100英亩木材”和“东100英亩木材”的标签,让它们知道它们来自同一个连续的森林体。我查了部分洪水填充逻辑,但由于缺乏主题术语,我的搜索陷入了困境。
如果你想看我正在做的代码:https://github.com/olinkirkland/map
你通常会使用一个“形态学的开口”,参见维基百科的定义,这是一个形态学的侵蚀,然后是膨胀。如果你在黑色背景上想象一个感兴趣的白色前景对象,侵蚀将侵蚀(蚕食)该对象的边缘,而膨胀将扩展/增肥边缘,从而移除小条带和窄连接。
您可以使用Python中的Scikit Image模块,也可以使用Python或C中的OpenCV。我选择在这里使用ImageMagick在终端的命令行中完成,ImageMagick安装在大多数Linux发行版上,可用于macOS和Windows。
因此,使用此地图图像:
我加载它,反转/否定它以使森林变白,然后应用我提到的形态学开口,然后反转它并保存:
magick convert map.png -negate -morphology open disk:5 -negate result.png
找到连接区域后,可以使用右手规则 (https://en.wikipedia.org/wiki/Maze_solving_algorithm#Wall_follower) 在内部进行追踪。
要找到能够形成良好分割点的单像素路径,您可以在此内部路径中查找两次访问的像素(每个方向一次)。如果路径长度在分割的两边都足够长,那么您可以在该像素处将区域一分为二,然后再尝试使用较小的区域。
如果你想找到超过一个像素宽的分割点,或者确保两侧的森林足够“强大”,我建议采用一种基于像素的方法,将其与其他方法相结合:
>
BFS以去除距离边界小于w的像素。
找到每个剩余的连接区域。每个都是森林的“中心”。
检查每个中心,确保其像素距离边缘足够远,可以成为森林的中心。
将移除的像素加回去,将它们连接到最近的中心。
你可以使用图像处理中的一种技术,使用模糊和应用50%的阈值。这样,减少了细连接和尖钉,并且特征通常变得更圆,而对象的整体大小不应该在一个特定的方向上改变。以下是重复应用该流程时的图像:
通过模糊和应用阈值来分离森林
上图代表您的原始情况,其中两个森林由一条细走廊连接。该过程逐步删除走廊。
你可以在这个过程中调整一些参数,例如模糊半径和步数,所以你可以根据自己的需要进行调整。