我正在使用PIL(Python影像库)。我想画透明的多边形。似乎指定包含alpha级别的填充颜色不起作用。是他们的解决方法吗?
如果使用PIL无法完成,我愿意使用其他方法。
如果有多个解决方案,则应考虑性能。图纸需要尽可能快。
这是针对Pillow,它是PIL维护得更好的分支。 http://pillow.readthedocs.org/
[如果要绘制相对于彼此透明的多边形,则基本Image必须是RGB类型,而不是RGBA类型,而ImageDraw必须是RGBA类型。示例:
from PIL import Image, ImageDraw
img = Image.new('RGB', (100, 100))
drw = ImageDraw.Draw(img, 'RGBA')
drw.polygon([(50, 0), (100, 100), (0, 100)], (255, 0, 0, 125))
drw.polygon([(50,100), (100, 0), (0, 0)], (0, 255, 0, 125))
del drw
img.save('out.png', 'PNG')
这将绘制两个三角形,并将它们的两种颜色混合在一起。这比必须为每个多边形合成多个“层”要快得多。
[使用PIL绘制透明图像时,我要做的是创建一个彩色层,一个在其上绘制了多边形的不透明层,并将其与基础层进行合成:
color_layer = Image.new('RGBA', base_layer.size, fill_rgb)
alpha_mask = Image.new('L', base_layer.size, 0)
alpha_mask_draw = ImageDraw.Draw(alpha_mask)
alpha_mask_draw.polygon(self.outline, fill=fill_alpha)
base_layer = Image.composite(color_layer, base_layer, alpha_mask)
使用Image.Blend时,在绘制的多边形上出现奇怪的轮廓行为问题。
这种方法的唯一问题是,在绘制大量合理尺寸的多边形时,性能非常糟糕。一种更快的解决方案是类似于“手动”在图像的numpy数组表示上绘制多边形。
PIL的图像模块提供了一种混合方法。
[创建第二张与您的第一张相同尺寸的图像,并使用黑色背景。在其上绘制您的多边形(全彩色)。然后调用Image.blend传递两个图像和一个Alpha级别。它返回第三张图像,上面应该有一个半透明的多边形。
我还没有衡量性能(嘿,我什至没有尝试过!),所以我无法评论它的适用性。我建议您制定性能预算,然后对其进行评估,以了解它是否足够快地满足您的目的。
我为此使用cairo + pycairo,并且效果很好。如果pil中无法在cairo中进行操作,则可以使用python缓冲区接口在PIL和cairo之间共享图像数据。
根据我的发现,它不能直接使用PIL完成。这是PyCairo的解决方案。 Mozilla,GTX +,Mono,Inkscape和WebKit也使用Cairo,所以我认为就将来的支持而言,它是安全的。也可以使用aggdraw(PIL的可选附件)来完成。请参阅我列出的资源以获取更多详细信息。使用Python版本2.7.3。
来源:http://livingcode.org/2008/12/14/drawing-with-opacity.1.html
帮助文件:random_polys_util.py
MIN_ALPHA = 50
MAX_ALPHA = 100
WIDTH = 500
HEIGHT = 250
#
# Utilities
#
def hex2tuple(hex_color):
return tuple([int(hex_color[i:i+2], 16) for i in range(1,9,2)])
def tuple2hex(tuple_color):
return "#%0.2X%0.2X%0.2X%0.2X" % tuple_color
def ints2floats(tuple_color):
return tuple([c / 255.0 for c in tuple_color])
def inc_point(p, dp):
return (p[0] + dp[0]) % WIDTH, (p[1] + dp[1]) % HEIGHT
def inc_triangle(t, dt):
return tuple([inc_point(t[i], dt[i]) for i in range(3)])
def inc_color(c, dc):
new_c = [(c[i] + dc[i]) % 256 for i in range(3)]
new_a = (c[3] + dc[3]) % MAX_ALPHA
if new_a < MIN_ALPHA: new_a += MIN_ALPHA
new_c.append(new_a)
return tuple(new_c)
def draw_all(draw_fn):
triangle = start_t
color = start_c
for i in range(50):
triangle = inc_triangle(triangle, dt)
color = inc_color(color, dc)
draw_fn(triangle, color)
#
# Starting and incrementing values
#
start_c = hex2tuple('E6A20644')
start_t = (127, 132), (341, 171), (434, 125)
dt = (107, 23), (47, 73), (13, 97)
dc = 61, 113, 109, 41
主文件:random_polys.py
from random_polys_util import *
def cairo_poly(pts, clr):
ctx.set_source_rgba(*ints2floats(clr))
ctx.move_to(*pts[-1])
for pt in pts:
ctx.line_to(*pt)
ctx.close_path()
ctx.fill()
def cairo_main():
# Setup Cairo
import cairo
global ctx
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
ctx = cairo.Context(surface)
# fill background white
cairo_poly(((0,0),(WIDTH,0),(WIDTH,HEIGHT),(0,HEIGHT)),(255,255,255,255))
draw_all(cairo_poly)
surface.write_to_png('cairo_example.png')
def main():
cairo_main()
if __name__ == "__main__":
main()
import cv2
import numpy as np
from shapely.geometry import Polygon
alpha = 0.5 # that's your transparency factor
path = 'path_to_image.jpg'
image = cv2.imread(path)
(H, W) = image.shape[:2]
xmin = 0
ymin = 0
xmax = int(W / 2)
ymax = int(H / 2)
polygon = Polygon([(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)])
int_coords = lambda x: np.array(x).round().astype(np.int32)
exterior = [int_coords(polygon.exterior.coords)]
overlay = image.copy()
cv2.fillPoly(overlay, exterior, color=(255, 255, 0))
cv2.addWeighted(overlay, alpha, image, 1 - alpha, 0, image)
cv2.imshow("Polygon", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
我必须绘制带有轮廓的外部多边形,然后减去内部多边形(在GIS中是常见的操作)。使用颜色(255,255,255,0)
就像吊饰一样工作。
image = Image.new("RGBA", (100,100))
drawing = ImageDraw.Draw(i)
for index, p in enumerate(polygons):
if index == 0:
options = { 'fill': "#AA5544",
'outline': "#993300"}
else:
options = {'fill': (255,255,255,0)}
drawing.polygon( p, **options )
buf= StringIO.StringIO()
i.save(buf, format= 'PNG')
# do something with buf