在Pillow中为浮动图像叠加线条绘制

2 投票
2 回答
1329 浏览
提问于 2025-04-18 12:05

我正在使用浮动图像来绘制一些线条。

from PIL import Image, ImageDraw

im = Image.new("F", (64, 64), 0)
draw = ImageDraw.Draw(im)
draw.line((0, 0, 64, 64), 128, 5)
draw.line((0, 64, 64, 0), 128, 5)
im.show()

错误的结果

但是,线条并没有一个叠加在另一个上面。我希望得到的结果是,两个线条的值能够相加。

期望的结果

我尝试用两个浮动图像进行加法运算。

from PIL import Image, ImageDraw, ImageChops
im1 = Image.new("F", (64, 64), 0)
draw = ImageDraw.Draw(im1)
draw.line((0, 0, 64, 64), 128, 5)

im2 = Image.new("F", (64, 64), 0)
draw = ImageDraw.Draw(im2)
draw.line((0, 64, 64, 0), 128, 5)

im = ImageChops.add_modulo(im1, im2)

但是Pillow报错了,提示 ValueError: image has wrong mode(而且这样处理很多线条会很低效)。

有没有其他方法可以做到这一点,而不是逐个像素地遍历两个图像进行相加呢?

编辑:看起来 scikit-image 也有同样的问题,所以我也愿意接受任何涉及它的解决方案。

2 个回答

0

使用cairo图形库和它的Python接口,而不是Pillow。这个库让你可以设置一种叫做合成操作符的东西。

如果你想要一个位图图像,可以创建一个ImageSurface。然后你可以使用write_to_png方法把它保存为PNG文件。

2

你可以使用绘图模块来生成坐标和数值,然后把它们添加到图像中(图像其实就是一个普通的numpy数组):

from skimage.draw import line_aa
import matplotlib.pyplot as plt
import numpy as np

image = np.zeros((64, 64), dtype=float)

for (rr, cc, val) in [line_aa(0, 0, 63, 63),
                      line_aa(63, 0, 0, 63)]:
    image[rr, cc] += val

image /= image.max()

plt.imsave("/tmp/out.png", image, vmin=0, vmax=1, cmap='gray')

如果你需要画更粗的线条,我们有这样的功能,不过现在它稍微隐藏在measure这个子模块里。如果你觉得有用,我很乐意在绘图模块中把它展示出来。

撰写回答