Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何制作更平滑的柏林噪声发生器?_Python_Random_Perlin Noise - Fatal编程技术网

Python 如何制作更平滑的柏林噪声发生器?

Python 如何制作更平滑的柏林噪声发生器?,python,random,perlin-noise,Python,Random,Perlin Noise,我试图用柏林噪声发生器制作地图的瓷砖,但我注意到我的噪声太尖锐了,我的意思是,它有太多的海拔高度,没有平坦的地方,它们看起来不像山、岛屿、湖泊或其他东西;它们看起来太随机了,而且有很多峰值 在问题的末尾,需要进行修改以解决问题。 问题的重要代码是: def Noise(self, x): # I wrote this noise function but it seems too random random.seed(x) number = random.random()

我试图用柏林噪声发生器制作地图的瓷砖,但我注意到我的噪声太尖锐了,我的意思是,它有太多的海拔高度,没有平坦的地方,它们看起来不像山、岛屿、湖泊或其他东西;它们看起来太随机了,而且有很多峰值

在问题的末尾,需要进行修改以解决问题。

问题的重要代码是:

def Noise(self, x):     # I wrote this noise function but it seems too random
    random.seed(x)
    number = random.random()
    if number < 0.5:
        final = 0 - number * 2
    elif number > 0.5:
        final = number * 2
    return final

 def Noise(self, x):     # I found this noise function on the internet
    x = (x<<13) ^ x
    return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0)
def Noise(self, x, y):     # I wrote this noise function but it seems too random
    n = x + y
    random.seed(n)
    number = random.random()
    if number < 0.5:
        final = 0 - number * 2
    elif number > 0.5:
        final = number * 2
    return final

def Noise(self, x, y):     # I found this noise function on the internet
    n = x + y * 57
    n = (n<<13) ^ n
    return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0)
1D:

def Noise(self, x):     # I wrote this noise function but it seems too random
    random.seed(x)
    number = random.random()
    if number < 0.5:
        final = 0 - number * 2
    elif number > 0.5:
        final = number * 2
    return final

 def Noise(self, x):     # I found this noise function on the internet
    x = (x<<13) ^ x
    return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0)
def Noise(self, x, y):     # I wrote this noise function but it seems too random
    n = x + y
    random.seed(n)
    number = random.random()
    if number < 0.5:
        final = 0 - number * 2
    elif number > 0.5:
        final = number * 2
    return final

def Noise(self, x, y):     # I found this noise function on the internet
    n = x + y * 57
    n = (n<<13) ^ n
    return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0)

我在找更平滑的东西

也许在2D噪音中很难注意到我所说的,但在1D中要容易得多:

test = D1(1000, 3)
test.graph()

来自互联网的噪声函数的峰值稍小,频率也较低,但仍然有太多的峰值。我在找更平滑的东西

可能是这样的:

或者这个:

p.S:我是基于

编辑: Pikalek:

即使是较低的值,它也有峰值,没有曲线或平滑/平坦的线

geza:解决方案 感谢您,我找到了问题的解决方案:

def Perlin(self, lenght_axes, octaves, zoom = 0.01, amplitude_base = 0.5):
    result = []
    
    for y in range(lenght_axes):
        line = []
        for x in range(lenght_axes):
            value = 0
            for o in range(octaves):
                frequency = 2 ** o
                amplitude = amplitude_base ** o
                value += self.Interpolate_Noise(x * frequency * zoom, y * frequency * zoom) * amplitude
            line.append(value)
        result.append(line)
        print(f"{y} / {lenght_axes} ({y/lenght_axes*100:.2f}%): {round(y/lenght_axes*20) * '#'} {(20-round(y/lenght_axes*20)) * ' '}. Remaining {lenght_axes-y}.")
    return result
其他修改包括:

  • Z=np.array(self.result)
    代替此
    Z=np.array(self.result)。在图形函数中重塑(self.lenght\u轴,self.lenght\u轴)
  • 使用
    math.floor()
    (请记住
    import math
    )代替
    round\u Noise
    中的
    Interpolate\u Noise
    函数中的
    round\u x
    round\u y
    变量
  • Noise
    中的
    return
    行(第二行)修改为
    return(1.0-((n*(n*n*15731+789221)+1376312589)&0x7fffffff)/1073741824.0)
    D2(10000,10)
    现在唯一奇怪的是山(黄色)总是在同一个地方附近,但我认为这是更改
    Noise
    函数中的数字的问题

您需要实施更激进的平滑算法。最好的方法是使用矩阵卷积。其工作方式是,您有一个矩阵,我们称之为“内核”,它应用于网格中的每个单元,创建一个新的转换数据集。内核示例可能是:

0.1 0.1 0.1
0.1 0.2 0.1
0.1 0.1 0.1
假设你有一个这样的网格:

2 4 1 3 5
3 5 1 2 3
4 9 2 1 2
3 4 9 5 2
1 1 3 6 7
假设我们想将内核应用于最中心的
2
,我们将以内核的形状切割网格,并将每个单元格与其对应的内核单元格相乘:

. . . . .
. 5 1 2 .       0.1 0.1 0.1       0.5 0.1 0.2
. 9 2 1 .   x   0.1 0.2 0.1   =   0.9 0.4 0.1
. 4 9 5 .       0.1 0.1 0.1       0.4 0.9 0.5
. . . . .
然后我们可以将所有这些值相加,得到单元格的新值,
0.5+0.1+0.2+0.9+0.4+0.1+0.4+0.9+0.5=4
,并在新数据集上填充该空间:

? ? ? ? ?
? ? ? ? ?
? ? 4 ? ?
? ? ? ? ?
? ? ? ? ?
。。。可以想象,为了填充新的数据集,我们必须对网格中的其他空间重复此操作。一旦完成,我们就扔掉旧数据,使用这个新的网格作为数据集

这样做的好处是,可以使用大量内核来执行非常大的平滑操作。例如,您可以使用5x5或9x9大小的内核,这将使您的噪声更加平滑

还有一点需要注意,内核的构建需要确保其所有单元的总和为1,否则就不会有质量守恒(也就是说,如果总和大于1,那么峰值会变得更高,数据的平均值也会更高)。5x5矩阵的示例如下:

0.010 0.024 0.050 0.024 0.010
0.024 0.050 0.062 0.050 0.024
0.050 0.062 0.120 0.062 0.050
0.024 0.050 0.062 0.050 0.024
0.010 0.024 0.050 0.024 0.010
确保这种质量的一种方法是简单地规范化矩阵;将每个单元格除以所有单元格之和。例如:

1  4  16 4  1                    0.002808989    0.011235955 0.04494382  0.011235955 0.002808989
4  16 32 16 4                    0.011235955    0.04494382  0.08988764  0.04494382  0.011235955
16 32 64 32 16  (sum = 356) -->  0.04494382     0.08988764  0.179775281 0.08988764  0.04494382
4  16 32 16 4                    0.011235955    0.04494382  0.08988764  0.04494382  0.011235955
1  4  16 4  1                    0.002808989    0.011235955 0.04494382  0.011235955 0.002808989

我在您的代码中发现了以下错误:

  • 您需要将
    Interpolate_Noise
    参数相乘,以“放大”贴图(例如,将
    x
    0.01
    相乘)。如果您在1D的情况下这样做,您将看到生成的函数已经好得多了
  • 将倍频程数从3增加到更大(3个倍频程不会产生太多细节)
  • 使用振幅0.5^倍频程,而不是0.25^倍频程(但您可以使用此参数,因此0.25本身并不坏,但它不会给出太多细节)
  • 对于2D的情况,你需要有2个外循环(一个用于水平,一个用于垂直。当然,你仍然需要有倍频程循环)。因此,您需要使用水平和垂直位置对噪声进行适当的“索引”,而不仅仅是
    x
    x
  • 完全删除平滑。柏林噪音不需要它
  • 2D noise函数有一个bug:它在返回表达式中使用
    x
    而不是
    n
  • 在三次插值中,使用
    round
    而不是
    math.floor

下面是我的答案,用一个简单的Perlin类(不适合Perlin)噪声的(C++)实现:

您可以使用简单算法使噪声更平滑->
f(n)=(f(n-1)+f(n+1))/2

不知道为什么,但它正在工作


尽管有标题,但该教程并未涉及实际的柏林噪声(使用渐变),而是针对(可以给出类似的结果,但有一些)。无论如何,可能还有其他问题,但我怀疑第一个问题是您的初始值1000。如果你尝试100张或10张会怎么样?@Pikalek,我在最后添加了更多照片。所以我不是在制造柏林噪音??你在想什么?它是西班牙语的,但有照片。这不也是柏林噪声吗?从技术上讲,不,这两个教程都没有使用柏林噪声,但是如果你得到了你需要的输出类型,不用担心。“值噪波”的计算要简单得多,对于某些应用程序来说效果很好。但是,如果“值噪波”对你来说不起作用,你可以读取或查找“单纯形噪波”。1)好的,但这不仅会使所有的峰值都处于较低的刻度?我的意思是,不是像[0.2,0.7,0.6,0.4,0.5]这样的东西,而是[0.002,0.007,0.006,0.004,0.005],但是每个值之间的相对大小是相同的。2) 我知道,我不是苏