0

I'm trying to plot a 3D shape with a 2D image overlaying the xy-plane. I've only just started working with python, so this is more challenging than it ought to be.

This question here addresses what I am trying to do : Image overlay in 3d plot using python. But when I run the provided code I get the following error:

File "test.py", line 13, in <module>
ax.plot_surface(x, y, 10, rstride=5, cstride=5, facecolors=img)
File "/usr/lib64/python2.7/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 663, in plot_surface
rows, cols = Z.shape
AttributeError: 'int' object has no attribute 'shape'

The image I am using is stored in the same folder as my 'test.py.' The question I referenced above uses an image from get_sample_data, but if I edit it to use my image, the code is as follows:

from pylab import *
from mpl_toolkits.mplot3d import Axes3D
from matplotlib._png import read_png

img = read_png('milkyway.png')

x, y = ogrid[0:img.shape[0], 0:img.shape[1]]
ax = gca(projection='3d')
ax.plot_surface(x, y, 10, rstride=5, cstride=5, facecolors=img)
show()

I get the same error whether I use get_sample_data or my own image. Any suggestions of what I can change? Thanks!

Community
  • 1
  • 1

2 Answers2

0

The error appears to be because plot_surface is expecting an array for the 'Z' argument, but you have given it the integer 10. (thus the error 'int' object has no attribute 'shape')

Luke
  • 11,374
  • 2
  • 48
  • 61
  • I want to put the image at z=0, so can I make z be an array of 0's? If so, and it needs to be the same size as x and y, can I write: z = np.zeros(size(x))? – user2569840 Jul 10 '13 at 22:15
  • Have a look at the API documentation: http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#mpl_toolkits.mplot3d.Axes3D.plot_surface Each argument is a 2D array providing the x, y, or z coordinate of a grid of points. – Luke Jul 10 '13 at 22:28
  • @user2569840 That is the right idea, but it should be `z = np.zeros(x.shape)` – tacaswell Jul 10 '13 at 22:52
0

You're not loading your image correctly - read_png() need a file object as its input, not a file path. Try this:

 f = open('milkyway.png','r')
 img = read_png(f)
ali_m
  • 71,714
  • 23
  • 223
  • 298
  • OK, what does `img` look like? Is it definitely a rows x cols x RGB(A) array? Can you just `imshow` it? – ali_m Jul 10 '13 at 22:25
  • Yes, imshow displays it nicely. The trick now is getting it into a 3D plot. – user2569840 Jul 10 '13 at 22:33
  • Now `x` and `y` just need to be 2D arrays of the same shape as the image. In my version of matplotlib (1.2.1), `plot_surface` seems to accept an integer argument for `z`, but if that doesn't work you should also try handing it an array of the same shape as `x` and `y`: `z = np.zeros_like(x)`. – ali_m Jul 10 '13 at 22:41