2017-01-23 98 views
0

简而言之:我使用matplotlib绘制了scater图和曲面。我遇到了一个问题,因此表面总是绘制在点的顶部,而不是像它应该的那样。Matplotlib:混色或如何预处理颜色以抵消透明度

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

我遇到的表面和点的问题与here描述的问题类似。


下面是详细信息:

我在Matplotlib蓝和红点的三维散点图:

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 hereenter image description here

一旦分离面被绘制时,我无法迫使平面红色和蓝色点(如从平面方程和点的位置预期)的平面之间绘制总是出现在所有要点之上。

的解决方案,我想大概是这样的:“预处理”蓝点的颜色,这样,当与透明平面的颜色叠加我得到原来的蓝色。通过这种方式,这些点将显示在飞机的顶部,它应该“解决”我当前的问题。

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

换句话说,我想才达到类似sepicifiying: Blue = #0000FFRed = #FF0000PreProcBlue = "#-FF00FF"'使PreProcBlue + Red = Blue

谢谢!

+0

如果曲面应该位于** all **点的后面,那么您可以简单地使用'zorder'参数(例如,表面为'zorder = -1',点为'zorder = 1')。 – ImportanceOfBeingErnest

+0

当用半透明平面覆盖时出现蓝色的点出现了什么问题?然后你会有红点和不那么蓝点。无论如何,你在这里尝试的解决方案是不可能的。 – ImportanceOfBeingErnest

+0

@ImportanceOfBeingErnest感谢您的评论,第一条评论:表面平面应该位于红点和蓝点之间,即红点和蓝点之间。 'zorder'不起作用,我尝试了不同的方式。对第二个评论:我想和飞机以及没有飞机的情况并排放置,所以我想要在这两个地块上匹配蓝色点的颜色。我对高质量的自动输出感兴趣,所以颜色的小变化很重要,否则,我不会打扰。 – them

回答

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表现为预期的,示出的平面上方的红点和蓝点在它下面。

enter image description here

请注意,我已经使用matplotlib 2.0.0生产这些地块;我不确定,如果1.5.3或更低版本的情况相同。


为什么是不可能的“预补偿”的背景点的颜色混合使用的情况下覆盖一些见解,所产生的颜色应该是完全蓝色:

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

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

正如你所看到的,蓝色通道需要为2才能工作,这是在颜色系统的范围之外。当然你可能想验证对于任何其他颜色cover这仍然是真实的,但它已经很直观地清楚了:对于任何用透明颜色cover混合,cdot的蓝色通道将大于1,产生一个不存在的颜色。

+0

谢谢,我将它标记为答案,因为它可以解决我的问题,它是解决它的正确方法,但我仍然在寻找颜色混合的公式以解决我的具体问题,而无需更新等。 – them

+1

我已经添加了一些细节,说明为什么不可能进行混合,结果会是完全蓝色的。 – ImportanceOfBeingErnest