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
相乘)。如果您在1D的情况下这样做,您将看到生成的函数已经好得多了0.01
- 将倍频程数从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) 我知道,我不是苏