创建具有圆形区域边缘的 Voronoi 艺术

2023-11-25

I'm trying to create some artistic "plots" like the ones below:Red Voronoi art enter image description here

区域的颜色并不重要,我想要实现的是沿着 Voronoi 区域的边缘的可变“厚度”(特别是,它们看起来像一个更大的圆形斑点,它们在拐角处相遇,而在拐角处相遇则更薄)他们的中间点)。

我尝试根据到每个质心的最小距离“手动绘制”每个像素(每个像素与一种颜色相关联):

n_centroids = 10
centroids = [(random.randint(0, h), random.randint(0, w)) for _ in range(n_centroids)]
colors = np.array([np.random.choice(range(256), size=3) for _ in range(n_centroids)]) / 255

for x, y in it.product(range(h), range(w)):
    distances = np.sqrt([(x - c[0])**2 + (y - c[1])**2 for c in centroids])
    centroid_i = np.argmin(distances)
    img[x, y] = colors[centroid_i]
    
plt.imshow(img, cmap='gray')

voronoi diagram

Or by scipy.spatial.Voronoi,这也给了我顶点,尽管我仍然不知道如何以所需的可变厚度通过它们画一条线。

from scipy.spatial import Voronoi, voronoi_plot_2d

# make up data points
points = [(random.randint(0, 10), random.randint(0, 10)) for _ in range(10)]

# add 4 distant dummy points
points = np.append(points, [[999,999], [-999,999], [999,-999], [-999,-999]], axis = 0)

# compute Voronoi tesselation
vor = Voronoi(points)

# plot
voronoi_plot_2d(vor)

# colorize
for region in vor.regions:
    if not -1 in region:
        polygon = [vor.vertices[i] for i in region]
        plt.fill(*zip(*polygon))

# fix the range of axes
plt.xlim([-2,12]), plt.ylim([-2,12])
plt.show()

voronoi region plot

Edit:

我成功地通过对每个单独区域的侵蚀+角平滑(通过评论中建议的中值滤波器)获得了一些令人满意的结果,然后将其绘制到黑色背景中。

res = np.zeros((h,w,3))
for color in colors:
    region = (img == color)[:,:,0]
    region = region.astype(np.uint8) * 255
    region = sg.medfilt2d(region, 15) # smooth corners
    # make edges from eroding regions
    region = cv2.erode(region, np.ones((3, 3), np.uint8))
    region = region.astype(bool)
    res[region] = color
    
plt.imshow(res)

voronoi art But as you can see the "stretched" line along the boundaries/edges of the regions is not quite there. Any other suggestions?


This is what @JohanC suggestion looks like. IMO, it looks much better than my attempt with Bezier curves. However, there appears to be a small problem with the RoundedPolygon class, as there are sometimes small defects at the corners (e.g. between blue and purple in the image below).

编辑:我修复了 RoundedPolygon 类。

enter image description here

#!/usr/bin/env python
# coding: utf-8
"""
https://stackoverflow.com/questions/72061965/create-voronoi-art-with-rounded-region-edges
"""

import numpy as np
import matplotlib.pyplot as plt

from matplotlib import patches, path
from scipy.spatial import Voronoi, voronoi_plot_2d


def shrink(polygon, pad):
    center = np.mean(polygon, axis=0)
    resized = np.zeros_like(polygon)
    for ii, point in enumerate(polygon):
        vector = point - center
        unit_vector = vector / np.linalg.norm(vector)
        resized[ii] = point - pad * unit_vector
    return resized


class RoundedPolygon(patches.PathPatch):
    # https://stackoverflow.com/a/66279687/2912349
    def __init__(self, xy, pad, **kwargs):
        p = path.Path(*self.__round(xy=xy, pad=pad))
        super().__init__(path=p, **kwargs)

    def __round(self, xy, pad):
        n = len(xy)

        for i in range(0, n):

            x0, x1, x2 = np.atleast_1d(xy[i - 1], xy[i], xy[(i + 1) % n])

            d01, d12 = x1 - x0, x2 - x1
            l01, l12 = np.linalg.norm(d01), np.linalg.norm(d12)
            u01, u12 = d01 / l01, d12 / l12

            x00 = x0 + min(pad, 0.5 * l01) * u01
            x01 = x1 - min(pad, 0.5 * l01) * u01
            x10 = x1 + min(pad, 0.5 * l12) * u12
            x11 = x2 - min(pad, 0.5 * l12) * u12

            if i == 0:
                verts = [x00, x01, x1, x10]
            else:
                verts += [x01, x1, x10]

        codes = [path.Path.MOVETO] + n*[path.Path.LINETO, path.Path.CURVE3, path.Path.CURVE3]

        verts[0] = verts[-1]

        return np.atleast_1d(verts, codes)


if __name__ == '__main__':

    # make up data points
    n = 100
    max_x = 20
    max_y = 10
    points = np.c_[np.random.uniform(0, max_x, size=n),
                   np.random.uniform(0, max_y, size=n)]

    # add 4 distant dummy points
    points = np.append(points, [[2 * max_x, 2 * max_y],
                                [   -max_x, 2 * max_y],
                                [2 * max_x,    -max_y],
                                [   -max_x,    -max_y]], axis = 0)

    # compute Voronoi tesselation
    vor = Voronoi(points)

    fig, ax = plt.subplots(figsize=(max_x, max_y))
    for region in vor.regions:
        if region and (not -1 in region):
            polygon = np.array([vor.vertices[i] for i in region])
            resized = shrink(polygon, 0.15)
            ax.add_patch(RoundedPolygon(resized, 0.2, color=plt.cm.Reds(0.5 + 0.5*np.random.rand())))

    ax.axis([0, max_x, 0, max_y])
    ax.axis('off')
    ax.set_facecolor('black')
    ax.add_artist(ax.patch)
    ax.patch.set_zorder(-1)
    plt.show()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建具有圆形区域边缘的 Voronoi 艺术 的相关文章

  • 使用 matplotlib 在图像数据之上对线网格进行像素精确定位

    我试图在 python 库 matplotlib 显示的图像网格顶部精确地覆盖 1 像素宽线的网格 不幸的是 我似乎无法对结果进行足够精细的控制 以实现线网格与数据网格的正确对齐 如下面的代码所示 结果似乎总是很接近 但并不完全正确 我尝试
  • 在Python中用空格分割字符串——保留带引号的子字符串

    我有一个像这样的字符串 this is a test 我正在尝试用 Python 编写一些内容 以将其按空格分开 同时忽略引号内的空格 我正在寻找的结果是 this is a test 附言 我知道您会问 如果引号内有引号会发生什么 嗯 在
  • 如果新文件不存在则写入新文件,如果存在则追加到文件

    我有一个程序可以写入用户的highscore到一个文本文件 该文件由用户选择时命名playername 如果具有该特定用户名的文件已经存在 那么程序应该附加到该文件 以便您可以看到多个highscore 如果具有该用户名的文件不存在 例如
  • 在Python中将距离矩阵转换为成对距离列表[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 假设Python中有以下距离矩阵 0 1 2 3 0 0 1 4 8 1 1 0 3 7 2 4 3 0 3 3 8 7 3 0 我想
  • django/whitenoise 存储后端导致错误

    我在调试关闭时在 heroku 上运行 django 应用程序时遇到了 500 错误 使用 rollbar 了解发生错误的原因后 它报告了以下内容 ValueError The file media img 1 jpg could not
  • 在python中浏览ftp目录

    我正在尝试使用 ftplib 使用 Python 3 从 ftp 服务器下载多个文件夹 我有一个文件夹名称列表 它们都位于文件夹 root 中 问题是我不知道如何浏览它们 当我使用cwd我可以进入更深的目录 但是如何再次起来呢 我正在尝试得
  • Python - 在先前已在全局范围内查找的函数内重新分配名称

    为什么我在下面的第三个代码中出现错误 但在前两个代码中却没有出现错误 我使用的是 Python 3 6 0 Anaconda 4 3 1 64 位 Jupyter Code 1 c 100 def fib c 20 a c print a
  • 检查对象是否是字符串列表的列表?

    是什么elegant检查对象是否是字符串列表列表的方法 没有嵌套循环 也许这里必须是构造结构化迭代的常规方法 UPD 像这样的东西 l a b c d 1 3 e 2 f def recurse iterable levels result
  • 如何计算具有较大中间值的总和

    我想计算 for n m两个值都是 1000 以内的整数 最终结果是一个不大于 1000 的数字n但中间值对于 python 来说太大了 无法处理 你怎么解决这个问题 我将函数定义如下 from scipy misc import comb
  • 如何在 PySide/PyQt 中制作一个位于屏幕中央的小部件?

    这段代码有效 但我想知道是否有更简单的方法 def center self qr self frameGeometry cp gui QDesktopWidget availableGeometry center qr moveCenter
  • 在 PyQt 中使用 Windows 7 任务栏功能

    我正在寻找有关将一些新的 Windows 7 任务栏功能集成到我的 PyQt 应用程序中的信息 具体来说 如果已经存在使用新进度指示器的可能性 see here http www petri co il wp content uploads
  • OpenCV:处理每一帧

    我想使用 OpenCV 编写一个跨平台应用程序进行视频捕获 在所有示例中 我发现来自相机的帧是使用抓取功能进行处理并等待一段时间 我想处理序列中的每一帧 我想定义自己的回调函数 每次当一个新帧准备好处理时都会执行该函数 例如直播对于 Win
  • VS Code Pylance 不突出显示变量和模块

    我正在使用带有 Python 和 Pylance 扩展的 VS Code 我遇到的问题是 Pylance 扩展没有对模块和数据框等内容进行语法突出显示 我希望顶部的模块为绿色 df 变量为蓝色 我正在使用默认的深色 颜色主题 这是我的 VS
  • SQL查询中的Python列表作为参数[重复]

    这个问题在这里已经有答案了 我有一个 Python 列表 比如说 l 1 5 8 我想编写一个 SQL 查询来获取列表中所有元素的数据 例如 select name from students where id IN THE LIST l
  • 使用 pyinstaller 制作的可执行文件出现运行时错误

    所以我使用 Pygame 制作了一个游戏 现在我想用它制作一个可执行文件 首选独立可执行文件 所以我用它来制作可执行文件 pyinstaller onefile main py 编译顺利 但运行时出现错误 这是错误 Traceback mo
  • Python 中的“finally”总是执行吗?

    对于Python中任何可能的try finally块 是否保证finally块总是会被执行吗 例如 假设我在except block try 1 0 except ZeroDivisionError return finally print
  • python 中的优化标准化

    在优化过程中 对输入参数进行归一化 使它们处于同一数量级 通常会很有帮助 这样收敛效果会更好 例如 如果我们想要最小化 f x 而合理的近似值是 x0 1e3 1e 4 则将 x0 0 和 x0 1 归一化到大约相同的数量级可能会有所帮助
  • 带有 graphviz_layout 的水平树

    在Python中 使用networkx 我可以用以下方法绘制垂直树 g nx balanced tree 2 4 pos nx graphviz layout g prog dot nx draw g pos labels b all no
  • Mac 上的 PythonXY?

    如何在 Mac OS X Lion 上安装 Python 我开始了 它应该能够通过 macports 但无论如何我找不到 mac ports 网站上所述的端口 pythonXY 我对 MAC 和 pythonXY 都不太了解 但在 pyth
  • Python 线程与 Linux 中的多处理

    基于此question https stackoverflow com questions 807506 threads vs processes in linux我假设创建新流程应该几乎和创造新线程在Linux中 然而 很少的测试显示出截

随机推荐

  • Java8 中的 Files.lines 跳过断行

    我正在使用 Files lines 读取一个非常大 500mb 的文件 它读取文件的一部分 但在某些时候它会因 java io UncheckedIOException java nio charset MalformedInputExce
  • 在 PHP 和 MySQL 中创建不带 HTTPS 的安全登录脚本

    Question Is 维基百科上的这篇文章在 PHP 和 MySQL 中创建安全登录脚本的好参考 在警告部分 作者强调该代码只能与 HTTPS 一起使用 我无法使用 HTTPS 但需要在 PHP 和 MySQL 中实现相对安全的登录脚本
  • C# 事件删除语法

    我对 C 中删除事件处理程序的语法感到困惑 Something new MyHandler HandleSomething add Something new MyHandler HandleSomething remove new 在每一
  • 两个 PCI 设备之间直接通信

    我有一个 NIC 卡和一个 HDD 它们都连接在 Linux 机器的 PCIe 插槽上 理想情况下 我希望将传入数据包传输到 HDD 而不涉及 CPU 或最少涉及 CPU 是否可以像这样沿着 PCI 总线建立直接通信 有谁知道要阅读什么内容
  • 从命令行运行 JUnit 测试套件

    如何从命令行运行 Junit 4 8 1 测试套件 另外我想使用 JUnit 4 8 引入的类别 有没有办法 我可以从命令行指定我想要运行的类别 Using java run JUnit核心类 另见here 类别应该与测试套件一起使用 Ru
  • JavaScript 中的 URL 帮助器

    我正在使用 jQuery Lightbox 作为我的图片库 按钮图像的 URL 是 Content Lightbox lightbox btn next gif 如果我的网址是 localhost Something1 Somtehing2
  • Visual Studio 2012 中缺少 Visual C++ 的先决条件

    我最近安装了vs2012我已经更新了我的 ClickOnce 应用程序 更准确地说 我第一次打开我的C project 这取决于我的主要 c 项目 我还没有更新它 一切都工作正常 VS 2012仍然能够看到 Visual C 2010 先决
  • 如何在java中打印给定整数a = 1234的最后两位数字

    如果我给出像 a 1234 这样的值 我只想打印最后两位数字 34 任何人都可以给我解决这个问题 int a 1234 System out print a number 100结果是最后 2 位数字 See ideone演示
  • 如果不向数据库(例如 SQL Server)提交事务会发生什么?

    假设我有一个查询 begin tran some other sql code 然后我忘记提交或回滚 如果另一个客户端尝试执行查询 会发生什么 只要你不COMMIT or ROLLBACK一个事务 它仍然在 运行 并且可能持有锁 如果您的客
  • FTP 协议中有类似 HTTP Range 标头的内容吗?

    假设我只想通过 FTP 传输文件的一部分 是否可以使用标准 FTP 协议 在 HTTP 中我可以使用范围标头在请求中指定远程资源的数据范围 如果是 1mb 文件 我可以要求 600k 到 700k 之间的字节 FTP中有类似的东西吗 我在读
  • 实体框架 4 - ApplyCurrentValues 与 ObjectStateManager.ChangeObjectState

    我们有一个 WCF 服务 其更新方法可以更新数据库中的客户 此方法从客户端获取一个分离的实体 void UpdtaeCustomer Customer detachedCustomer 我们想出了两种编写此方法的方法 1 context C
  • PDF打印视图问题

    我尝试过两种方式 1 正在创建一个WebView并加载我的pdf文档 我的应用程序几乎完成了打印过程的一部分 但在这方面我面临着打印问题 它没有完整的 A4 表格视图 任何人都可以帮忙吗 我使用了以下代码 public void creat
  • 标准化 Python Pandas 数据框中的一些列?

    下面的Python代码只返回一个数组 但我希望缩放后的数据替换原始数据 from sklearn preprocessing import StandardScaler df StandardScaler fit transform df
  • MVC 将数据从视图发送到控制器

    我对 MVC 3 还很陌生 我知道如何将强类型对象从控制器发送到视图 我现在拥有的是一个视图 其中包含一个由该数据组成的表 表单 用户可以在该视图 html 页面 中更改该数据 当他们单击 保存 时 如何将数据从视图发送回控制器 以便我可以
  • Java 和 C++ 运算符有什么区别吗?

    如果您采用 Java 的原始数字类型加上布尔值 并将其与 C 等效类型进行比较 那么运算符 例如优先级规则或位操作运算符的作用 是否存在任何差异 还是括号的作用 换句话说 如果我采用 Java 表达式并尝试在 C 中编译并运行它 它是否总是
  • 我应该使用 IIFE 还是 window onload 来初始化?

    以下两个代码片段均有效 在js文件中使用IIFE function initialize txtInput document getElementById txtInput txtResult document getElementById
  • 更改 tkinter 消息框按钮上的文字

    我使用 tkinter 的 askokcancel 消息框通过弹出窗口警告用户不可逆转的操作 from tkinter import Tk Tk withdraw from tkinter messagebox import askokca
  • C# Visual Studio GPIB 命令

    在 C Visual Studio 中使用什么命令与 GPIB 仪器进行通信 我需要能够向仪器写入命令并读取输出 I use 安捷伦 IO 库套件 这是在 C 上使用它的教程 C 中的 I O 编程示例 然而 在我的公司中 我们遇到了 VI
  • Popstate - 将弹出状态传递给事件处理程序

    以下代码应导致警报 1 但实际上什么也不执行 window onpopstate function event alert event state a history pushState a 1 history back Fiddle ht
  • 创建具有圆形区域边缘的 Voronoi 艺术

    I m trying to create some artistic plots like the ones below 区域的颜色并不重要 我想要实现的是沿着 Voronoi 区域的边缘的可变 厚度 特别是 它们看起来像一个更大的圆形斑点