英文:
More efficent way of plotting image on 3D plane in matplotlib than using a meshgrid
问题
有没有比这个更好的方法在matplotlib中绘制带有图像的3D平面:
xx, yy = np.meshgrid(np.linspace(0, 1, img_size[1]), np.linspace(0, 1, img_size[0]))
zz = np.ones((img_size[0],img_size[1]))
ax.plot_surface(xx, yy, zz, rstride=1, cstride=1, facecolors=img / 255, shade=False)
我不想创建与像素数量相同的面,因为这相当低效。是否有更好的方法?
这是我的绘图效果:
英文:
Is there a better way to plot a plane with image in 3D in matplotlib than this:
xx, yy = np.meshgrid(np.linspace(0, 1, img_size[1]), np.linspace(0, 1, img_size[0]))
zz = np.ones((img_size[0],img_size[1]))
ax.plot_surface(xx, yy, zz, rstride=1, cstride=1, facecolors=img / 255, shade=False)
I dont want to create a surface with as many faces as I have pixels, since that quite inefficient.
Is there a better way to do so?
This is what my plot looks like:
答案1
得分: 2
一个简单的一行方法是按如下方式进行子采样:img_smaller = img[::10, ::10, :]
。这将使图像缩小10倍,但由于未应用插值,图像会看起来粗糙,如果尺寸不是10的倍数,则边缘可能会被剪切:
在降采样之前:
使用数组切片进行降采样:
另一种方法是在使用PIL
加载图像后进行降采样。设置downsample=12
,即12倍降采样:
PIL
降采样:
from PIL import Image
#加载图像,或者创建一个测试图像
np.random.seed(0)
img = Image.fromarray( np.random.randint(0, 255, size=(100, 100, 3), dtype=np.ubyte))
img = Image.open('.. /image.png')
#进行12倍子采样并应用插值
downsample = 12
img_small = img.resize((img.height // downsample, img.width // downsample),
resample=Image.BICUBIC)
h, w = img_small.height, img_small.width
img_small_arr = np.asarray(img_small)
#绘图
ax = plt.figure(figsize=(3, 3)).add_subplot(projection='3d')
xx, yy = np.meshgrid(np.linspace(0, 1, w), np.linspace(0, 1, h))
zz = np.ones((h, w))
ax.plot_surface(xx, yy, zz, facecolors=img_small_arr / 255, shade=False)
#facecolor=[0,0,0,0], linewidth=1) #可选添加'grid'效果
使用切片的一行方法:
#使用切片进行降采样
img_small_arr = np.asarray(img)[::10, ::10, :]
#新尺寸
h, w, _ = img_small_arr.shape
#其余绘图部分与之前相同
ax = plt.figure(figsize=(3, 3)).add_subplot(projection='3d')
xx, yy = np.meshgrid(np.linspace(0, 1, w), np.linspace(0, 1, h))
zz = np.ones((h, w))
ax.plot_surface(xx, yy, zz, facecolors=img_small_arr / 255, shade=False)
英文:
A simple one-liner method is to subsample as follows: img_smaller = img[::10, ::10, :]
. This will subsample it down 10x, but the image will look coarse as no interpolation was applied, and edges may look clipped if the dimensions aren't multiples of 10:
Before downsampling:
Downsampling using array slicing:
Another approach is to downsample the image after loading it using PIL
. After setting downsample=12
, i.e. 12x downsampling:
PIL
downsampling:
from PIL import Image
#Load image, or make a test image
np.random.seed(0)
img = Image.fromarray( np.random.randint(0, 255, size=(100, 100, 3), dtype=np.ubyte))
img = Image.open('../image.png')
#Subsample 12x and apply interpolation
downsample = 12
img_small = img.resize((img.height // downsample, img.width // downsample),
resample=Image.BICUBIC)
h, w = img_small.height, img_small.width
img_small_arr = np.asarray(img_small)
#Plot
ax = plt.figure(figsize=(3, 3)).add_subplot(projection='3d')
xx, yy = np.meshgrid(np.linspace(0, 1, w), np.linspace(0, 1, h))
zz = np.ones((h, w))
ax.plot_surface(xx, yy, zz, facecolors=img_small_arr / 255, shade=False)
#facecolor=[0,0,0,0], linewidth=1) #optionally add a 'grid' effect
One-liner method using slicing:
#Downsample using slicing
img_small_arr = np.asarray(img)[::10, ::10, :]
#New dimensions
h, w, _ = img_small_arr.shape
#Rest of the plotting, as before
ax = plt.figure(figsize=(3, 3)).add_subplot(projection='3d')
xx, yy = np.meshgrid(np.linspace(0, 1, w), np.linspace(0, 1, h))
zz = np.ones((h, w))
ax.plot_surface(xx, yy, zz, facecolors=img_small_arr / 255, shade=False)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论