绘制半透明线/ 16位alpha值

时间:2014-07-23 22:21:12

标签: python opengl matplotlib alpha alphablending

我想绘制一个具有非常小的alpha值的大量(约100万)重叠半透明线。 我尝试了matplotlib,但显然不可能将alpha值设置为低于某个值(1/256)(参见https://github.com/matplotlib/matplotlib/issues/2287) 切换到OpenGL没有帮助,我有同样的问题(参见例如http://www.opengl.org/discussion_boards/showthread.php/170674-Alpha-Buffer-Alpha-Bits)。

是否有一种简单的方法来绘制具有非常小的alpha值的线条?

1 个答案:

答案 0 :(得分:1)

你需要一个行累加器,这里是从scikit-image修改的代码:

import cython
import numpy as np

@cython.wraparound(False)
@cython.boundscheck(False)
def acc_lines(Py_ssize_t[:, ::1] lines, int w, int h):
    cdef int[:, ::] count

    cdef char steep = 0
    cdef Py_ssize_t sx, sy, d, i, idx, r, c, dx, dy, x, y, x2, y2

    count = np.zeros((h, w), int)

    for idx in range(lines.shape[0]):
        steep = 0
        x = lines[idx, 0]
        y = lines[idx, 1]
        x2 = lines[idx, 2]
        y2 = lines[idx, 3]

        dx = x2 - x
        dy = y2 - y
        if dx < 0:
            dx = -dx
        if dy < 0:
            dy = -dy

        sx = 1 if (x2 - x) > 0 else -1
        sy = 1 if (y2 - y) > 0 else -1

        if dy > dx:
            steep = 1
            x, y = y, x
            dx, dy = dy, dx
            sx, sy = sy, sx

        d = (2 * dy) - dx

        for i in range(dx):
            if steep:
                r = x
                c = y
            else:
                r = y
                c = x
            if 0 <= r < h and 0 <= c < w:
                count[r, c] += 1

            while d >= 0:
                y = y + sy
                d = d - (2 * dx)
            x = x + sx
            d = d + (2 * dy)

        r = y2
        c = x2
        if 0 <= r < h and 0 <= c < w:
            count[r, c] += 1

    return count.base

这是一个演示如何使用它的演示:

from matplotlib.collections import LineCollection

w = h = 512
lines = np.random.randint(0, 512, size=(10000, 4))
count = acc_lines(lines, w, h)

fig, axes = pl.subplots(1, 2, figsize=(10, 5))
lc = LineCollection(lines.reshape(-1, 2, 2), alpha=0.015, color="black")

axes[0].imshow(count, cmap="gray_r")
axes[1].add_collection(lc)
axes[1].axis((0, w, h, 0))
axes[0].set_aspect("equal")
axes[1].set_aspect("equal")

这是输出,左边是acc_lines计算的图像,右边是LineCollection

enter image description here