[英]How to correctly display an image as a 3D plot with step transitions in Python?
I am trying to visualize differences between images in 3D, in order to more easily differentiate between positive and negative differences. 我试图想象三维图像之间的差异,以便更容易区分正面和负面的差异。
I have succeeded with a basic plot of an image, however, between the values matplotlib
is interpolating values. 我已经成功完成了图像的基本绘图,但是,值matplotlib
是插值之间的值。 I need these to be step changes between pixels. 我需要这些是像素之间的步骤变化。
I am often testing with very low-resolution images, for example, 16 by 16, so the interpolation has a large effect. 我经常使用非常低分辨率的图像进行测试,例如16乘16,因此插值效果很好。
Numpy file of 16 by 16 image: https://wetransfer.com/downloads/c916f76e0d86a61c00c2ed4cfe4ae97520190210192200/60d87c Numpy文件16 x 16图像: https : //wetransfer.com/downloads/c916f76e0d86a61c00c2ed4cfe4ae97520190210192200/60d87c
One way to solve this would be to repeat the values however, this seems very inefficient and requires cleaning up the ticks after. 解决这个问题的一种方法是重复这些值,但这似乎非常低效,需要清理后的滴答声。
Code to generate above image: 生成上图的代码:
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)
I've looked into 3D bar charts but they all use binning schemes and I can't make it work for an image. 我已经研究过3D条形图,但它们都使用分级方案,我无法使其适用于图像。
Eventually managed to answer my own question. 最终设法回答了我自己的问题。
A brute force method to solve this is to repeat the values in the array, hence making the interpolation between values that 'matplotlib' does, less impactful and better approximating a step change. 解决这个问题的强力方法是重复数组中的值,从而在'matplotlib'的值之间进行插值,减少影响并更好地逼近阶跃变化。 This can be achieved using numpy.repeat . 这可以使用numpy.repeat来实现。 As this is a 3D array we must iterate over one axis than the other. 由于这是一个3D数组,我们必须迭代一个轴而不是另一个轴。 Otherwise, the array will be flattened repeated and this flat array returned. 否则,阵列将被重复展平并返回此平面阵列。
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.