2016-11-24 21 views
0

我在Java中实现了菱形方块算法,但我并不完全满意作为高度图的结果。它形成了一个“湖泊”的小批量批次 - 小高度的小区域。使用菱形方块算法生成高度,然后进行归一化。在下面的例子中,白色=高,黑色=低,蓝色是高度15以下的任何东西:海洋的占位符。从钻石方形地图中删除湖泊

height map example

此图像显示了本色的高度图 enter image description here

我怎样才能顺利的地形,以减少湖泊的数量?

我已经研究了一个简单的框模糊功能(将每个像素设置为其邻居的平均值),但是这会导致奇怪的伪影,可能是因为钻石正方形的方形步骤。

将一个不同的(也许是高斯)模糊是适当的,还是这是我的实现问题? This链接说钻石正方形有一些固有的问题,但这些似乎并不是规律间隔的伪影,而我的高度图是用16(而不是4)值播种的。

+0

研究形态学操作,特别是'关闭' – chris

+1

为什么不为一个像素应用模糊/平均的像素,如果它是蓝色的,而且没有邻居是?这应该很容易做到,并减少“点”效应,即任何没有至少一个即时蓝色邻居的蓝色像素获得所有邻居的平均颜色。 – Thomas

+0

我没有想到这一点。因为湖泊没有规律的间隔,我认为检测它们是O(n^2)。我对更好的解决方案感兴趣,但这应该起作用。 –

回答

0

您的阈值算法需要更合理。您需要实际指定要在大小方面删除的内容,而不仅仅是高度。基本上,简单的阈值设置“海平面”,低于这个水平的任何东西都是水。问题在于,因为用于生成地形的算法是偶然的,所以小的区域可能会被水填满。

要解决这个问题,你需要基本上确定水域的大小,只允许更大的区域。

这样做的一个简单方法是不允许单个“像素”表示水。基本上不要将它们设置为水(可以使用位图,其中每个位代表是否有水)或者简单地提升水平。这应该可以让大部分单个像素从图像中清除出来,并将其清除很多。

您可以扩展此为N像素(本质上代表面积)。基本上你必须通过计算连接像素来确定水域的大小。问题在于,它允许很长的薄区域(可能代表河流)。

所以最好再采取一步,分别计算宽度和长度。

例如,以检测一个简单的单个像素

如果地图[I,J] <阈& &(地图[I-1,J-1]>阈& & ... & &地图[I + 1,j + 1]>阈值),则区域= 1

将检测隔离像素。

你可以修改这个来检测更大的群体并编写一个通用算法来测量任何大小的潜在“海洋”......然后它应该很容易生成任何最小(和最大)大小的海洋地图想。下一步是“固定”(或使用位图)地图中可能低于海平面但未转换为实际水的部分。即,因为我们通常希望海平面以下的东西容纳水。通过使用位图,您可以允许在水中的水或陆地上的水等。

如果你使用平滑,它可能会工作得很好,但你仍然会遇到这样的问题。平滑减少了“海洋”的大小,但是大洋可能会变成一个小而一个小的最终成为单个像素。根据地图的整体平均值,经过足够的迭代后,您可能会得到全部水或全部土地。模糊也减少了地图的细节。

好消息是,如果你用可控参数设计你的算法,那么你可以控制像地图中有多少海洋,它们有多大,它们的方形(如果你想要的话多么圆形) ,或者可以使用多少总水量等)。

您为此付出的更多努力更准确地模拟了现实。最终,如果你想要变得无限复杂,你可以考虑地形是如何形成的等等......但是,当然,这些简单算法的全部重点是让它们在合理的时间内可以计算。

+0

嗯......我不知道我明白你在说什么。 本质上,你从最低点开始,填充所有低于“海平面”的邻居并重复直到所有邻居都在海平面以上? –

+0

@JonTakagi不,我的意思是你基本上计算相邻的蓝色像素。单个蓝色像素意味着8个周围像素不能为蓝色。蓝色表示蓝色的某个阈值。因此,您可以轻松确定孤立像素是否为蓝色,如果是,则可以确定如何将其删除(例如,将其设置为刚好高于阈值)。 – AbstractDissonance

+0

对于大于1的蓝色像素组,它稍微复杂一些,但基本上只计算连接的蓝色像素的数量(这里有算法)。但是这个数字可以作为海洋“地区”的衡量指标。然后,您基本上为海洋大小设置了一个阈值,如果它们低于这个值(例如,面积为10像素或更大的区域将被视为海洋),并且如果它低于该值,则必须以某种方式将其去除(例如,钳位到阈值)。这将有助于摆脱“小”海洋。 – AbstractDissonance