首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将多个高度贴图缝合在一起以移除接缝?

如何将多个高度贴图缝合在一起以移除接缝?
EN

Stack Overflow用户
提问于 2013-05-08 13:13:07
回答 2查看 3K关注 0票数 1

我正在尝试编写一个算法(用c#),它可以将两个或多个不相关的高度贴图缝合在一起,这样贴图之间就没有可见的接缝了。基本上,我想模仿这个页面上的功能:http://www.bundysoft.com/wiki/doku.php?id=tutorials:l3dt:stitching_heightmaps

(你可以只看图片来理解我所说的要点)

我还希望能够获得一个单一的高度图,并改变它,使其可以平铺,以便创建一个无尽的世界(所有这些都是用在Unity3d中)。但是,如果我可以将多个高度图缝合在一起,我应该能够很容易地修改算法以作用于单个高度图,所以我不担心这一部分。

任何类型的指导都将不胜感激,因为我已经一遍又一遍地寻找解决方案,但没有成功。只是在正确的方向上的一个简单的推动将是非常感谢的!据我所知,许多图像处理技术都可以应用于高度图,但一直无法找到能够产生我想要的结果的图像处理算法。例如,image stitching似乎只适用于视野重叠的图像,而不适用于不相关的高度贴图。

在某种程度上利用FFT低通滤波器是否有效,或者只在生成单个可平铺高度图时有用?

因为算法是在Unit3d中使用的,所以任何c#代码都必须限制在Unity3.5上,因为我相信这是.Net使用的最新版本。谢谢你的帮助!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-05-09 11:13:53

我最初尝试将高度图缝合在一起,包括对高度图上的每个点执行以下步骤:

相反的点只是在x轴(如果缝合水平边)或z轴(对于垂直边)上反射的第一个点。

2)使用以下公式找到点的新高度:

代码语言:javascript
复制
newHeight = oldHeight + (average - oldHeight)*((maxDistance-distance)/maxDistance);

其中,距离是高度贴图上的点到最近的水平或垂直边的距离(取决于要缝合的边)。距离小于maxDistance (这是一个影响地形改变程度的可调值)的任何点都将根据此公式进行调整。

这是旧的公式,虽然它为大多数地形产生了非常好的结果,但它在更改的高度图点区域和未更改的高度图点区域之间的区域中创建了明显的线。我几乎立刻意识到这种情况的发生是因为与未改变的区域相比,改变区域的斜率太陡峭了,因此在两者之间产生了明显的对比。不幸的是,我以错误的方式解决了这个问题,寻找如何模糊或平滑对比区域以移除线条的解决方案。

在平滑技术取得很小的成功后,我决定尝试减少改变区域的斜率,希望它能更好地与未改变区域的斜率混合。我很高兴地报告,这大大改进了我的拼接算法,删除了上面报告的99%的线条。

旧公式的主要罪魁祸首是这一部分:

代码语言:javascript
复制
(maxDistance-distance)/maxDistance

它根据点到最近边的距离线性地产生一个介于0和1之间的值。随着高度映射点和边缘之间距离的增加,高度映射点将越来越少地利用平均值(如上所述),并且越来越接近它们的原始值。这种线性插值是导致too step斜率的原因,但幸运的是,我在Unity的API的Mathf类中找到了一个内置方法,它允许二次(我相信是三次)插值。这是SmoothStep Method

使用这种方法(我相信在here发现的Xna框架中可以找到类似的方法),在中等距离时,在确定高度映射值时使用了多少平均值的变化变得非常严重,但随着距离接近maxDistance,严重程度会呈指数级降低,从而创建一个不太严重的坡度,更好地与未改变区域的坡度混合。

代码语言:javascript
复制
//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;

甚至可能有更好的插值方法来产生更好的拼接。如果我找到这样的方法,我一定会更新这个问题,这样任何其他希望进行高度图拼接的人都可以找到他们需要的信息。称赞rincewound在线性插值的正确轨道上!

票数 0
EN

Stack Overflow用户

发布于 2013-05-08 15:02:04

在你发布的图像中所做的事情对我来说看起来很像简单的线性插值。所以基本上:你需要两张图片(左,右)并定义一个拼接区域。对于线性插值,您可以采用左侧图像的最左侧像素(在拼接区域中)和右侧图像的最右侧像素(也在拼接区域中)。然后用插值法填充其间的空白处。

以这个例子为例--我在这里只用了一行代码来说明这个想法:

代码语言:javascript
复制
Left = [11,11,11,10,10,10,10]
Right= [01,01,01,01,02,02,02]

假设我们的重叠是4个像素宽:

代码语言:javascript
复制
 Left = [11,11,11,10,10,10,10]
 Right=          [01,01,01,01,02,02,02]
                   ^  ^  ^  ^ overlap/stitiching region.

左边的图像最左边的值是10,右边的图像的最右边的值是1。现在我们分两步在10和1之间线性插值,我们的新拼接区域如下所示

代码语言:javascript
复制
stitch = [10, 07, 04, 01]

我们以下面的拼接代码结束:

代码语言:javascript
复制
line = [11,11,11,10,07,04,01,02,02,02]

如果你将它应用于两个完整的图像,你应该会得到与你之前发布的结果类似的结果。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16433122

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档