使用scipy.spatial.Voronoi绘制任意形状的面积Voronoi图

y4ekin9u  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(150)

我们需要计算面积Voronoi图,而不是计算点Voronoi图。点Voronoi图不是一个可行的选择,因为涉及的图形形状相当复杂。
面积Voronoi图是一个合适的选项,并且可以通过点Voronoi图算法的适应版本来近似。
近似包括三个步骤。它不是从对象的中心坐标计算Voronoi图,而是使用每个对象轮廓上的点。除了期望的效果之外,这还将导致源自位于对象的相同轮廓上的点的对象的不必要的分割,其必须被校正。
1.计算图形轮廓上的点集
1.计算这些点的点Voronoi图
1.删除从同一图形上的点生成的Voronoi边
而1.和2.我们想知道如何才能确定哪些边是由同一图形上的点生成的,而不需要编写我们自己的Voronoi图实现?

import numpy as np
import matplotlib.pyplot as plt

from scipy.spatial import Voronoi, voronoi_plot_2d
from skimage.filters import threshold_otsu
from skimage.measure import find_contours

def create_sample_img():
    object_selectors = []
    object_selectors.append((slice(50, 70), slice(100, 120)))
    object_selectors.append((slice(30, 80), slice(20, 60)))
    object_selectors.append((slice(10, 35), slice(80, 105)))
    object_selectors.append((slice(10, 90), slice(140, 190)))

    image = np.zeros((100,200))
    for selector in object_selectors:
        image[selector] = 1

    return image

def imshow_contours(image, contours, ax):
    ax.imshow(image, alpha=0.75)
    for contour in contours:
        ax.plot(contour[:, 1], contour[:, 0], linewidth=2)
    return ax

def area_voronoi(binary_image, ):
    downsampling = 3
    contour_index_mask = [] # to be used to see from which contour a point originates form
    contour_coordinates = []

    contours_grouped = find_contours(binary_image, 0)

    for contour_index, contours in enumerate(contours_grouped):
        contour_coordinates.extend(contours[::downsampling])
        contour_index_mask.extend([contour_index, ]*len(contours[::downsampling]))

    contour_coordinates = [[coord[1], coord[0]] for coord in contour_coordinates]

    vor = Voronoi(contour_coordinates)

    # TODO remove edges that originate from the same contours

    fig, ax = plt.subplots()
    imshow_contours(image, contours_grouped, ax)
    voronoi_plot_2d(vor, ax=ax)
    plt.show()

image = create_sample_img()
binary_image = image > threshold_otsu(image)
area_voronoi(binary_image)

字符串

qjp7pelc

qjp7pelc1#

请注意,在计算点的Voronoi图时,您应该了解每条边分隔哪两个点的信息。
接下来,您应该计算从中提取点的原始图像的标记(连通分量分析)。现在,对于每条边,您可以查找它将哪两个点分开,并且在标记的图像中,您可以看到这些点中的每一个属于哪个连通分量。如果连接的组件相等,则删除边。
从连接的零部件图像中,还可以立即导出每个连接零部件的面积。这为下一步提供了足够的信息,下一步将对两点之间的距离和两个连接组件的面积比应用特定阈值,以决定是保留还是删除边。
scipy.spatial.Voronoi对象有一个属性vor.ridge_points(一个NumPy数组),它告诉你哪两个点被边分开。因此,您可以在输入图像中查找这两个点的坐标,从而查找每个点所属的连通分量。
还有一个属性vor.ridge_vertices(一个列表),稍后您需要知道如何绘制边缘。这个列表和上面的数组需要保持同步,当你删除一条边时,你必须删除ridge_points数组中的行,以及ridge_vertices列表中的相应元素。虽然删除代价很高,但也许可以保留一个逻辑数组,指示保留哪些边,丢弃哪些边?

相关问题