添加背景图像到3d图 [英] Add background image to 3d plot

查看:145
本文介绍了添加背景图像到3d图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



在级别 z = min(z)-1 ,其中 -1 是一个视觉偏移,以避免重叠,我想插入一个图像曲线显示特定值的元素。 怎么做?



在这个例子中,我不关心元素及其值之间的完美匹配,所以请随意上传你喜欢的任何图像。另外,有没有办法让图像旋转,以防有人对匹配不满意?



编辑



这是类似于3D直方图的可视化示例。级别 z = 0 的灰色形状是条形图显示某个 z 值的元素。

解决方案

使用 plot_surface 通过 facecolors 参数绘制图像。

 来自mpl_toolkits.mplot3d import Axes3D 
来自matplotlib导入cm
来自matplotlib.ticker导入LinearLocator,FormatStrFormatter
导入matplotlib.pyplot作为plt
导入numpy为np
来自matplotlib._png import read_png
来自matplotlib.cbook import get_sample_data

fig = plt.figure()
ax = fig.gca(projection ='3d')
X = np.arange( -5,5,.25)
Y = np.arange(-5,5,.25)
X,Y = np.meshgrid(X,Y)
R = np。 sqrt(X ** 2 + Y ** 2)
Z = np.sin(R)
surf = ax.plot_surface(X,Y,Z,rstride = 1,cstrid e = 1,cmap = cm.winter,
linewidth = 0,antialiased = True)

ax.set_zlim(-2.01,1.01)
ax.zaxis.set_major_locator(LinearLocator (10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%。02f'))

fn = get_sample_data(./ lena.png,asfileobj = False)
arr = read_png(fn)
#10是表面的x和y轴的相等长度
stepX,stepY = 10. / arr.shape [0],10。/ arr.shape [1 ]

X1 = np.arange(-5,5,stepX)
Y1 = np.arange(-5,5,stepY)
X1,Y1 = np.meshgrid (X1,Y1)
#stride args允许确定图像质量
#stride = 1 work slow
ax.plot_surface(X1,Y1,-2.01,rstride = 1,cstride = 1, facecolors = arr)

plt.show()



如果您需要添加值,请使用 PathPatch


来自mpl_toolkits.mplot3d的

 从matplotlib导入Axes3D 
从matplotlib.ticker导入cm
导入LinearLocator,FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import mpl_toolkits.mplot3d.art3d as art3d
from matplotlib.text import MatPath
from matplotlib.transforms从matplotlib.patches导入Affine2D
导入PathPatch

def text3d(ax,xyz,s,zdir =z,size = None,angle = 0,usetex = False,** kwargs ):
x,y,z = xyz
如果zdir ==y:
xy1,z1 =(x,z),y
elif zdir ==y :
xy1,z1 =(y,z),x
else:
xy1,z1 =(x,y),z

text_path = TextPath(( 0,0),s,size = size,usetex = usetex)
trans = Affine2D()。rotate(angle).translate(xy1 [0],xy1 [1])$ ​​b
$ b p1 = PathPatch(trans.transform_path(text_path),** kwargs)
ax.add_patch(p1)
art3d.pathpatch_2d_to_3d( p1,z = z1,zdir = zdir)

#main
fig = plt.figure()
ax = fig.gca(projection ='3d')
X = np.arange(-5,5,.25)
Y = np.arange(-5,5,.25)

Xg,Yg = np.meshgrid(X ,Y)
R = np.sqrt(Xg ** 2 + Yg ** 2)
Z = np.sin(R)
surf = ax.plot_surface(Xg,Yg,Z ,rstride = 1,cstride = 1,cmap = cm.winter,
linewidth = 0,antialiased = True)

ax.set_zlim(-2.01,1.01)
ax。 zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%。02f'))

#为i添加路径值为
,x in枚举(X [:: 4]):
表示j,y表示枚举(Y [:: 4]):
text3d(ax,(x,y,-2.01),{0: .1f}。format(Z [i] [j]),zdir =z,size = .5,ec =none,fc =k)

plt.show ()


This topic has been touched here, but no indications were given as to how to create a 3D plot and insert an image in the (x,y) plane, at a specified z height.

So to come up with a simple and reproducible case, let's say that I create a 3D plot like this with mplot3d:

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.winter,
                       linewidth=0, antialiased=True)
ax.set_zlim(-1.01, 1.01)

ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

plt.show()

Visually we have:

At the level z=min(z)-1, where -1 is a visual offset to avoid overlapping, I want to insert an image representing the elements for which the curve shows a certain value. How to do it?

In this example I don't care about a perfect matching between the element and its value, so please feel free to upload any image you like. Also, is there a way of letting that image rotate, in case one is not happy with the matching?

EDIT

This is a visual example of something similar made for a 3D histogram. The grey shapes at the level z=0 are the elements for which the bars show a certain z value. Source.

解决方案

Use plot_surface to draw image via facecolors argument.

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np
from matplotlib._png import read_png
from matplotlib.cbook import get_sample_data

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(-5, 5, .25)
Y = np.arange(-5, 5, .25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.winter,
                       linewidth=0, antialiased=True)

ax.set_zlim(-2.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

fn = get_sample_data("./lena.png", asfileobj=False)
arr = read_png(fn)
# 10 is equal length of x and y axises of your surface
stepX, stepY = 10. / arr.shape[0], 10. / arr.shape[1]

X1 = np.arange(-5, 5, stepX)
Y1 = np.arange(-5, 5, stepY)
X1, Y1 = np.meshgrid(X1, Y1)
# stride args allows to determine image quality 
# stride = 1 work slow
ax.plot_surface(X1, Y1, -2.01, rstride=1, cstride=1, facecolors=arr)

plt.show()

If you need to add values use PathPatch:

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import mpl_toolkits.mplot3d.art3d as art3d
from matplotlib.text import TextPath
from matplotlib.transforms import Affine2D
from matplotlib.patches import PathPatch

def text3d(ax, xyz, s, zdir="z", size=None, angle=0, usetex=False, **kwargs):
    x, y, z = xyz
    if zdir == "y":
        xy1, z1 = (x, z), y
    elif zdir == "y":
        xy1, z1 = (y, z), x
    else:
        xy1, z1 = (x, y), z

    text_path = TextPath((0, 0), s, size=size, usetex=usetex)
    trans = Affine2D().rotate(angle).translate(xy1[0], xy1[1])

    p1 = PathPatch(trans.transform_path(text_path), **kwargs)
    ax.add_patch(p1)
    art3d.pathpatch_2d_to_3d(p1, z=z1, zdir=zdir)

# main
fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(-5, 5, .25)
Y = np.arange(-5, 5, .25)

Xg, Yg = np.meshgrid(X, Y)
R = np.sqrt(Xg**2 + Yg**2)
Z = np.sin(R)
surf = ax.plot_surface(Xg, Yg, Z, rstride=1, cstride=1, cmap=cm.winter,
                       linewidth=0, antialiased=True)

ax.set_zlim(-2.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

# add pathces with values
for i,x in enumerate(X[::4]):
    for j,y in enumerate(Y[::4]):
        text3d(ax, (x, y, -2.01), "{0:.1f}".format(Z[i][j]), zdir="z", size=.5, ec="none", fc="k")

plt.show()

这篇关于添加背景图像到3d图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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