2016-11-24 22 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