2013-05-08 112 views
1

我想寫一個算法(在C#中),將兩個或更多不相關的高度圖縫合在一起,因此地圖之間沒有可見的接縫。基本上我想模仿這個網頁上找到的功能: http://www.bundysoft.com/wiki/doku.php?id=tutorials:l3dt:stitching_heightmaps如何縫合多個高度圖以去除接縫?

(你可以只看圖片得到的,我說的是什麼要點)

我也希望能夠採取一個單一的高度圖,並改變它,以便它可以平鋪,以創建一個無盡的世界(所有這些都用於Unity3d)。但是,如果我可以將多個高度圖拼接在一起,我應該可以輕鬆修改算法以在單個高度圖上執行操作,所以我不擔心這部分。

任何類型的指導將不勝感激,因爲我已經搜索和搜索解決方案沒有成功。只是在正確的方向簡單微調將不勝感激!我瞭解許多圖像處理技術可以應用於高度貼圖,但一直無法找到能夠產生我期待的結果的圖像處理算法。例如,image stitching似乎只適用於具有重疊視野的圖像,對於不相關的高度圖不是這種情況。

會在某種程度上使用FFT低通濾波器工作,還是隻能用於生成單個tileable高度圖?

由於該算法將在Unit3d中使用,因此任何C#代碼都必須侷限於.Net 3.5,因爲我相信這是Unity使用的最新版本。 感謝您的幫助!

回答

1

好吧,似乎我是在正確的軌道上與我以前的嘗試解決這個問題。我最初嘗試將高度貼拼接在一起涉及到heightmap上每個點的以下步驟:

1)找到高度圖上的一個點與其相對點之間的平均值。相反的點只是在x軸(如果縫合水平邊緣)或z軸(用於垂直邊緣)上反射的第一個點。

newHeight = oldHeight + (average - oldHeight)*((maxDistance-distance)/maxDistance); 

其中距離是從在高度圖到最近的水平或垂直邊緣的點的距離(取決於哪個邊緣要:

2)使用下面的公式找到該點的新的高度縫合)。根據此公式調整距離小於maxDistance的點(這是一個影響地形多少的可調整值)。

這是舊的公式,雖然它在大多數地形上都產生了非常好的結果,但它在變化的高度圖點區域和未改變的高度圖點區域之間的區域中創建了明顯的線條。我幾乎立即意識到發生了這種情況,因爲與未改變的區域相比,改變區域的坡度太陡,因此在兩者之間形成了明顯的對比。不幸的是,我以錯誤的方式解決了這個問題,尋找解決方案來解決如何模糊或平滑對比區域以消除線條。

在平滑技術取得很小的成功之後,我決定嘗試減小變化區域的斜率,希望能夠更好地與未改變區域的斜率相融合。我很高興地報告,這大大改進了我的拼接算法,去掉了上面報告的99%的線條。

從舊式的主要元兇是這一部分:

(maxDistance-distance)/maxDistance 

將其線性地基於點到最近的邊緣之間的距離產生0和1之間的值。隨着高度圖點與邊緣之間的距離增加,高度圖點將利用越來越少的平均值(如上所定義的),並且越來越多地移向它們的原始值。這種線性插值是導致斜率太大的原因,但幸運的是我在Unity API的Mathf類中找到了一種內置方法,允許二次(我相信三次)插值。這是SmoothStep Method。使用這種方法(我相信類似的方法可以在Xna框架找到here),在確定高度圖值時使用多少平均值的變化在中等距離變得非常嚴重,但是嚴重程度減輕了指數級地,距離越接近maxDistance,產生一個不太嚴重的斜率,與未改變區域的斜率更好地融合。新的論壇看起來像這樣:

//Using Mathf - Unity only? 
float weight = Mathf.SmoothStep(1f, 0f, distance/maxDistance); 

//Using XNA 
float weight = MathHelper.SmoothStep(1f, 0f, distance/maxDistance); 

//If you can't use either of the two methods above 
float input = distance/maxDistance; 
float weight = 1f + (-1f)*(3f*(float)Math.Pow(input, 2f) - 2f*(float)Math.Pow(input, 3f)); 

//Then calculate the new height using this weight 
newHeight = oldHeight + (average - oldHeight)*weight; 

可能有更好的插值方法,產生更好的拼接。如果我找到這樣的方法,我肯定會更新這個問題,所以其他想要進行高度貼圖拼接的人都可以找到他們需要的信息。用線性插值方式在正確的軌道上獲得榮譽ruthwound的榮譽!

0

你發佈的圖像中做了什麼看起來很像我簡單的線性插值。 所以基本上:你拍兩張圖像(左,右)並定義拼接區域。對於線性插值,可以將左圖像的最左像素(拼接區域中)和右圖像的最右像素(也在拼接區域中)。然後用填充值填充它們之間的空格。

拿這個例子 - 我使用的是單線這裏要說明的想法:

Left = [11,11,11,10,10,10,10] 
Right= [01,01,01,01,02,02,02] 

比方說我們的重疊是4個像素寬:

Left = [11,11,11,10,10,10,10] 
Right=   [01,01,01,01,02,02,02] 
       ^^^^ overlap/stitiching region. 

左側的左值圖像將爲10 右圖像的最右邊值爲1. 現在我們在2和10之間線性插值,我們的新拼接區域如下所示

stitch = [10, 07, 04, 01] 

我們結束了以下縫合線:

line = [11,11,11,10,07,04,01,02,02,02] 

如果應用此兩個完整的圖像,你應該得到類似於您發佈之前什麼結果。

+0

好的,我明白你在說什麼,但是你會如何將它應用於高度圖?在您的示例中,生成的縫合線的長度爲10,但合併後,最初的左和右線條的長度爲14.我需要生成與原始左/右線條長度相同的新左/右線條,左邊的最右邊的值與右邊的最左邊的值匹配(如果它們不是相同的值,那麼heightmaps之間會有差距)。 – 2013-05-08 16:18:05

+0

感謝您的幫助,插值絕對在正確的軌道上。我添加了一個答案,迄今爲止產生了最好的結果。將自己的答案標記爲問題的答案是否可以,或者通常是否被忽視? – 2013-05-09 03:18:21