Estoy tratando de producir ruido perlin 2D usando numpy, pero en lugar de algo suave, obtengo esto:
mi ruido perlin roto, con cuadritos feos por doquier
Seguro, estoy mezclando mis dimensiones en alguna parte, probablemente cuando combino los cuatro gradientes... Pero no puedo encontrarlo y mi cerebro se está derritiendo en este momento. ¿Alguien puede ayudarme a identificar el problema?
De todos modos, aquí está el código:
%matplotlib inline import numpy as np import matplotlib.pyplot as plt def perlin(x,y,seed=0): # permutation table np.random.seed(seed) p = np.arange(256,dtype=int) np.random.shuffle(p) p = np.stack([p,p]).flatten() # coordinates of the first corner xi = x.astype(int) yi = y.astype(int) # internal coordinates xf = x - xi yf = y - yi # fade factors u = fade(xf) v = fade(yf) # noise components n00 = gradient(p[p[xi]+yi],xf,yf) n01 = gradient(p[p[xi]+yi+1],xf,yf-1) n11 = gradient(p[p[xi+1]+yi+1],xf-1,yf-1) n10 = gradient(p[p[xi+1]+yi],xf-1,yf) # combine noises x1 = lerp(n00,n10,u) x2 = lerp(n10,n11,u) return lerp(x2,x1,v) def lerp(a,b,x): "linear interpolation" return a + x * (ba) def fade(t): "6t^5 - 15t^4 + 10t^3" return 6 * t**5 - 15 * t**4 + 10 * t**3 def gradient(h,x,y): "grad converts h to the right gradient vector and return the dot product with (x,y)" vectors = np.array([[0,1],[0,-1],[1,0],[-1,0]]) g = vectors[h%4] return g[:,:,0] * x + g[:,:,1] * y lin = np.linspace(0,5,100,endpoint=False) y,x = np.meshgrid(lin,lin) plt.imshow(perlin(x,y,seed=0))
Gracias a Paul Panzer y una buena noche de sueño, ahora funciona ...
import numpy as np import matplotlib.pyplot as plt def perlin(x, y, seed=0): # permutation table np.random.seed(seed) p = np.arange(256, dtype=int) np.random.shuffle(p) p = np.stack([p, p]).flatten() # coordinates of the top-left xi, yi = x.astype(int), y.astype(int) # internal coordinates xf, yf = x - xi, y - yi # fade factors u, v = fade(xf), fade(yf) # noise components n00 = gradient(p[p[xi] + yi], xf, yf) n01 = gradient(p[p[xi] + yi + 1], xf, yf - 1) n11 = gradient(p[p[xi + 1] + yi + 1], xf - 1, yf - 1) n10 = gradient(p[p[xi + 1] + yi], xf - 1, yf) # combine noises x1 = lerp(n00, n10, u) x2 = lerp(n01, n11, u) # FIX1: I was using n10 instead of n01 return lerp(x1, x2, v) # FIX2: I also had to reverse x1 and x2 here def lerp(a, b, x): "linear interpolation" return a + x * (b - a) def fade(t): "6t^5 - 15t^4 + 10t^3" return 6 * t**5 - 15 * t**4 + 10 * t**3 def gradient(h, x, y): "grad converts h to the right gradient vector and return the dot product with (x,y)" vectors = np.array([[0, 1], [0, -1], [1, 0], [-1, 0]]) g = vectors[h % 4] return g[:, :, 0] * x + g[:, :, 1] * y lin = np.linspace(0, 5, 100, endpoint=False) x, y = np.meshgrid(lin, lin) # FIX3: I thought I had to invert x and y here but it was a mistake plt.imshow(perlin(x, y, seed=2), origin='upper')