首页 > 解决方案 > 如何在 Python 中将图像正确显示为带有步进转换的 3D 图?

问题描述

我试图在 3D 中可视化图像之间的差异,以便更容易地区分正负差异。

我已经成功绘制了图像的基本图,但是,值之间matplotlib是插值。我需要这些是像素之间的阶跃变化。

我经常使用分辨率非常低的图像进行测试,例如 16 x 16,因此插值效果很大。

16 x 16 图像的 Numpy 文件: https ://wetransfer.com/downloads/c916f76e0d86a61c00c2ed4cfe4ae97520190210192200/60d87c

解决此问题的一种方法是重复这些值,但这似乎非常低效,并且需要在之后清理刻度。

在此处输入图像描述

生成上图的代码:

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

SubIm = np.load("Subtract_Image.npy")

def ImPlot2D3D(img, cmap=plt.cm.jet):

    Z = img[::1, ::1]

    fig = plt.figure(figsize=(14, 7))

    # 2D Plot
    ax1 = fig.add_subplot(1, 2, 1)
    im = ax1.imshow(Z, cmap=cmap)
    ax1.set_title('2D')
    ax1.grid(False)

    # 3D Plot
    ax2 = fig.add_subplot(1, 2, 2, projection='3d')
    X, Y = np.mgrid[:Z.shape[0], :Z.shape[1]]
    ax2.plot_surface(X, Y, Z, cmap=cmap)
    ax2.set_title('3D')

    plt.show()


ImPlot2D3D(SubIm)

我研究了 3D 条形图,但它们都使用分箱方案,我无法让它适用于图像。

标签: pythonimagematplotlibplot

解决方案


最终设法回答了我自己的问题。

解决此问题的蛮力方法是重复数组中的值,从而使“matplotlib”所做的值之间的插值影响更小,并且更好地逼近阶跃变化。这可以使用numpy.repeat来实现。由于这是一个 3D 数组,我们必须在一个轴上进行迭代,而不是在另一个轴上进行迭代。否则,数组将被重复展平并返回此平面数组。

结果: 结果:

def ImPlot2D3D(img, cmap=plt.cm.jet, step=False, ratio=10):

    if step:
        img = (img.repeat(ratio, axis=0)).repeat(ratio, axis=1)

    Z = img[::1, ::1]

    fig = plt.figure(figsize=(14, 7))

    # 2D Plot
    ax1 = fig.add_subplot(1, 2, 1)
    im = ax1.imshow(Z, cmap=cmap)
    ax1.set_title('2D')
    ax1.grid(False)

    # 3D Plot
    ax2 = fig.add_subplot(1, 2, 2, projection='3d')
    X, Y = np.mgrid[:Z.shape[0], :Z.shape[1]]
    ax2.plot_surface(X, Y, Z, cmap=cmap)
    ax2.set_title('3D')

    # Scale the ticks back down to original values
    if step:
        ticks_x = ticker.FuncFormatter(lambda x, pos: '{0:g}'.format(x / ratio))
        ticks_y = ticker.FuncFormatter(lambda y, pos: '{0:g}'.format(y / ratio))
        ax1.xaxis.set_major_formatter(ticks_x)
        ax1.yaxis.set_major_formatter(ticks_y)
        ax2.xaxis.set_major_formatter(ticks_x)
        ax2.yaxis.set_major_formatter(ticks_y)

    plt.show()

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

SubIm = np.load("Subtract_Image.npy")
ImPlot2D3D(SubIm, step=True)

推荐阅读