如何在 python 中有效地创建重叠的半透明圆圈图像
How to efficiently create images of overlapping, semi-transparent circles in python
我正在私下研究一种遗传算法,该算法应该使用彩色圆圈来近似图片,类似于 this example written in javascript。
该算法包含一个函数,可以根据个体的内部表示创建图片,用于计算其fitness,因此需要经常执行。
在下面找到一个最小的工作代码示例,它创建的图片完全符合我的要求,但是时间太长了:
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 解决方案还要慢。
如果有想法可以加快我的代码或替代方法,我会非常高兴。
试试 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()
我正在私下研究一种遗传算法,该算法应该使用彩色圆圈来近似图片,类似于 this example written in javascript。
该算法包含一个函数,可以根据个体的内部表示创建图片,用于计算其fitness,因此需要经常执行。
在下面找到一个最小的工作代码示例,它创建的图片完全符合我的要求,但是时间太长了:
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 解决方案还要慢。
如果有想法可以加快我的代码或替代方法,我会非常高兴。
试试 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()