Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plotting a imshow() image in 3d in matplotlib

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:

http://www.physics.iitm.ac.in/~raj/imshow_plot_surface.png

like image 734
Raj Avatar asked May 26 '15 16:05

Raj


People also ask

Can matplotlib plot 3D images?

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.

How do you show images on Imshow?

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 .

How do you plot a 3D surface graph in Python?

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.


1 Answers

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:

result

Although this won't work for a slice at an arbitrary position in 3D where the imshow solution is better.

like image 56
Ed Smith Avatar answered Sep 18 '22 11:09

Ed Smith