Matplotlib plot_surface透明度伪像 [英] Matplotlib plot_surface transparency artefact

查看:160
本文介绍了Matplotlib plot_surface透明度伪像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从一组指定 z 值的数据中绘制 3D 曲面.尽管我设置了alpha = 1.0,但我还是得到了一些奇怪的透明伪像,即使从那里也可以看到它.

I'm trying to plot a surface in 3D from a set of data which specifies the z-values. I get some weird transparency artefact though, where I can see through the surface, even though I set alpha=1.0.

在绘图和保存到文件(png 和 pdf 格式)时都存在人工制品:

The artefact is present both when plotting and when saved to file (both as png and pdf):

我尝试更改线宽,并将步幅数从 1 更改为 10(在后一种情况下,由于分辨率太粗糙,表面不可见).

I have tried changing the line width, and changing the number of strides from 1 to 10 (in the latter case, the surface is not visible though due to too rough resolution).

问:我怎样才能摆脱这种透明度?

这是我的代码:

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

y_label = r'x'
x_label = r'y'
z_label = r'z'

x_scale = 2.0*np.pi
y_scale = 2.0*np.pi

y_numPoints = 250
x_numPoints = 250

def quasiCrystal(x, y):
    z = 0
    for i in range(0,5):
        z += np.sin(x * np.cos(float(i)*np.pi/5.0) +
                    y * np.sin(float(i)*np.pi/5.0))
    return z

x = np.linspace(-x_scale, x_scale, x_numPoints)
y = np.linspace(-y_scale, y_scale, y_numPoints)
X,Y = np.meshgrid(x,y)

Z = quasiCrystal(X, Y)


f = plt.figure()
ax = f.gca(projection='3d')

surf = ax.plot_surface( X, Y, Z,
                        rstride=5, cstride=5,
                        cmap='seismic',
                        alpha=1,
                        linewidth=0,
                        antialiased=True,
                        vmin=np.min(Z),
                        vmax=np.max(Z)
                      )

ax.set_zlim3d(np.min(Z), np.max(Z))

f.colorbar(surf, label=z_label)

ax.set_xlabel(x_label)
ax.set_ylabel(y_label)
ax.set_zlabel(z_label)

plt.show()

这是我的实际数据的另一张图片,在此图片中更容易看到伪像:

Here is another picture of my actual data where it is easier to see the artefact:

推荐答案

Matplotlib 不是真正的"3D 引擎.这是一个众所周知的问题,偶尔会出现与您类似的问题(参见 thisthis).问题在于,相同的人工制品可能会引发看起来不同的问题.我相信您就是这种情况.

Matplotlib is not a "real" 3D engine. This is a very well known problem and once in a while a similar question to yours appears appears (see this and this). The problem is that the same artefact can originate problems that seem to be different. I believe such is the case for you.

在继续我的建议之前,让我从 maplotlib 网站引用此信息:

Before going on with my recommendations let me just quote this information from the maplotlib website:

我的3D图在某些视角下看起来不正确

这可能是mplot3d最常报告的问题.问题是从某些视角来看,一个 3D 对象会出现在另一个对象,即使它实际上在后面.这个可以导致绘图看起来物理上不正确".

This is probably the most commonly reported issue with mplot3d. The problem is that – from some viewing angles – a 3D object would appear in front of another object, even though it is physically behind it. This can result in plots that do not look "physically correct."

不幸的是,虽然正在做一些工作以减少发生这个神器,目前是一个棘手的问题,不能得到全面解决,直到matplotlib支持其3D图形渲染为止核心.

Unfortunately, while some work is being done to reduce the occurance of this artifact, it is currently an intractable problem, and can not be fully solved until matplotlib supports 3D graphics rendering at its core.

问题是由于将 3D 数据缩减为 2D +z阶标量.单个值代表所有维度的第3维集合中3D对象的一部分.因此,当边界两个集合的盒子相交,这成为可能出现的工件.此外,两个 3D 对象的交集(例如多边形或补丁)无法正确渲染matplotlib 的 2D 渲染引擎.

The problem occurs due to the reduction of 3D data down to 2D + z-order scalar. A single value represents the 3rd dimension for all parts of 3D objects in a collection. Therefore, when the bounding boxes of two collections intersect, it becomes possible for this artifact to occur. Furthermore, the intersection of two 3D objects (such as polygons or patches) can not be rendered properly in matplotlib’s 2D rendering engine.

在添加 OpenGL 支持之前,此问题可能无法解决所有后端(非常欢迎补丁).在那之前,如果您需要复杂的 3D 场景,我们建议使用 MayaVi.

This problem will likely not be solved until OpenGL support is added to all of the backends (patches are greatly welcomed). Until then, if you need complex 3D scenes, we recommend using MayaVi.

看来 Mayavi 终于转向 Python 3,因此肯定有可能.如果您想坚持使用 matplotlib 来绘制此类图,我的建议是您使用 rstride 和 cstride 值来查看哪些值会产生令您满意的图.

It seems that Mayavi has finally moved on to Python 3, so its certainly a possibility. If you want to stick with matplotlib for this kind of plot my advice is that you work with rstride and cstride values to see which ones produce a plot satisfactory to you.

surf = ax.plot_surface( X, Y, Z,
                        rstride=5, cstride=5,
                        cmap='jet',
                        alpha=1,
                        linewidth=0,
                        antialiased=True,
                        vmin=0,
                        rstride=10,
                        cstride=10,
                        vmax=z_scale
                      )

其他可能性是尝试查看其他类型的3D绘图是否做得更好.检查 plot_trisurf 等高线.我知道它并不理想,但过去我也设法绕开使用 3D 多边形的其他类型的人工制品.

Other possibility is to try to see if other kinds of 3D plots do better. Check plot_trisurf, contour or contourf. I know its not ideal but in the past I also managed to circumvent other type of artefacts using 3D polygons.

抱歉没有更满意的答案.也许其他SO用户对此有更好的解决方案.祝你好运.

Sorry for not having a more satisfactory answer. Perhaps other SO users have better solutions for this. Best of luck.

这篇关于Matplotlib plot_surface透明度伪像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆