You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

增量邻域法迭代生成圆形像素绘制Voronoi图问题求解

增量邻域法生成欧氏距离Voronoi图问题与解决方案

问题描述

我正尝试使用增量邻域法在图像中生成Voronoi图,方案逻辑为:给定n个随机点(每个点对应一个像素),为每个点绘制其邻域,再对这些新邻域点继续向外扩展,直到整图被填满。目前遇到的问题是生成的区域完全错乱。我猜测原因是:如果检查给定点的全部邻域,最终扩展出的形状是正方形而非圆形,因此任意点的距离计算不符合欧氏距离。我不想通过计算每个像素到所有随机点的距离实现需求,该方案运行速度过慢,想知道如何正确筛选生成邻域,保证按欧氏距离正确扩展。

我尝试过仅在奇数次迭代时检查像素的对角线邻域,得到的圆形效果略有提升,但仍不符合要求。

当前运行效果

当前代码运行效果如下:
当前代码运行效果

以下分别是迭代50次和75次的效果示例:
迭代50次效果
迭代75次效果

现有代码

区域生成代码

def createVoronoiIncremental(im, numPoints, param):
    y, x, z = im.shape
    points = []

    count = 0
    while count < numPoints:
        px = np.random.randint(0,x)
        py = np.random.randint(0,y)
        if not inPoints(np.array([px,py]), points):
            points.append(np.array([px,py]))
            count += 1

    points = np.array(points)

    mapPoint = {}
    mapDist = {}

    for i, col in enumerate(im):
            for j, row in enumerate(col):
                mapPoint[(j, i)] = -1 # 空白像素
                mapDist[(j, i)] = y*x # 空白像素


    groups = {}
    groups[-1] = (0,0,0)
    outer = {}
    count = 0
    for point in points:
        i = point[1]
        j = point[0]
        mapPoint[(j, i)] = count # 按组着色的像素
        mapDist[(j, i)] = 0
        outer[(j, i)] = [np.array([j, i])]
        groups[count] = (np.random.randint(0,255),np.random.randint(0,255),np.random.randint(0,255))
        count += 1

    isNeighbour = True
    count = 0
    while isNeighbour:
        isNeighbour = False
        for point in points:
            outerPoints = outer[(point[0], point[1])].copy()
            newOuterPoints = []
            for p in outerPoints:
                n, mapPoint = neightbours(p, mapPoint, mapDist, (x,y), count)
                for neighbour in n:
                    newOuterPoints.append(neighbour)
            outer[(point[0], point[1])] = newOuterPoints
            if len(newOuterPoints) != 0:
                isNeighbour = True
        count += 1
        if count > param:
            break

    return mapPoint

邻域定义代码

def neightbours(points, mapPoint, size, count):
    neightbours = []
    potentialNeighbours = []

    if type(points) != 'numpy.ndarray':
        x = points[0]
        y = points[1]

        # 上侧邻域
        if x-1 >= 0 and y+1 < size[1]:
            potentialNeighbours.append(np.array([x-1,y+1]))
        if y+1 < size[1]:
            potentialNeighbours.append(np.array([x  ,y+1]))
        if x+1 < size[0] and y+1 < size[1]:
            potentialNeighbours.append(np.array([x+1,y+1]))

        # 侧边邻域
        if x-1 >= 0:
            potentialNeighbours.append(np.array([x-1,y]))
        if x+1 < size[0]:
            potentialNeighbours.append(np.array([x+1,y]))

        # 下侧邻域
        if x-1 >= 0 and y-1 >= 0:
            potentialNeighbours.append(np.array([x-1,y-1]))
        if y-1 >= 0:
            potentialNeighbours.append(np.array([x  ,y-1]))
        if x+1 < size[0] and y-1 >= 0:
            potentialNeighbours.append(np.array([x+1,y-1]))

        for potentialNeighbour in potentialNeighbours:
            if mapPoint[(potentialNeighbour[0], potentialNeighbour[1])] == -1: #空白像素
                mapPoint[(potentialNeighbour[0], potentialNeighbour[1])] = mapPoint[(x,y)]
                neightbours.append(potentialNeighbour)
    else:
        for point in points:
            x = point[0]
            y = point[1]

            # 上侧邻域
            if x-1 >= 0 and y+1 < size[1]:
                potentialNeighbours.append(np.array([x-1,y+1]))
            if y+1 < size[1]:
                potentialNeighbours.append(np.array([x  ,y+1]))
            if x+1 < size[0] and y+1 < size[1]:
                potentialNeighbours.append(np.array([x+1,y+1]))

            # 侧边邻域
            if x-1 >= 0:
                potentialNeighbours.append(np.array([x-1,y]))
            if x+1 < size[0]:
                potentialNeighbours.append(np.array([x+1,y]))

            # 下侧邻域
            if x-1 >= 0 and y-1 >= 0:
                potentialNeighbours.append(np.array([x-1,y-1]))
            if y-1 >= 0:
                potentialNeighbours.append(np.array([x  ,y-1]))
            if x+1 < size[0] and y-1 >= 0:
                potentialNeighbours.append(np.array([x+1,y-1]))

            for potentialNeighbour in potentialNeighbours:
                if mapPoint[(potentialNeighbour[0], potentialNeighbour[1])] == -1: #空白像素
                    mapPoint[(potentialNeighbour[0], potentialNeighbour[1])] = mapPoint[(x,y)]
                    neightbours.append(potentialNeighbour)
                    
    return neightbours, mapPoint

解决方案

使用布雷森汉姆圆绘制算法(Bresenham’s circle drawing algorithm),逐次增大圆半径,检查对应点是否已被绘制,即可生成符合欧氏距离要求的Voronoi图,效果如下:
优化后Voronoi图效果


内容的提问来源于stack exchange,提问作者Hugofac

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 03:15:05