How to plot a imshow()
image in 3d axes? I was trying with this post. In that post, the surface plot looks same as imshow()
plot but actually they are not. To demonstrate, here I took different data:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
# create a 21 x 21 vertex mesh
xx, yy = np.meshgrid(np.linspace(0,1,21), np.linspace(0,1,21))
# create vertices for a rotated mesh (3D rotation matrix)
X = xx
Y = yy
Z = 10*np.ones(X.shape)
# create some dummy data (20 x 20) for the image
data = np.cos(xx) * np.cos(xx) + np.sin(yy) * np.sin(yy)
# create the figure
fig = plt.figure()
# show the reference image
ax1 = fig.add_subplot(121)
ax1.imshow(data, cmap=plt.cm.BrBG, interpolation='nearest', origin='lower', extent=[0,1,0,1])
# show the 3D rotated projection
ax2 = fig.add_subplot(122, projection='3d')
ax2.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=plt.cm.BrBG(data), shade=False)
Here are my plots:
The first one is a standard import statement for plotting using matplotlib, which you would see for 2D plotting as well. The second import of the Axes3D class is required for enabling 3D projections.
imshow( BW ) displays the binary image BW in a figure. For binary images, imshow displays pixels with the value 0 (zero) as black and 1 as white. imshow( X , map ) displays the indexed image X with the colormap map . imshow( filename ) displays the image stored in the graphics file specified by filename .
Creating 3D surface Plot The axes3d present in Matplotlib's mpl_toolkits. mplot3d toolkit provides the necessary functions used to create 3D surface plots. Surface plots are created by using ax. plot_surface() function.
I think your error in the 3D vs 2D surface colour is due to data normalisation in the surface colours. If you normalise the data passed to plot_surface
facecolor with, facecolors=plt.cm.BrBG(data/data.max())
the results are closer to what you'd expect.
If you simply want a slice normal to a coordinate axis, instead of using imshow
, you could use contourf
, which is supported in 3D as of matplotlib 1.1.0,
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from matplotlib import cm
# create a 21 x 21 vertex mesh
xx, yy = np.meshgrid(np.linspace(0,1,21), np.linspace(0,1,21))
# create vertices for a rotated mesh (3D rotation matrix)
X = xx
Y = yy
Z = 10*np.ones(X.shape)
# create some dummy data (20 x 20) for the image
data = np.cos(xx) * np.cos(xx) + np.sin(yy) * np.sin(yy)
# create the figure
fig = plt.figure()
# show the reference image
ax1 = fig.add_subplot(121)
ax1.imshow(data, cmap=plt.cm.BrBG, interpolation='nearest', origin='lower', extent=[0,1,0,1])
# show the 3D rotated projection
ax2 = fig.add_subplot(122, projection='3d')
cset = ax2.contourf(X, Y, data, 100, zdir='z', offset=0.5, cmap=cm.BrBG)
ax2.set_zlim((0.,1.))
plt.colorbar(cset)
plt.show()
This code results in this image:
Although this won't work for a slice at an arbitrary position in 3D where the imshow solution is better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With