简体   繁体   English

在 Python 中在 3D 绘图上绘制 2D 图片

[英]Plotting 2D picture on 3D plot in Python

I would like to present some 3D spatial data with Python, but with the geometry of the setup plotted for each direction.我想用 Python 呈现一些 3D 空间数据,但要为每个方向绘制设置的几何图形。 So for the XY plane, I would have at z=0 the view from above, same for XZ and YZ.所以对于 XY 平面,我会在 z=0 处看到上面的视图,对于 XZ 和 YZ 相同。

I saw that other posts asked a similar question, but here, the data would not be coordinates and colors, but rather a real picture.我看到其他帖子问过类似的问题,但是这里的数据不是坐标和颜色,而是真实的图片。

My idea, based on other posts was the following:根据其他帖子,我的想法如下:

import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
import numpy as np
import matplotlib.image as mpimg

fig = plt.figure()
fig.add_subplot(111, projection="3d")

# 3D data
X = np.random.uniform(0,100,100)
Y = np.random.uniform(0,100,100)
Z = np.random.uniform(0,100,100)
values = np.random(100)
# XY
img = mpimg.imread('/home/geometryXY')
imgplot = plt.imshow(img, zdir='x', aspect='auto')
# XZ
img = mpimg.imread('/home/geometryXZ')
imgplot = plt.imshow(img, zdir='y', aspect='auto')
# YZ
img = mpimg.imread('/home/geometryYZ')
imgplot = plt.imshow(img, zdir='z', aspect='auto')
plt.show()

Any image file would work.任何图像文件都可以。 Indeed, for now, what interests me is to see if we can put a 2D image on a 3D axis and overlap a 3D plot on it.事实上,就目前而言,我感兴趣的是看看我们是否可以将 2D 图像放在 3D 轴上并在其上重叠 3D 图。

At least the idea would be that.至少想法是这样的。 However, the 'zdir' option does not seem to exist.但是,'zdir' 选项似乎不存在。 Would you have any tip?你有什么小费吗?

Thanks谢谢

EDIT:编辑:

Based on blunova's answer, I changed several things.根据 blunova 的回答,我改变了几件事。 First I added where I want to see the plot with the val argument, and scaling parameters for each axis xlim and ylim .首先,我使用val参数添加了我想查看绘图的位置,以及每个轴xlimylim的缩放参数。 To make it work, for some reason, I also had to swap the x and y axes of the imread object and to flip the y axis.为了使它工作,出于某种原因,我还必须交换imread对象的 x 和 y 轴并翻转 y 轴。

Several problems are still here.几个问题仍然存在。

The first one is that the process is very slow.第一个是过程非常缓慢。 Showing the 2D picture with imshow would take less few seconds (images are 3000*5000 pixels large), but here I stopped the function after few minutes because it was too slow.使用imshow显示 2D 图片将花费更少的几秒钟(图像大小为 3000*5000 像素),但在这里我在几分钟后停止了该功能,因为它太慢了。 I therefore changed the rstride and cstride , and mutliplied them by 15, which is huge (does it mean I reduce my quality by 15^2?) just to make it barely ok (2 minutes to plot 3 images).因此,我更改了rstridecstride ,并将它们乘以 15,这是巨大的(这是否意味着我将质量降低了 15^2?)只是为了让它几乎没问题(绘制 3 张图像需要 2 分钟)。 What I don't understand why there is such a difference between the normal imshow and the plot_surface routines.我不明白为什么正常的imshowplot_surface例程之间存在如此差异。

The second is that the images "cut" the 3D data in foreground, even though I added the 3D plot afterwards, and even if the zorder for the images is set to -1000.第二个是图像“剪切”了前景中的 3D 数据,即使我随后添加了 3D 图,即使图像的zorder设置为 -1000。 The 3D data should show a full cylinder, and no value is lower than the -144 value shown in the code. 3D 数据应该显示一个完整的圆柱体,并且没有任何值低于代码中显示的 -144 值。

There also seems to be a problem with the lighting which is strange.灯光似乎也有问题,这很奇怪。

For your reference, here is the current state of this plot.供您参考,这是该图的当前状态。

def plot_image(ax, image, axis, xlim, ylim, val, rstride=15, cstride=15):
    array = plt.imread(image)
    array = np.swapaxes(array, 0, 1)
    array = np.flip(array, 1)
    step_x, step_y = np.diff(xlim) / array.shape[0], np.diff(ylim) / array.shape[1]
    x_1 = np.arange(xlim[0], xlim[1], step_x)
    y_1 = np.arange(ylim[0], ylim[1], step_y)
    y_1, x_1 = np.meshgrid(y_1, x_1)
    vals = np.ones((array.shape[0], array.shape[1]))*val
    if axis == "x":
        ax.plot_surface(vals, x_1, y_1, rstride=rstride, cstride=cstride, facecolors=array, zorder=-1000)
    elif axis == "y":
        ax.plot_surface(x_1, vals, y_1, rstride=rstride, cstride=cstride, facecolors=array, zorder=-1000)
    elif axis == "z":
        ax.plot_surface(x_1, y_1, vals, rstride=rstride, cstride=cstride, facecolors=array,zorder=-1000)

fig = plt.figure(figsize=(10,15))
fig.add_subplot(111, projection="3d")

# Plot geometry in background
plot_image(plt.gca(), '/home/yryves/serpent_cases/domain_decomposition_dvlpt/test_stl2/Plots/input_geom1_bu1.png','x', xlim=[-144,144], ylim=[0,487.528], val=-144)
plot_image(plt.gca(), '/home/yryves/serpent_cases/domain_decomposition_dvlpt/test_stl2/Plots/input_geom2_bu1.png','y', xlim=[-144,144], ylim=[0,487.528], val=144)
plot_image(plt.gca(), '/home/yryves/serpent_cases/domain_decomposition_dvlpt/test_stl2/Plots/input_geom3_bu1.png','z', xlim=[-144,144], ylim=[-144,144], val=0)

# 3D data plot
pbed.plot3D('z', new_fig=False)

plt.savefig('geometry.png')

当前几何

Based on this answer , I came up with the following solution.基于这个答案,我想出了以下解决方案。 I have used three cryptopunks images centered at the origin and lying in the x=0 , y=0 and z=0 planes.我使用了三个以原点为中心并位于x=0y=0z=0平面上的密码朋克图像。


import matplotlib.pyplot as plt
import numpy as np


def main():
    fig = plt.figure()
    ax = fig.add_subplot(projection='3d')

    x = np.random.uniform(-5, 5, 100)
    y = np.random.uniform(-5, 5, 100)
    z = np.random.uniform(-5, 5, 100)
    ax.scatter(x, y, z)

    plot_image(ax, "1.png", "x")
    plot_image(ax, "2.png", "y")
    plot_image(ax, "3.png", "z")

    plt.show()


def plot_image(ax, image, axis):

    array = plt.imread(image)
    step_x, step_y = 10. / array.shape[0], 10. / array.shape[1]

    x_1 = np.arange(-5, 5, step_x)
    y_1 = np.arange(-5, 5, step_y)
    x_1, y_1 = np.meshgrid(x_1, y_1)

    zeros = np.zeros((array.shape[0], array.shape[1]))

    rstride = 1
    cstride = 1
    if axis == "x":
        ax.plot_surface(
            zeros, x_1, y_1, rstride=rstride, cstride=cstride, facecolors=array
        )
    elif axis == "y":
        ax.plot_surface(
            x_1, zeros, y_1, rstride=rstride, cstride=cstride, facecolors=array
        )
    elif axis == "z":
        ax.plot_surface(
            x_1, y_1, zeros, rstride=rstride, cstride=cstride, facecolors=array
        )


if __name__ == "__main__":
    main()

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM