【问题标题】:Matplotlib: color mixing or how to preprocess color to counteract transparencyMatplotlib:颜色混合或如何预处理颜色以抵消透明度
【发布时间】:2023-04-05 06:24:01
【问题描述】:

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

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

我遇到的面点问题和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)

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

绘制分离平面后,我无法强制在红点和蓝点之间绘制平面(正如平面方程和点的位置所预期的那样)平面总是出现在所有的点。

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

我用过HEXcolor specification,我不确定在matplotlib中使用透明度时颜色如何混合。我正在寻找参考或建议我应该如何“抵消”飞机的红色透明色,例如alpha = 0.2

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

谢谢!

【问题讨论】:

  • 如果表面应该在所有点之后,您可以简单地使用zorder参数(例如zorder=-1用于表面,zorder=1用于点) .
  • 当被半透明平面覆盖时,出现蓝色点有什么问题?然后你会有红点和不那么蓝的点。无论如何,您在这里尝试的解决方案是不可能的。
  • @ImportanceOfBeingErnest 感谢 cmets,对于第一条评论:表面平面应该在红点和蓝点之间,即在红点之上和蓝点之后。 zorder 不起作用,我尝试了不同的方法。对于第二条评论:我想把有飞机的箱子和没有飞机的箱子放在一起,所以我希望蓝点的颜色在这两个图上匹配。我对高质量的自动输出很感兴趣,所以颜色的微小变化很重要,否则,我不会打扰。
  • 所以你可以去另一个方向。在没有平面的情况下将点着色为与有平面的相同颜色。这实际上是可行的,您只需要绘制一次,使用一些颜色选择器程序来确定带有平面的图片中的颜色,然后将其应用于没有平面的情况。
  • @ImportanceOfBeingErnest 好主意,感谢您提及,但是,这些图与其他类似样式的图(使用蓝红色的图)一起用于出版质量文档中,我想坚持整张纸都是蓝色的……我现在不想换成另一种蓝色。

标签: python matplotlib colors color-scheme


【解决方案1】:

一个问题是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 的行为符合预期,显示平面上方的红点和下方的蓝点。

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


关于为什么在结果颜色应该是全蓝色的情况下,为什么不可能“预补偿”混合背景点的颜色与叠加层的一些见解:

我们停留在 RGBA 色彩场景中,其中每种颜色由元组(红色、绿色、蓝色、alpha)表示,其中每个通道的值可以介于 01 之间。
生成的颜色应为全蓝色: cres = (0,0,1,1)。覆盖层的颜色可以是一些半透明的红色:cover = (1,0,0,0.5)

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

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

【讨论】:

  • 谢谢,我会将其标记为答案,因为它可以解决我的问题并且是解决问题的正确方法,尽管我仍然想知道颜色混合的公式来解决我的具体问题更新等等...
  • 我添加了一些详细信息,说明为什么无法进行混合以使结果变为全蓝。
猜你喜欢
  • 2017-09-23
  • 2021-02-18
  • 2012-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-07
  • 2021-04-07
相关资源
最近更新 更多