C#2D阵列放大

时间:2014-03-05 18:27:01

标签: c# arrays xna interpolation scaling

解决

我正在研究2D程序岛生成器。到目前为止,我已经使用了几种噪声函数和混合来实现所需的岛形状,但目前它们的尺寸仅为300 x 200像素。我想要做的是将图像数据(不是图像)扩展到400,000 x 400,000范围内所需的地图大小。我考虑过简单地将噪声函数更改为较低的频率,从而产生较大的岛屿,但我也将它们与生成的梯度混合在一起,该梯度已经在计算上很重。增加生成的渐变的大小会大大缩短生成时间。

我的岛屿形状/图像:http://4.bp.blogspot.com/-ed7nK7jwcJc/UxYjNMxUF-I/AAAAAAAAASc/sG-BygA4usA/s1600/PopulationMap1.png

岛屿背后的数据是一系列花车,范围从0到1,代表水/海滩/陆地。我所需要的只是将 THAT 数据扩展到我继续生成道路等所需的范围。基本上每个像素都是一个瓦片,我需要宽度约为400k,宽度为300。我意识到输入数据可能太少而无法将其扩展到高,但我仍然想尝试它。

我已经阅读了所有图像过滤和插值方法,但我无法掌握它们中的任何一个。我注意到这个问题已经问Array interpolation但是我无法理解如何让它在大于4x4的网格上工作,但是OP正好描述了我正在寻找的东西。

基本上线性或双三次滤波/缩放浮点值的大网格。我只需要一些示例代码来概述该过程..

如果所有其他方法都失败了,我会将渐变切换为更简单的方法,只生成我希望它开始的大小的整个地图数据。但我真的想尝试扩展它。提前谢谢。

编辑 - 我已经达到了这样的程度,即我所查询的点周围的每个瓦片都有一个加权值对列表。因此,如果我查询5.5,5.5的值,我会得到周围(包括)5,5的瓦片的值和重量。所以我有一个9 {0.9,1.27} {0.3,0.77}等值对的列表,其中第一个是数组中的元素,第二个是它的权重(它与查询点之间的距离的倒数)。现在我正在努力将所有这些加权值对加在一起以达到最终值。我很确定它与某种插值有关但我无法完全掌握它的方法。如果我能够通过这一部分那么我应该对其余部分做得很好。

1 个答案:

答案 0 :(得分:0)

我找到了一种适合我的方法。我将尝试在此处解释我的解决方案,以防其他人需要有关此主题的帮助。请注意,这可能不是最佳解决方案,但确实可以完成工作。

我从源数组float[,] sourceArray开始  还有一个我希望缩放到float[,] targetArray

的更大数组

然后我循环遍历目标数组中的每个tile(数组元素),并获得它的中心与缩放目标的总高度和宽度之间的百分比值。然后我调用一个返回计算值的方法,传入百分比,源数组,源数组的宽度和源数组的高度。

for(float x = 0, x < scaleWidth, x++)
{
    for(float y = 0, y < scaleHeight, y++)
    {
        Vector2 percentage = new Vector2((x+0.5)/scaleWidth, (y+0.5)/scaleHeight);
        targetArray[x,y] = GetScaleValueAt(percentage, sourceArray, sourceWidth, sourceHeight);
    }
}

我的GetScaleValueAt()方法返回请求的,正确缩放的值。首先,它根据百分比在源数组中找到相应的位置。它还会找到该位置所在的图块。

public float GetScaleValueAt(float percent, float[,] source, int width, int height)
{
    Vector2 location = new Vector2(width * percent.X, height * percent.Y);
    Point centerTile = new Point((int)Math.Floor(loc.X), (int)Math.Floor(loc.Y));\

然后我使用另一种方法来获得与中心区域相邻的所有区块(包括中心区块)

    List<Point> tiles = GetIncNeighborhood(centerTile.X, centerTile.Y, width, height);

接下来,我遍历此列表并使用WeightedPair填充第二个列表,该列表只是一个具有两个浮点值的类或结构 - float value, weight是可访问的。 weight是根据location与每个图块之间距离的倒数计算出来的。我还保存了加权值的总和。

    List<WeightedPair> weightValues = new List<WeightedPair>();
    float weightedTotal = 0;
    foreach(Point p in tiles)
    {
        Vector2 distance = new Vector2();
        distance.X = System.Math.Abs(loc.X - p.X);
        distance.Y = System.Math.Abs(loc.Y - p.Y);
        float inverseDist = 1 / distance.Length();

        float value = source[p.X, p.Y];

        weightedTotal += invDist;
        weightValues.Add(new WeightedPair(value, invDist));
    }

最后,我遍历weightValues列表并通过将每个value乘以相应的weight/weightedTotal来计算值。

    float finalValue = 0;
    foreach(WeightedPair w in weightValues)
    {
        finalValue += w.value * (w.weight/weightedTotal);
    }
    return finalValue;
}

结果是一个类似于整体形状和复杂性的较小版本的图像,带有一些轻微的伪像和保真度问题。它不如标准图像处理技术好,但对我来说效果很好。希望这有助于某人。