python - Matplotlib:颜色混合或如何预处理颜色以抵消透明度

标签 python matplotlib colors color-scheme

简而言之:我正在使用 matplotlib 绘制散点图和曲面。我遇到了一个问题,因此曲面总是绘制在点的顶部,而不是应有的后面。

我想通过预处理点的颜色来解决这个问题,以便当被表面覆盖时我获得“原始颜色”,这样表面将出现在点后面。我使用 HEX 值指定点的颜色

我遇到的面和点的问题和描述的问题类似here .

<小时/>

详细信息如下:

我在 Matplotlib 中有一个蓝色和红色点的 3D 散点图:

self.subplot_3d = self.subplot.scatter(x_red, y_red, z_red, s = 150, c = RED,  depthshade = False, lw = 0, alpha = 1)
self.subplot_3d = self.subplot.scatter(x_blue, y_blue, z_blue, s = 150, c = BLUE,  depthshade = False, lw = 0, alpha = 1)

点是线性可分离的 - 存在一个分离平面,它将红点和蓝点分开。我使用绘制平原

self.plane = self.subplot.plot_surface(X, Y, Z, antialiased = True, color = RED_BACKGROUND, alpha = 0.5)

我想绘制两个图:在第一个图中,没有绘制分隔的普通图 - 只有红点和蓝点(左)。第二个有一个分离平面(右)。

enter image description here enter image description here

一旦绘制了分离平面,我就无法强制在红点和蓝点之间绘制平面(正如平面方程和点位置所预期的那样)平面始终出现在所有要点。

我正在考虑的解决方案如下:“预处理”蓝点的颜色,以便在与透明平面的颜色叠加时获得原始的蓝色。这样这些点就会出现在平面的顶部,它应该“解决”我当前的问题。

我使用了HEX color specification ,我不确定在 matplotlib 中使用透明度时颜色如何混合。我正在寻找引用或建议,如何用 alpha = 0.2 来“抵消”平面的红色透明颜色。

换句话说,我想实现类似 sepicifiying 的目标: Blue = #0000FF Red = #FF0000 PreProcBlue = "#-FF00FF"' 这样 PreProcBlue + Red = Blue >.

谢谢!

最佳答案

一个问题是scatter不尊重zorder 。因此可以使用plot相反。

我编译了一个示例来比较 plotscatter ,在 z=0 下方绘制蓝点,在 z=0 处绘制平面,在 z=0 上方绘制红点。
在每种情况下,我分别对蓝点、平面、红点使用 -100、1、100 的 zorder。 (请注意,如果 zorder 的差异较小或全部为正,则此操作将失败)

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(12,6))
ax = fig.add_subplot(121, projection='3d', aspect="equal")
ax2 = fig.add_subplot(122, projection='3d', aspect="equal")
plt.subplots_adjust(0,0,1,1,0,0)

x = np.array([-1,1])
X,Y = np.meshgrid(x,x)
Z = np.zeros_like(X)

xr = np.random.rand(10,3)
xb = np.random.rand(10,3)
xb[:,2] = xb[:,2]-1.


ax2.set_title("scatter")
ax2.scatter(xb[:,0], xb[:,1], xb[:,2], s = 144, c = "b",  depthshade = False, lw = 0, alpha = 1, zorder=-100)
ax2.plot_surface(X, Y, Z, antialiased = True, color = "#800000", alpha = 0.5, zorder=0)
ax2.scatter(xr[:,0], xr[:,1], xr[:,2], s = 144, c = "r",  depthshade = False, lw = 0, alpha = 1, zorder=100)

ax.set_title("plot")
ax.plot(xb[:,0], xb[:,1], xb[:,2], c = "b",  marker="o", markersize=12, lw = 0, alpha = 1, zorder=-100)
ax.plot_surface(X, Y, Z, antialiased = True, color = "#800000", alpha = 0.5, zorder=0)
ax.plot(xr[:,0], xr[:,1], xr[:,2], c = "r",  marker="o", markersize=12, lw = 0, alpha = 1, zorder=100)

ax2.view_init(elev=32, azim=115)
ax.view_init(elev=32, azim=115)

def on_move(event):
    if event.inaxes == ax:
        ax2.view_init(elev=ax.elev, azim=ax.azim)
    elif event.inaxes == ax2:
        ax.view_init(elev=ax2.elev, azim=ax2.azim)
    else:
        return
    fig.canvas.draw_idle()

c1 = fig.canvas.mpl_connect('motion_notify_event', on_move)

plt.savefig(__file__+".png")
plt.show()

从图中可以看出,plot其行为符合预期,显示平面上方的红点和下方的蓝点。

enter image description here

请注意,我使用 matplotlib 2.0.0 来生成这些图;我不确定 1.5.3 或更低版本是否相同。

<小时/>

关于为什么无法“预补偿”背景点的颜色以与叠加层混合以实现最终颜色应为全蓝色的一些见解:

我们停留在 RGBA 颜色组中,其中每种颜色都由元组(红、绿、蓝、alpha)表示,其中每个 channel 可以采用 0 之间的值。和1 .
最终的颜色应为全蓝色: cres = (0,0,1,1) 。覆盖层的颜色可以是一些半透明的红色:cover = (1,0,0,0.5)

然后可以使用通常的colormixing formulae来计算点的颜色。成为 cdot = (1,0,2,1)

如您所见,蓝色 channel 需要为 2为了让它发挥作用,这超出了颜色系统的范围。当然,您可能想验证任何其他颜色 cover这仍然是正确的,但直观上已经很清楚了:对于任何与透明颜色的混合cover , cdot的蓝色 channel 将大于 1 ,产生一种不存在的颜色。

关于python - Matplotlib:颜色混合或如何预处理颜色以抵消透明度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41815488/

相关文章:

python - 使用 pandas 在数据框上进行多图绘制

node.js - 使用 NPM 运行脚本在终端中进行彩色登录

android - 在 Android 的库 22 中以编程方式在 TextView 中设置 TextColor

Python Mechanize 写入 TinyMCE 文本编辑器

numpy - 在 Scipy 中计算 KL 散度时出错

python - 用零替换python数组中的Nones

python - 为什么 RGB 和 HLS 颜色系统之间的转换不精确?

python - PyQt5 styleSheet 动画

python - Zope:无法访问属性装饰器下的 REQUEST

python - 优化 Python 中的列表搜索