首页 文章

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

提问于
浏览
0

简而言之:我正在使用 matplotlib 绘制一个scater情节和一个表面 . 我遇到了一个问题,因此表面总是被绘制在点的顶部,而不是应该在后面 .

我想通过预处理点的颜色来解决这个问题,这样当表面覆盖时我得到"original color",这样表面就会出现在点的后面 . 我使用 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)

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

enter image description here

enter image description here

绘制分离平面后,我无法强制在红点和蓝点之间绘制平面(正如平面方程和点的位置所预期的那样) The plane always appears on top of all the points.

我正在考虑的解决方案如下: "preprocess" the color of the blue points so that when overlayed with the color of the transparent plane I obtain the original blue color . 通过这种方式,点将显示在平面的顶部,它应该是我当前的问题 .

我使用了 HEX color specification,我不确定在matplotlib中使用透明度时颜色是如何混合的 . 我正在寻找参考或建议如何"counteract"飞机的红色透明颜色,比方说, alpha = 0.2 .

换句话说,我想实现像sepicifiying这样的东西: Blue = #0000FF Red = #FF0000 PreProcBlue = "#-FF00FF"' 以便 PreProcBlue + Red = Blue .

谢谢!

1 回答

  • 2

    一个问题是 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 才能工作,这超出了colorsystem的范围 . 当然你可能想要验证任何其他颜色 cover 这仍然是正确的,但它已经直观清晰:对于任何混合透明色 covercdot 的蓝色通道将大于 1 ,产生不存在颜色 .

相关问题