【问题标题】:Distorting Voronoi With Perlin Noise用柏林噪声扭曲 Voronoi
【发布时间】:2020-10-23 16:21:44
【问题描述】:

根据this blog post,有几种方法可以使 voronoi 细胞看起来更有活力。我感兴趣的是他们提到的第一个:

上图和上图是同一个Voronoi图,只是现在使用Perlin噪声来扭曲哪些点属于哪个单元格。这在单元格之间创建了一些更有趣的边界。 只要您对最近的 voronoi 原点使用逐个像素(或逐个图块)分配,这很容易实现,因为您可以通过 Perlin 噪声非常简单地偏移像素的实际坐标 - 相当与扭曲的 Perlin 噪声密切相关。

我在其他地方看到过类似的想法,但没有显示 perlin 噪声如何“扭曲”或“添加”到 voronoi 图的实际代码。我试过通过猜测来应用它,但没有运气。我的代码写的方式,点之间的距离是几百,而perlin噪声值只是从0到1,所以添加或减去噪声确实没有多大作用。乘法似乎打破了voronoi。我尝试将 voronoi 距离值缩放到 0 到 1 或 -1 到 1 之间,然后将其应用于噪声,但这也不起作用。

下面是我生成的 voronoi 图和 perlin 噪声的示例。如果有任何反馈或能力为我指明正确的方向,我将不胜感激。

from PIL import Image
import random
import math
import numpy as np
import noise
wid = 500
hei = 250
image = Image.new("RGB",(wid,hei))
world_test = np.zeros(image.size)
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)
# Creates perlin noise
for x in range(wid):
    for y in range(hei):
        world_test[x][y] = ((noise.pnoise2(x/100, 
                                    y/100, 
                                    octaves     = octaves, 
                                    persistence = persistence, 
                                    lacunarity  = lacunarity, 
                                    repeatx     = wid, 
                                    repeaty     = hei, 
                                    base        = 0)))
def generate_voronoi_diagram(width, height, num_cells):
    image = Image.new("RGB", (width, height))
    putpixel = image.putpixel
    imgx, imgy = image.size
    nx = []
    ny = []
    nr = []
    ng = []
    nb = []
    #Go through number of cells
    for i in range(num_cells):
        #creat a point (x,y) and give it a specific color value
        nx.append(random.randrange(imgx))
        ny.append(random.randrange(imgy))
        nr.append(random.randrange(256))
        ng.append(random.randrange(256))
        nb.append(random.randrange(256))
    #go through each pixel in the image
    for y in range(int(imgy)):
        for x in range(int(imgx)):
            dmin = math.hypot(imgx-1, imgy-1)
            j = -1
            #go through each cell
            for i in range(num_cells):
                # d is distance from each voronoi starting point
                d = math.hypot((nx[i]-x), (ny[i]-y))
                # apply perlin distort to d
                d +=  world_test[x][y]
                #if distance is less than the current min distance,
                #set that point as the owner of this pixel and the new dmin
                if d < dmin:
                    dmin = d
                    j = i
            putpixel((x, y), (nr[j], ng[j], nb[j]))
    image.save("Voronoi_example.png", "PNG")
    image.show()
generate_voronoi_diagram(wid, hei, 30)

【问题讨论】:

    标签: python voronoi perlin-noise


    【解决方案1】:

    我想我找到了解决这个问题的方法。 如果您为每个坐标(x 和 y)创建单独的噪声贴图,并在计算 d 期间将该噪声贴图的值添加到每个像素,则该值将被贴图扭曲。 我想我在这个网站上找到了这个答案,但我不确定: https://gamedev.stackexchange.com/questions/182582/how-to-distort-an-image-using-perlin-noise

    基于这个网站,我修改了你的 python 代码,它现在应该可以工作了。

    from PIL import Image
    import random
    import math
    import numpy as np
    import noise
    wid = 100
    hei = 100
    image = Image.new("RGB",(wid,hei))
    world_test_x = np.zeros(image.size)
    world_test_y = np.zeros(image.size)
    scale       = 0.1 # 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)
    seed = 19829813472
    mult = 50 # Strenght
    # Creates perlin noise to distort x coordinates
    for x in range(wid):
        for y in range(hei):
            world_test_x[x][y] = ((noise.pnoise2(x/100, 
                                        y/100, 
                                        octaves     = octaves, 
                                        persistence = persistence, 
                                        lacunarity  = lacunarity, 
                                        repeatx     = wid, 
                                        repeaty     = hei, 
                                        base        = 0)))*mult
    # Creates perlin noise to distort y coordinates
    for x in range(wid):
        for y in range(hei):
            world_test_y[x][y] = ((noise.pnoise2((x+seed)/100, 
                                        (y+seed)/100, 
                                        octaves     = octaves, 
                                        persistence = persistence, 
                                        lacunarity  = lacunarity, 
                                        repeatx     = wid, 
                                        repeaty     = hei, 
                                        base        = 0)))*mult
    
    def generate_voronoi_diagram(width, height, num_cells):
        image = Image.new("RGB", (width, height))
        putpixel = image.putpixel
        imgx, imgy = image.size
        nx = []
        ny = []
        nr = []
        ng = []
        nb = []
        nsize=[]
        #Go through number of cells
        for i in range(num_cells):
            #creat a point (x,y) and give it a specific color value
            nx.append(random.randrange(imgx))
            ny.append(random.randrange(imgy))
            nr.append(random.randrange(256))
            ng.append(random.randrange(256))
            nb.append(random.randrange(256))
            nsize.append(0)
        #go through each pixel in the image
        for y in range(int(imgy)):
            for x in range(int(imgx)):
                dmin = math.hypot(imgx-1, imgy-1)
                j = -1
                #go through each cell
                for i in range(num_cells):
                    # d is distance from each voronoi starting point
                    # each point gets its coordinates distorted so d also gets distorted
                    d = math.hypot((nx[i]-x+world_test_x[x][y]), (ny[i]-y+world_test_y[x][y]))
                    #if distance is less than the current min distance,
                    #set that point as the owner of this pixel and the new dmin
                    if d < dmin:
                        dmin = d
                        j = i
                    nsize[j]+=1
                putpixel((x, y), (nr[j], ng[j], nb[j]))
        image.save("Voronoi_example.png", "PNG")
        image.show()
        print(nsize)
        print(nr)
    generate_voronoi_diagram(wid, hei, 8)
    

    Here is the Voronoi map

    Here is the distorted Voronoi map

    【讨论】:

    • 发布这个问题一年后,我忘了我问过这个问题。几个月前我在其他地方得到了解决问题的帮助,从那时起的结果与您的建议相似。感谢您花时间回答一个老问题。
    猜你喜欢
    • 2021-04-29
    • 2012-01-29
    • 2017-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多