Как вы рисуете прозрачные полигоны с помощью Python?

Я использую PIL (Python Imaging Library). Я хотел бы нарисовать прозрачные полигоны. Кажется, что указание цвета заливки, включающего альфа-уровень, не работает. Их обходные пути?

Если это не может быть сделано с помощью PIL, я готов использовать что-то еще.

Если существует более одного решения, необходимо учитывать производительность. Рисование должно быть максимально быстрым.

11.12.2008 15:26:43
6 ОТВЕТОВ

Для этого я использую cairo + pycairo, и он работает хорошо. И вы можете делиться данными изображения между PIL и cairo, используя буферный интерфейс python, если в pil есть операция, которую нельзя сделать в cairo.

2
18.12.2008 14:44:16

Модуль Image PIL предоставляет метод наложения.

Создайте второе изображение того же размера, что и ваше первое, с черным фоном. Нарисуйте на нем свой многоугольник (с полным цветом). Затем вызовите Image.blend, передав два изображения и альфа-уровень. Возвращает третье изображение, на котором должен быть полупрозрачный многоугольник.

Я не измерял производительность (эй, я даже не пробовал!), Поэтому я не могу комментировать ее пригодность. Я предлагаю вам составить свой бюджет производительности, а затем измерить его, чтобы увидеть, достаточно ли он быстр для ваших целей.

3
22.12.2008 09:40:34

При использовании 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 у меня были проблемы со странным поведением обводки на нарисованных полигонах.

Единственная проблема, связанная с этим подходом, заключается в том, что при рисовании большого количества полигонов разумного размера производительность является ужасной. Гораздо более быстрым решением было бы что-то вроде «ручного» рисования многоугольника на представлении изображения в виде массива.

6
3.02.2009 21:14:54

Мне пришлось нарисовать внешний многоугольник с контуром и вычесть внутренние многоугольники (обычная операция в ГИС). Работает как шарм с использованием цвета (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
-1
13.03.2012 14:43:12
Это не имеет ничего общего с прозрачностью.
Junuxx 20.05.2012 23:10:22

Из того, что я обнаружил, это нельзя сделать напрямую с помощью PIL. Вот решение с PyCairo. Cairo также используется в Mozilla, GTX +, Mono, Inkscape и WebKit, поэтому я считаю, что это безопасно для будущей поддержки. Это также можно сделать с помощью 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()
1
11.05.2012 16:28:52

Это для Pillow, более ухоженной вилки PIL. http://pillow.readthedocs.org/

Если вы хотите рисовать прозрачные многоугольники относительно друг друга, базовое изображение должно быть типа 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')

Это нарисует два треугольника, перекрывающихся с их смешением двух цветов. Это намного быстрее, чем составлять несколько «слоев» для каждого многоугольника.

55
13.02.2014 23:56:17
Спасибо, это очень полезно. Я понятия не имею, откуда у вас эта информация - я не вижу ее документированной. Я получил странное поведение, когда использовал комбинации RGB / RGBA, отличные от тех, которые вы упомянули ...
jwd 24.09.2015 01:45:59
Почему ты пишешь del drw, а не del img?
Marcus Johansson 24.05.2016 14:19:26
Работает как шарм! (Жаль, что вам нужно прокрутить весь путь вниз, чтобы получить лучший ответ :))
Anton vBR 10.07.2017 13:56:07
Я второй "где ты нашел эту документацию";)
javadba 22.04.2020 05:08:35