¿Cómo hacer un generador de ruido Perlin más suave?

Ender Look:

Estoy tratando de usar un generador de ruido Perlin para hacer los mosaicos de un mapa, pero noto que mi ruido es demasiado puntiagudo, quiero decir, tiene demasiadas elevaciones y no hay lugares planos, y no parecen montañas, islas, lagos o cualquier cosa; parecen demasiado aleatorias y con muchos picos.

Al final de la pregunta hay los cambios necesarios para solucionarlo.

El código importante para la pregunta es:

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)

2D:

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)

Dejé mi código para el ruido Perlin 1D y 2D porque tal vez alguien está interesado en él: (Me tomó mucho tiempo encontrar algún código, así que creo que alguien estaría encantado de encontrar un ejemplo aquí).
No necesita Matplotlib o NumPy para hacer el ruido; Solo los estoy usando para hacer el gráfico y ver mejor el resultado.

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 < 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 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"{x} / {lenght} ({x/lenght*100:.2f}%): {round(x/lenght*10) * '#'} {(10-round(x/lenght*10)) * ' '}. Remaining {lenght-x}.")     # 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 = "Line")
        for x in args:
            plt.axhline(y=x, color='r', linestyle='-')    
        plt.xlabel('X')
        plt.ylabel('Y')
        plt.title("Simple Plot")
        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 < 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)

    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"{x} / {lenght} ({x/lenght*100:.2f}%): {round(x/lenght*10) * '#'} {(10-round(x/lenght*10)) * ' '}. Remaining {lenght-x}.")     # 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()

El problema es que la salida no parece adecuada para un mapa.

Mire esta salida usando:

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

ingrese la descripción de la imagen aquí

Estoy buscando algo más suave.

Tal vez es difícil notar en el ruido 2D de lo que estoy hablando, pero en 1D es mucho más fácil:

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

ingrese la descripción de la imagen aquí

La función de ruido de Internet tiene picos ligeramente más pequeños y menos frecuentes, pero aún tiene demasiados. Estoy buscando algo más suave.

Tal vez algo como esto:
ingrese la descripción de la imagen aquí

O esto:
ingrese la descripción de la imagen aquí

PD: Hice esto basado en este pseudocódigo .

EDITAR:

Pikalek:

ingrese la descripción de la imagen aquí

Even with low values it has peaks and no curves or smooth/flat lines.

geza: SOLUTION

Thanks to geza's suggestions I found the solution to my problem:

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

Other modifications were:

  • Z = np.array(self.result) instead of this Z = np.array(self.result).reshape(self.lenght_axes, self.lenght_axes)in the graph function.
  • Use of math.floor() (remember import math) instead of round() in Interpolate_Noise function in round_x and round_y variables.
  • Modification of the return line in Noise (the second one) to return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0) . D2(10000, 10) ingrese la descripción de la imagen aquí 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 Noise function.
geza :

I've spotted these mistakes in your code:

  • You need to multiply Interpolate_Noise parameter, to "zoom" into the map (for example, multiply x with 0.01). If you do this in the 1D case, you'll see that the generated function is already much better
  • Increase the octave count from 3 to something larger (3 octaves don't generate too much detail)
  • Use amplitude 0.5^octave, not 0.25^octave (but you can play with this parameter, so 0.25 is not inherently bad, but it doesn't give too much detail)
  • For the 2D case, you need to have 2 outer loops (one for horizontal, and one for vertical. And of course, you still need to have the octave loop). So you need to "index" the noise properly with horizontal and vertical position, not just x and x.
  • Remove smoothing altogether. Perlin noise doesn't need it.
  • La función de ruido 2D tiene un error: se usa en xlugar de nen la expresión de retorno
  • en la interpolación cúbica, se usa en roundlugar de math.floor.

Aquí hay una respuesta mía, con una implementación simple (C ++) de ruido similar al de Perlin (no es el adecuado perlin): https://stackoverflow.com/a/45121786/8157187

Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.

En caso de infracción, por favor [email protected] Eliminar

Editado en
0

Déjame decir algunas palabras

0Comentarios
Iniciar sesiónRevisión de participación posterior

Artículos relacionados

¿Cómo hacer un generador invocable?

Cómo hacer un desplazamiento suave de listas en Swing

No puedo averiguar cómo hacer un generador a partir de un generador

Extraño resultado del generador de ruido perlin

¿Cómo hacer un generador de retro-síntesis de química orgánica de pitón?

Matlab ¿cómo hacer un trazado de contorno suave?

Unidad - Octavas de ruido Perlin

Unidad - Octavas de ruido Perlin

¿Cómo hacer un efecto de zoom suave en html?

Cómo hacer un generador de consultas correcto con subconsultas

¿Cómo hacer que el generador de datos sea más eficiente?

¿Cómo hacer que el generador de datos sea más eficiente?

Rejilla de bloque de ruido Perlin

Ruido Perlin mejorado "demasiado suave"

Ruido Perlin mejorado "demasiado suave"

¿Cómo puedo suavizar mi mapa de alturas? (Ruido de Perlin, openGL)

Cómo aumentar la desviación estándar de una distribución de ruido Perlin

¿Cómo hacer un generador de color de fondo de botón aleatorio?

¿Cómo hacer un generador de color de fondo de botón aleatorio?

Cómo hacer y dibujar un ruido Perlin en un JPanel

transición de ruido de lienzo más suave: aparición gradual de partículas

Cómo hacer un generador de marca de tiempo ISO de precisión genérico

¿Cómo hacer una onda más suave aplicando una ventana de hamming?

Hacer un bucle de animación drawSVG más suave

Hacer un bucle de animación drawSVG más suave

¿Cómo hacer que el segmento de flecha sea más suave en ggplot?

¿Cómo puede el generador obtener el ruido de entrada z?

¿Cómo hacer que este movimiento de cámara sea más suave?

¿Cómo hacer un desplazamiento suave?

TOP Lista

  1. 1

    ¿Cómo ocultar la aplicación web de los robots de búsqueda? (ASP.NET)

  2. 2

    Kibana 4 , making pie chart , error message

  3. 3

    Manera correcta de agregar referencias al proyecto C # de modo que sean compatibles con el control de versiones

  4. 4

    récupérer les noms de clés depuis Firebase react-native

  5. 5

    OAuth 2.0 utilizando Spring Security + WSO2 Identity Server

  6. 6

    Cómo eliminar o caducar las cookies en Chrome usando asp.net

  7. 7

    desbordamiento: oculto no funciona al hacer zoom en un iframe de YouTube usando transformar

  8. 8

    Cómo extraer una palabra clave (cadena) de una columna en pandas dataframe en python

  9. 9

    Link library in Visual Studio, why two different ways?

  10. 10

    선언되지 않은 유형 'MessagingDelegate'사용

  11. 11

    actualizar el contenido de la vista de reciclaje falla en la hoja inferior

  12. 12

    Ver todos los comentarios en un video de YouTube

  13. 13

    Problema con la vista de impresión de PDF

  14. 14

    ¿Cómo pintar el Dropline de un RowHeader-JTable en el Main-JTable durante un DragAndDrop?

  15. 15

    Pregunta de fórmula de desplazamiento y transposición de Excel / Google Sheets

  16. 16

    ¿Cómo puedo hacer accesible la información de color en tablas HTML?

  17. 17

    ¿Cómo generalizar el JSON en el procedimiento almacenado?

  18. 18

    Recortar fotos rectangulares de escaneos en OpenCV con Python

  19. 19

    2D 배열에 대한 Numpy 요소 별 평균 계산

  20. 20

    Typescript의 "window"전역 개체에 "adsbygoogle"애드 센스 속성을 추가하는 방법은 무엇입니까?

  21. 21

    Error: la ejecución falló para la tarea ': app: compileDebugJavaWithJavac'. java.io.FileNotFoundException:

CalienteEtiquetas

Archivo