How to create surface plot from greyscale image with Matplotlib?

BlueLemon picture BlueLemon · Aug 4, 2015 · Viewed 13k times · Source

Let's say I have a greyscale image (size: 550x150 px). I load the image with matplolib

import matplotlib.pyplot as plt
import matplotlib.image as mp_img
image = mp_img.imread("my-cat.png")
plt.imshow(image)
plt.show()

Now, plt.imshow displays the image on the screen. But what I want is a surface plot of the greyscale values, something like this:

.Colour is not really a necessity, but it would be helpful for the height lines. I know, that I need a function of the form f(x,y) -> z to create the surface plot. So, I want to use the greyscale value at (x_pixel,y_pixel) in my image to get the value of f. This leads to my problem:

  • I'd like to do some interpolation (e.g. smoothing) of my image values during plotting. This depends also on the size of my meshgrid, so how do I control this? And,
  • how do I make a surface plot of the greyscale values from my image?

Answer

hitzg picture hitzg · Aug 4, 2015

So this is pretty straightforward. Load the data, build the plot:

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

# generate some sample data
import scipy.misc
lena = scipy.misc.lena()

# downscaling has a "smoothing" effect
lena = scipy.misc.imresize(lena, 0.15, interp='cubic')

# create the x and y coordinate arrays (here we just use pixel indices)
xx, yy = np.mgrid[0:lena.shape[0], 0:lena.shape[1]]

# create the figure
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(xx, yy, lena ,rstride=1, cstride=1, cmap=plt.cm.gray,
        linewidth=0)

# show it
plt.show()

Result:

enter image description here