添加背景图像到3d图 [英] Add background image to 3d plot
问题描述
在级别 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屋!