【问题标题】:Is it possible to do additive blending with matplotlib?是否可以使用 matplotlib 进行加法混合?
【发布时间】:2014-12-29 09:31:45
【问题描述】:

在处理重叠的高密度散点图或不同颜色的线图时,可以方便地实施加法混合方案,其中每个标记的 RGB 颜色相加在一起以在画布中生成最终颜色。这是 2D 和 3D 渲染引擎中的常见操作。

但是,在 Matplotlib 中,我只发现了对 alpha/opacity 混合的支持。有什么迂回的方法吗?还是我坚持渲染到位图,然后将它们混合到某个绘图程序中?

编辑:这是一些示例代码和手动解决方案。

这将产生两个部分重叠的随机分布:

x1 = randn(1000)
y1 = randn(1000)
x2 = randn(1000) * 5
y2 = randn(1000)
scatter(x1,y1,c='b',edgecolors='none')
scatter(x2,y2,c='r',edgecolors='none')

这将在 matplotlib 中产生以下内容:

如您所见,有一些重叠的蓝点被红点遮挡,我们希望看到它们。通过在 matplotlib 中使用 alpha/opacity blending,您可以:

scatter(x1,y1,c='b',edgecolors='none',alpha=0.5)
scatter(x2,y2,c='r',edgecolors='none',alpha=0.5)

这将产生以下内容:

但我真正想要的是以下内容:

我可以通过将每个绘图独立地渲染到位图来手动完成:

xlim = plt.xlim()
ylim = plt.ylim()
scatter(x1,y1,c='b',edgecolors='none')
plt.xlim(xlim)
plt.ylim(ylim)
scatter(x2,y2,c='r',edgecolors='none')
plt.xlim(xlim)
plt.ylim(ylim)
plt.savefig(r'scatter_blue.png',transparent=True)
plt.savefig(r'scatter_red.png',transparent=True)

这给了我以下图片:

然后您可以将它们作为独立图层加载到 Paint.NET/PhotoShop/gimp 中,然后添加混合它们。

现在理想的是能够在 Matplotlib 中以编程方式执行此操作,因为我将处理数百个这些!

【问题讨论】:

  • 最简单的方法可能是制作二维直方图。请向我们展示一些示例代码和数据以帮助我们入门。
  • 谢谢,刚刚添加了一些示例代码和手动解决方案的步骤。
  • 谢谢,现在问题好多了,看看我能做什么。
  • 我不认为这是我们支持开箱即用的模式。
  • 我也不明白您关于“固定颜色背景”的评论,它应该与画布上当前的内容混合。

标签: python matplotlib blending color-blending


【解决方案1】:

如果你只需要一个图像作为结果,你可以将画布缓冲区作为一个numpy数组,然后进行混合,这里是一个例子:

from matplotlib import pyplot as plt
import numpy as np

fig, ax = plt.subplots()
ax.scatter(x1,y1,c='b',edgecolors='none')
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)
ax.patch.set_facecolor("none")
ax.patch.set_edgecolor("none")
fig.canvas.draw()

w, h = fig.canvas.get_width_height()
img = np.frombuffer(fig.canvas.buffer_rgba(), np.uint8).reshape(h, w, -1).copy()

ax.clear()
ax.scatter(x2,y2,c='r',edgecolors='none')
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)
ax.patch.set_facecolor("none")
ax.patch.set_edgecolor("none")
fig.canvas.draw()

img2 = np.frombuffer(fig.canvas.buffer_rgba(), np.uint8).reshape(h, w, -1).copy()

img[img[:, :, -1] == 0] = 0
img2[img2[:, :, -1] == 0] = 0

fig.clf()

plt.imshow(np.maximum(img, img2))
plt.subplots_adjust(0, 0, 1, 1)
plt.axis("off")
plt.show()

结果:

【讨论】:

  • 当你的答案出现时,我实际上只是在检查 buffer_rgba() 函数。是的,我认为这是目前使用 Matplotlib 可以做到的最好的。由于某种原因,在我的 Matplotlib 版本中,最终结果并不那么漂亮(透明度被搞砸了),但我确信只要稍加调整,我现在就能让它工作。谢谢!
  • 那么目前没有获得矢量图形的解决方案吗? :(
【解决方案2】:

我的 matplotlib 后端 https://github.com/anntzer/mplcairo(仅限主服务器)现在支持此功能:

import matplotlib; matplotlib.use("module://mplcairo.qt")
from matplotlib import pyplot as plt
from mplcairo import operator_t
import numpy as np

x1 = np.random.randn(1000)
y1 = np.random.randn(1000)
x2 = np.random.randn(1000) * 5
y2 = np.random.randn(1000)
fig, ax = plt.subplots()
# The figure and axes background must be made transparent.
fig.patch.set(alpha=0)
ax.patch.set(alpha=0)
pc1 = ax.scatter(x1, y1, c='b', edgecolors='none')
pc2 = ax.scatter(x2, y2, c='r', edgecolors='none')
operator_t.ADD.patch_artist(pc2)  # Use additive blending.
plt.show()

【讨论】:

  • 这是你的图书馆吗?如果是这样,您应该在回答中明确说明您是作者
猜你喜欢
  • 2020-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-25
  • 1970-01-01
  • 2013-12-18
  • 1970-01-01
  • 2021-10-29
相关资源
最近更新 更多