Я сейчас пытаюсь использовать шум для генерации случайных фантазийных карт в Python. Я нашел учебник онлайн, который действительно помог мне. К сожалению, это на C ++, поэтому мне пришлось поиграть с моим кодом, чтобы получить его как можно ближе. Очевидно, невозможно заставить все быть один на один. Например, он использует случайный шум, а я использую perlin. Я все еще хочу попробовать.
Хотя я в целом доволен тем, как это получается, меня беспокоит серьезная проблема.
В программах, как моей, так и учебной, число от 0 до 1 (в моем случае числа становятся меньше от центра оси y, а затем меняются на 0 и 1) определяет цвет каждого элемента градиента. На картинке урока красный является основным цветом в центре, но остальные цвета более или менее равны друг другу. Мой близок к этому, но некоторые цвета определенно больше, с темно-синим (все цифры менее 0,05) просто маленькая полоска. Я попытался изменить размер градиента, но это заставило темно-синий обогнать все остальные цвета. Я в тупике. Является ли проблема в том, что градиент урока изначально переходит от красного в центре к синему, а у моего - от белого к черному? Это размер моего градиента? Должен ли я просто изменить числа, которые я использовал в учебнике?
Тепловая карта градиента учебника
Моя тепловая карта градиента
Мой код
import numpy as np
import math
import noise
from PIL import Image
shape = (500,500)
width = shape[0]
height = shape[1]
scale = 100 # Number that determines at what distance to view the noisemap
octaves = 6 # the number of levels of detail you want you perlin noise to have
persistence = 0.5 # number that determines how much detail is added or removed at each octave (adjusts frequency)
lacunarity = 2.0 # number that determines how much each octave contributes to the overall shape (adjusts amplitude)
def add_color(arr):
color_world = np.zeros(arr.shape+(3,))
for x in range(width):
for y in range(height):
if arr[x][y] < .20:
color_world[x][y] = [70,130,180]
elif arr[x][y] < .40:
color_world[x][y] = [100,149,237]
elif arr[x][y] < .50:
color_world[x][y] = [154,205,50]
elif arr[x][y] < .70:
color_world[x][y] = [0,128,0]
elif arr[x][y] < .80:
color_world[x][y] = [192,192,192]
elif arr[x][y] < 1.0:
color_world[x][y] = [255,255,255]
return color_world
world = np.zeros(shape)
for x in range(width):
for y in range(height):
world[x][y] = noise.pnoise2(x/scale,
y/scale,
octaves = octaves,
persistence = persistence,
lacunarity = lacunarity,
repeatx = 500,
repeaty = 500,
base = 0)
heat_noise = np.zeros(shape)
for x in range(width):
for y in range(height):
heat_noise[x][y] = noise.pnoise2(x/scale,
y/scale,
octaves = 4,
persistence = persistence,
lacunarity = lacunarity,
repeatx = 500,
repeaty = 500,
base = 0)
# get world between 0 and 1
max_grad = np.max(world)
min_grad = np.min(world)
world = (world-min_grad)/(max_grad-min_grad)
# get heat_noise between 0 and 1
max_grad = np.max(heat_noise)
min_grad = np.min(heat_noise)
heat_noise = (heat_noise-min_grad)/(max_grad-min_grad)
# Show noise
##im = Image.fromarray(np.uint8(world*255),"L")
##im.show()
# make world height colorful
color_world = add_color(world)
# Create colored world height map image to view
im = Image.fromarray(color_world.astype("uint8"), "RGB")
im.show()
# create gradient starting from center going up and down
center_y = width/2
heat_grad = np.zeros_like(world)
for y in range(world.shape[0]):
for x in range(world.shape[1]):
disty = abs(y - center_y)
dist =(disty*disty)
heat_grad[y][x] = dist
# get gradient between -1 and 1
max_grad = np.max(heat_grad)
heat_grad = heat_grad / max_grad
heat_grad -= 0.5
heat_grad *= 2.0
heat_grad = -heat_grad
# shrink gradient down
##for x in range(width):
## for y in range(height):
## if heat_grad[x][y] > 0:
## heat_grad[x][y] *= 20
# Multiply world height by gradient
for x in range(width):
for y in range(height):
heat_grad[x][y] = (heat_grad[x][y] * heat_noise[x][y])
# get gradient between 0 and 1
max_grad = np.max(heat_grad)
min_grad = np.min(heat_grad)
heat_grad = (heat_grad - min_grad)/(max_grad - min_grad)
# show gradient in image
im = Image.fromarray(np.uint8(heat_grad*255),"L")
im.show()
# add color to heat_grad
for x in range(width):
for y in range(height):
if heat_grad[x][y] < 0.05:
color_world[x][y] = [0,0,255]
elif heat_grad[x][y] < 0.20:
color_world[x][y] = [100,100,255]
elif heat_grad[x][y] < 0.40:
color_world[x][y] = [0,255,0]
elif heat_grad[x][y] < 0.60:
color_world[x][y] = [255,246,0]
elif heat_grad[x][y] < 0.80:
color_world[x][y] = [255,140,0]
else:
color_world[x][y] = [255,0,0]
#create heat map based on noise
im = Image.fromarray(color_world.astype("uint8"),"RGB")
im.save("./imagetest.png")
im.show()