визуализировать диаграмму Вороного в массив NumPy - PullRequest
0 голосов
/ 10 декабря 2018

Я хотел бы создать районы Вороного на основе списка центров и размера изображения.

Я попробовал следующий код на основе https://rosettacode.org/wiki/Voronoi_diagram

def generate_voronoi_diagram(width, height, centers_x, centers_y):
    image = Image.new("RGB", (width, height))
    putpixel = image.putpixel
    imgx, imgy = image.size
    num_cells=len(centers_x)
    nx = centers_x
    ny = centers_y
    nr,ng,nb=[],[],[]
    for i in range (num_cells):
        nr.append(randint(0, 255));ng.append(randint(0, 255));nb.append(randint(0, 255));

    for y in range(imgy):
        for x in range(imgx):
            dmin = math.hypot(imgx-1, imgy-1)
            j = -1
            for i in range(num_cells):
                d = math.hypot(nx[i]-x, ny[i]-y)
                if d < dmin:
                    dmin = d
                    j = i
            putpixel((x, y), (nr[j], ng[j], nb[j]))
    image.save("VoronoiDiagram.png", "PNG")
    image.show()

У меня есть желаемый вывод:

enter image description here

Но для генерации вывода требуется слишком много.

Я также пытался https://stackoverflow.com/a/20678647 Это быстро, но я не нашел способа перевести его в массив значений img_width X img_height.Главным образом, потому что я не знаю, как передать параметр размера изображения scipy класс Вороного .

Есть ли более быстрый способ получить этот вывод?Центры или ребра многоугольника не нужны

Заранее спасибо

Отредактировано 2018-12-11: использование @ tel «Быстрое решение»

enter image description here

Выполнение кода происходит быстрее, кажется, что центры были преобразованы.Вероятно, этот метод добавляет маржу к изображению

1 Ответ

0 голосов
/ 10 декабря 2018

Быстрое решение

Вот как можно преобразовать вывод быстрого решения на основе scipy.spatial.Voronoi, с которым вы связались, в массив Numpy произвольной ширины и высоты.Учитывая набор regions, vertices, который вы получаете в качестве вывода из функции voronoi_finite_polygons_2d в связанном коде, вот вспомогательная функция, которая преобразует этот вывод в массив:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas

def vorarr(regions, vertices, width, height, dpi=100):
    fig = plt.Figure(figsize=(width/dpi, height/dpi), dpi=dpi)
    canvas = FigureCanvas(fig)
    ax = fig.add_axes([0,0,1,1])

    # colorize
    for region in regions:
        polygon = vertices[region]
        ax.fill(*zip(*polygon), alpha=0.4)

    ax.plot(points[:,0], points[:,1], 'ko')
    ax.set_xlim(vor.min_bound[0] - 0.1, vor.max_bound[0] + 0.1)
    ax.set_ylim(vor.min_bound[1] - 0.1, vor.max_bound[1] + 0.1)

    canvas.draw()
    return np.frombuffer(canvas.tostring_rgb(), dtype='uint8').reshape(height, width, 3)

Тестирование его

Вот полный пример vorarr в действии:

from scipy.spatial import Voronoi

# get random points
np.random.seed(1234)
points = np.random.rand(15, 2)

# compute Voronoi tesselation
vor = Voronoi(points)

# voronoi_finite_polygons_2d function from https://stackoverflow.com/a/20678647/425458
regions, vertices = voronoi_finite_polygons_2d(vor)

# convert plotting data to numpy array
arr = vorarr(regions, vertices, width=1000, height=1000)

# plot the numpy array
plt.imshow(arr)

Вывод:

enter image description here

Как вы можетевидите, результирующий массив Numpy действительно имеет форму (1000, 1000), как указано в вызове vorarr.

Если вы хотите исправить свой существующий код

Вот как выможет изменить ваш текущий код для работы с / вернуть массив Numpy:

import math
import matplotlib.pyplot as plt
import numpy as np

def generate_voronoi_diagram(width, height, centers_x, centers_y):
    arr = np.zeros((width, height, 3))
    imgx,imgy = width, height
    num_cells=len(centers_x)

    nx = centers_x
    ny = centers_y
    nr = list(range(num_cells))
    ng = nr
    nb = nr

    for y in range(imgy):
        for x in range(imgx):
            dmin = math.hypot(imgx-1, imgy-1)
            j = -1
            for i in range(num_cells):
                d = math.hypot(nx[i]-x, ny[i]-y)
                if d < dmin:
                    dmin = d
                    j = i
            arr[x, y, :] = (nr[j], ng[j], nb[j])

    plt.imshow(arr.astype(int))
    plt.show()
    return arr
...