首页 > 解决方案 > 如何在python中有效地创建重叠的半透明圆圈的图像

问题描述

我正在私下研究一种应该使用彩色圆圈近似图片的遗传算法,类似于这个用 javascript 编写的示例

该算法包括一个从个体的内部表示创建图片的函数,该函数用于计算其适应度,因此需要经常执行。

在下面找到一个最小的工作代码示例,它创建了一张看起来完全符合我要求的图片,但是时间太长了

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


class Circle:
    def __init__(self):
        self.position = (randint(0, 200), randint(0, 200))
        self.radius = randint(5, 50)
        self.color = self.to_hex(randint(0, 256**4))

    @staticmethod
    def to_hex(number, length=8):
        h = hex(number)[2:]
        while len(h) < length:
            h = "0" + h
        return h


def create_picture(circles, show=False):
    fig, ax = plt.subplots(figsize=(2, 2))
    plt.xlim(0, 200)
    plt.ylim(0, 200)
    plt.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0)
    plt.margins(0, 0)
    for c in circles:
        new = plt.Circle(c.position, c.radius, facecolor="#" + c.color, edgecolor=None)
        ax.add_patch(new)
    ax.axis('off')
    canvas = FigureCanvasAgg(fig)
    canvas.draw()
    width, height = fig.get_size_inches() * fig.get_dpi()
    img = np.frombuffer(canvas.tostring_rgb(), dtype='uint8').reshape(int(height), int(width), 3)
    if show:
        plt.show()
    plt.close(fig)
    return img

create_picture([Circle() for _ in range(100)], True)

我的问题是:如何以更有效的方式在 python(不一定是 matplotlib)中创建这样的图片?

我曾尝试使用 PIL,但我无法让透明度部分在那里工作。我还尝试通过计算每个像素来计算 numpy 中的图片,这甚至比我的 plt 解决方案还要慢。

对于加快我的代码或替代方法的想法,我会非常高兴。

标签: pythonvisualizationgenetic-algorithm

解决方案


试试 OpenCV。不幸的是,它不能直接绘制半透明的圆形,您必须先绘制一个圆形,然后将结果与原始结果合并,这可能会减慢处理速度。但值得一试。

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

def draw_circle(image, center, radius, color, alpha):
    overlay = image.copy()
    cv2.circle(image, center, radius, color, -1)
    cv2.addWeighted(image, alpha, overlay, 1 - alpha, 0, image)

im = np.zeros((200, 200, 3), np.uint8) + 255
draw_circle(im, (80, 80), 40, (255, 0, 0), 0.5)
draw_circle(im, (100, 100), 40, (0, 255, 0), 0.5)
draw_circle(im, (120, 120), 40, (0, 0, 255), 1/3)
plt.figure()
plt.imshow(im)
plt.show()

推荐阅读