title: How to make a smoother Perlin noise generator?
body: <p>I'm trying to use a Perlin noise generator to make the tiles of a map, but I notice that my noise is too spiky, I mean, it has too many elevations and no flat places, and they don't seem like mountains, islands, lakes or anything; they seem much too random and with a lot of peaks.</p>
  <p><strong>At the end of the question there are the changes needed in order to fix it.</strong></p>
  <p><strong>The important code for the question is:</strong></p>
  <p><strong>1D:</strong></p>
  <pre><code>def Noise(self, x):     # I wrote this noise function but it seems too random
      random.seed(x)
      number = random.random()
      if number &lt; 0.5:
          final = 0 - number * 2
      elif number &gt; 0.5:
          final = number * 2
      return final
  
   def Noise(self, x):     # I found this noise function on the internet
      x = (x&lt;&lt;13) ^ x
      return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) &amp; 0x7fffffff) / 1073741824.0)
  </code></pre>
  <p><strong>2D:</strong></p>
  <pre><code>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 &lt; 0.5:
          final = 0 - number * 2
      elif number &gt; 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&lt;&lt;13) ^ n
      return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) &amp; 0x7fffffff) / 1073741824.0)
  </code></pre>
  <p><strong>I left in my code for 1D and 2D Perlin noise because maybe someone is interested in it:</strong>
  (It took me a long time to find some code, so I think someone would be glad to find an example here).<br />
  You don't need Matplotlib or NumPy to make the noise; I'm only using them to make the graph and see the result better.</p>
  <pre><code>import random
  import matplotlib.pyplot as plt              # To make graphs
  from mpl_toolkits.mplot3d import Axes3D      # To make 3D graphs
  import numpy as np                           # To make graphs
  
  class D():     # Base of classes D1 and D2
      def Cubic_Interpolate(self, v0, v1, v2, v3, x):
          P = (v3 - v2) - (v0 - v1)
          Q = (v0 - v1) - P
          R = v2 - v0
          S = v1
          return P * x**3 + Q * x**2 + R * x + S
  
  class D1(D):
      def __init__(self, lenght, octaves):
          self.result = self.Perlin(lenght, octaves)
      
      def Noise(self, x):     # I wrote this noise function but it seems too random
          random.seed(x)
          number = random.random()
          if number &lt; 0.5:
              final = 0 - number * 2
          elif number &gt; 0.5:
              final = number * 2
          return final
  
      def Noise(self, x):     # I found this noise function on the internet
          x = (x&lt;&lt;13) ^ x
          return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) &amp; 0x7fffffff) / 1073741824.0)
          
      def Perlin(self, lenght, octaves):
          result = []
          for x in range(lenght):
              value = 0
              for y in range(octaves):
                  frequency = 2 ** y
                  amplitude = 0.25 ** y            
                  value += self.Interpolate_Noise(x * frequency) * amplitude
              result.append(value)
              print(f&quot;{x} / {lenght} ({x/lenght*100:.2f}%): {round(x/lenght*10) * '#'} {(10-round(x/lenght*10)) * ' '}. Remaining {lenght-x}.&quot;)     # I don't use `os.system('cls')` because it slow down the code.
          return result
  
      def Smooth_Noise(self, x):
          return self.Noise(x) / 2 + self.Noise(x-1) / 4 + self.Noise(x+1) / 4
  
      def Interpolate_Noise(self, x):
          round_x = round(x)
          frac_x  = x - round_x
          v0 = self.Smooth_Noise(round_x - 1)
          v1 = self.Smooth_Noise(round_x)
          v2 = self.Smooth_Noise(round_x + 1)
          v3 = self.Smooth_Noise(round_x + 2)
          return self.Cubic_Interpolate(v0, v1, v2, v3, frac_x)
              
      def graph(self, *args):
          plt.plot(np.array(self.result), '-', label = &quot;Line&quot;)
          for x in args:
              plt.axhline(y=x, color='r', linestyle='-')    
          plt.xlabel('X')
          plt.ylabel('Y')
          plt.title(&quot;Simple Plot&quot;)
          plt.legend()
          plt.show()
  
  class D2(D):
      def __init__(self, lenght, octaves = 1):
          
          self.lenght_axes = round(lenght ** 0.5)
          self.lenght = self.lenght_axes ** 2
          
          self.result = self.Perlin(self.lenght, octaves)
  
      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 &lt; 0.5:
              final = 0 - number * 2
          elif number &gt; 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&lt;&lt;13) ^ n
          return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) &amp; 0x7fffffff) / 1073741824.0)
      
      def Smooth_Noise(self, x, y):
          corners = (self.Noise(x - 1, y - 1) + self.Noise(x + 1, y - 1) + self.Noise(x - 1, y + 1) + self.Noise(x + 1, y + 1) ) / 16
          sides   = (self.Noise(x - 1, y) + self.Noise(x + 1, y) + self.Noise(x, y - 1)  + self.Noise(x, y + 1) ) /  8
          center  =  self.Noise(x, y) / 4
          return corners + sides + center
      
      def Interpolate_Noise(self, x, y):
  
          round_x = round(x)
          frac_x  = x - round_x
  
          round_y = round(y)
          frac_y  = y - round_y
  
          v11 = self.Smooth_Noise(round_x - 1, round_y - 1)
          v12 = self.Smooth_Noise(round_x    , round_y - 1)
          v13 = self.Smooth_Noise(round_x + 1, round_y - 1)
          v14 = self.Smooth_Noise(round_x + 2, round_y - 1)
          i1 = self.Cubic_Interpolate(v11, v12, v13, v14, frac_x)
  
          v21 = self.Smooth_Noise(round_x - 1, round_y)
          v22 = self.Smooth_Noise(round_x    , round_y)
          v23 = self.Smooth_Noise(round_x + 1, round_y)
          v24 = self.Smooth_Noise(round_x + 2, round_y)
          i2 = self.Cubic_Interpolate(v21, v22, v23, v24, frac_x)
          
          v31 = self.Smooth_Noise(round_x - 1, round_y + 1)
          v32 = self.Smooth_Noise(round_x    , round_y + 1)
          v33 = self.Smooth_Noise(round_x + 1, round_y + 1)
          v34 = self.Smooth_Noise(round_x + 2, round_y + 1)
          i3 = self.Cubic_Interpolate(v31, v32, v33, v34, frac_x)
  
          v41 = self.Smooth_Noise(round_x - 1, round_y + 2)
          v42 = self.Smooth_Noise(round_x    , round_y + 2)
          v43 = self.Smooth_Noise(round_x + 1, round_y + 2)
          v44 = self.Smooth_Noise(round_x + 2, round_y + 2)
          i4 = self.Cubic_Interpolate(v41, v42, v43, v44, frac_x)
          
          return self.Cubic_Interpolate(i1, i2, i3, i4, frac_y)
      
      def Perlin(self, lenght, octaves):
          result = []
          for x in range(lenght):
              value = 0
              for y in range(octaves):
                  frequency = 2 ** y
                  amplitude = 0.25 ** y            
                  value += self.Interpolate_Noise(x * frequency, x * frequency) * amplitude
              result.append(value)
              print(f&quot;{x} / {lenght} ({x/lenght*100:.2f}%): {round(x/lenght*10) * '#'} {(10-round(x/lenght*10)) * ' '}. Remaining {lenght-x}.&quot;)     # I don't use `os.system('cls')` because it slow down the code.
          return result
  
      def graph(self, color = 'viridis'):
          # Other colors: https://matplotlib.org/examples/color/colormaps_reference.html
          fig = plt.figure()
          Z = np.array(self.result).reshape(self.lenght_axes, self.lenght_axes)
  
          ax = fig.add_subplot(1, 2, 1, projection='3d')
          X = np.arange(self.lenght_axes)
          Y = np.arange(self.lenght_axes)
          X, Y = np.meshgrid(X, Y)        
          d3 = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=color, linewidth=0, antialiased=False)
          fig.colorbar(d3)
  
          ax = fig.add_subplot(1, 2, 2)
          d2 = ax.imshow(Z, cmap=color, interpolation='none')
          fig.colorbar(d2)
                 
          plt.show()
  </code></pre>
  <p>The problem is that the output doesn't seem suitable for a map.</p>
  <p>Look at this output using:</p>
  <pre><code>test = D2(1000, 3)
  test.graph()
  </code></pre>
  <p><a href="https://i.stack.imgur.com/o7FiM.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/o7FiM.png" alt="enter image description here" /></a></p>
  <p>I am looking for something smoother.</p>
  <p>Maybe it's difficult to notice in the 2D noise what I'm talking about but in 1D it's much easier:</p>
  <pre><code>test = D1(1000, 3)
  test.graph()
  </code></pre>
  <p><a href="https://i.stack.imgur.com/WYenJ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/WYenJ.png" alt="enter image description here" /></a></p>
  <p>The noise function from the internet has slightly smaller and less frequent peaks, but it still has too many. I am looking for something smoother.</p>
  <p>Something like this maybe:<br />
  <a href="https://i.stack.imgur.com/sP3h2.gif" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/sP3h2.gif" alt="enter image description here" /></a></p>
  <p>Or this:<br />
  <a href="https://i.stack.imgur.com/MzLPH.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/MzLPH.png" alt="enter image description here" /></a></p>
  <p><strong>P.S:</strong> I made this based on <a href="https://web.archive.org/web/20160530124230/http://freespace.virgin.net:80/hugo.elias/models/m_perlin.htm" rel="nofollow noreferrer">this pseudocode</a>.</p>
  <h2><strong>EDIT:</strong></h2>
  <h3><strong>Pikalek:</strong></h3>
  <p><a href="https://i.stack.imgur.com/81YUk.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/81YUk.png" alt="enter image description here" /></a></p>
  <p>Even with low values it has peaks and no curves or smooth/flat lines.</p>
  <h3><strong>geza: SOLUTION</strong></h3>
  <p>Thanks to <a href="https://stackoverflow.com/a/47839493/7655838">geza's suggestions</a> I found the solution to my problem:</p>
  <pre><code>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&quot;{y} / {lenght_axes} ({y/lenght_axes*100:.2f}%): {round(y/lenght_axes*20) * '#'} {(20-round(y/lenght_axes*20)) * ' '}. Remaining {lenght_axes-y}.&quot;)
      return result
  </code></pre>
  <p>Other modifications were:</p>
  <ul>
  <li><code>Z = np.array(self.result)</code> instead of this <code>Z = np.array(self.result).reshape(self.lenght_axes, self.lenght_axes)</code>in the graph function.</li>
  <li>Use of <code>math.floor()</code> (remember <code>import math</code>) instead of <code>round()</code> in <code>Interpolate_Noise</code> function in <code>round_x</code> and <code>round_y</code> variables.</li>
  <li>Modification of the <code>return</code> line in <code>Noise</code> (the second one) to <code>return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) &amp; 0x7fffffff) / 1073741824.0)</code> .
  <code>D2(10000, 10)</code>
  <a href="https://i.stack.imgur.com/rdj5N.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/rdj5N.png" alt="enter image description here" /></a>
  The only thing strange right now is that the mountains (yellow) are always near the same place, but I think that is a matter of changing the numbers in the <code>Noise</code> function.</li>
  </ul>