使用 matplotlib 滚动重叠 3D 图像的 2D 切片
Using matplotlib to scroll through 2D slices of overlapping 3D images
我有这段代码非常适合滚动 3D numpy 数组的 2D 切片。
import matplotlib.pyplot as plt
import numpy as np
class IndexTracker(object):
def __init__(self, ax, X):
self.ax = ax
ax.set_title('use scroll wheel to navigate images')
self.X = X
rows, cols, self.slices = X.shape
self.ind = self.slices // 2
self.im = ax.imshow(self.X[:, :, self.ind], cmap="gray")
self.update()
def onscroll(self, event):
print("%s %s" % (event.button, event.step))
if event.button == 'up':
self.ind = (self.ind + 1) % self.slices
else:
self.ind = (self.ind - 1) % self.slices
self.update()
def update(self):
self.im.set_data(self.X[:, :, self.ind])
self.ax.set_ylabel('slice %s' % self.ind)
self.im.axes.figure.canvas.draw()
def plot3d(image):
fig, ax = plt.subplots(1, 1)
tracker = IndexTracker(ax, image)
fig.canvas.mpl_connect('scroll_event', tracker.onscroll)
plt.show()
if __name__ == "__main__":
img = np.array([[[0, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 0, 0], [1, 1, 1], [0, 0, 0]],
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]])
plot3d(img)
我想拥有相同的功能,但同时滚动浏览两个大小相同的 3D numpy 数组。其中一个阵列应以一定程度的不透明度和不同的配色方案显示,以便可以同时检查两个阵列。无需滚动,对于二维切片,这很容易实现:
img1 = np.array([[[0, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 0, 0], [1, 1, 1], [0, 0, 0]],
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]])
img2 = np.array([[[0, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 1, 0], [0, 1, 0], [0, 1, 0]],
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]])
plt.imshow(img1[:, :, 1], cmap="gray")
plt.imshow(img2[:, :, 1], cmap="jet", alpha=0.25)
plt.show()
我尝试扩展 IndexTracker class 以接受第二个 3D 数组并使用 imshow() 显示每个体积的一个切片(具有相同的索引)。此外,它旨在使用 set_data() 更新每个滚动事件中显示的图像。然而,这并没有成功。
import numpy as np
import matplotlib.pyplot as plt
class IndexTracker(object):
def __init__(self, ax, X, Y):
self.ax = ax
self.X = X
self.Y = Y
_, _, self.slices = X.shape
self.ind = self.slices // 2
self.im = ax.imshow(self.X[:, :, self.ind], cmap="gray")
self.im = ax.imshow(self.Y[:, :, self.ind], cmap="jet", alpha=0.25)
self.update()
def onscroll(self, event):
print("%s %s" % (event.button, event.step))
if event.button == 'up':
self.ind = (self.ind + 1) % self.slices
else:
self.ind = (self.ind - 1) % self.slices
self.update()
def update(self):
self.im.set_data(self.X[:, :, self.ind])
self.im.set_data(self.Y[:, :, self.ind])
self.ax.set_ylabel('slice %s' % self.ind)
self.im.axes.figure.canvas.draw()
def plot3d(image1, image2):
image1 = np.rot90(image1, k=-1)
image2 = np.rot90(image2, k=-1)
fig, ax = plt.subplots(1, 1)
tracker = IndexTracker(ax, image1, image2)
fig.canvas.mpl_connect('scroll_event', tracker.onscroll)
plt.show()
if __name__ == "__main__":
img1 = np.array([[[0, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 0, 0], [1, 1, 1], [0, 0, 0]],
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]])
img2 = np.array([[[0, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 1, 0], [0, 1, 0], [0, 1, 0]],
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]])
plot3d(img1, img2)
你知道如何使用 matplotlib 解决给定的问题吗?理想情况下,通过扩展包含 IndexTracker class.
的第一个代码片段
编辑:
添加第二个图像作为 plot3d() 调用的参数
幸运的是,如果您分别跟踪两个 Axes.imshow
对象(由 plt.imshow
返回),那么 matplotlib 将为您处理图像的分层。然后,您可以对每个单独使用 set_data。这样做时,您需要为每个图像保持相同的颜色图和 alpha 值,您可以使用 im.to_rgba
和 im.get_alpha
的组合来完成此操作。以下是您需要对 class 进行的修改,以实现此目的:
class IndexTracker(object):
def __init__(self, ax, X, Y):
...
self.im1 = ax.imshow(self.X[:, :, self.ind], cmap="gray")
self.im2 = ax.imshow(self.Y[:, :, self.ind], cmap="jet", alpha=.25)
...
def update(self):
im1_data = self.im1.to_rgba(self.X[:, :, self.ind], alpha=self.im1.get_alpha())
im2_data = self.im2.to_rgba(self.Y[:, :, self.ind], alpha=self.im2.get_alpha())
self.im1.set_data(im1_data)
self.im2.set_data(im2_data)
...
我有这段代码非常适合滚动 3D numpy 数组的 2D 切片。
import matplotlib.pyplot as plt
import numpy as np
class IndexTracker(object):
def __init__(self, ax, X):
self.ax = ax
ax.set_title('use scroll wheel to navigate images')
self.X = X
rows, cols, self.slices = X.shape
self.ind = self.slices // 2
self.im = ax.imshow(self.X[:, :, self.ind], cmap="gray")
self.update()
def onscroll(self, event):
print("%s %s" % (event.button, event.step))
if event.button == 'up':
self.ind = (self.ind + 1) % self.slices
else:
self.ind = (self.ind - 1) % self.slices
self.update()
def update(self):
self.im.set_data(self.X[:, :, self.ind])
self.ax.set_ylabel('slice %s' % self.ind)
self.im.axes.figure.canvas.draw()
def plot3d(image):
fig, ax = plt.subplots(1, 1)
tracker = IndexTracker(ax, image)
fig.canvas.mpl_connect('scroll_event', tracker.onscroll)
plt.show()
if __name__ == "__main__":
img = np.array([[[0, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 0, 0], [1, 1, 1], [0, 0, 0]],
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]])
plot3d(img)
我想拥有相同的功能,但同时滚动浏览两个大小相同的 3D numpy 数组。其中一个阵列应以一定程度的不透明度和不同的配色方案显示,以便可以同时检查两个阵列。无需滚动,对于二维切片,这很容易实现:
img1 = np.array([[[0, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 0, 0], [1, 1, 1], [0, 0, 0]],
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]])
img2 = np.array([[[0, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 1, 0], [0, 1, 0], [0, 1, 0]],
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]])
plt.imshow(img1[:, :, 1], cmap="gray")
plt.imshow(img2[:, :, 1], cmap="jet", alpha=0.25)
plt.show()
我尝试扩展 IndexTracker class 以接受第二个 3D 数组并使用 imshow() 显示每个体积的一个切片(具有相同的索引)。此外,它旨在使用 set_data() 更新每个滚动事件中显示的图像。然而,这并没有成功。
import numpy as np
import matplotlib.pyplot as plt
class IndexTracker(object):
def __init__(self, ax, X, Y):
self.ax = ax
self.X = X
self.Y = Y
_, _, self.slices = X.shape
self.ind = self.slices // 2
self.im = ax.imshow(self.X[:, :, self.ind], cmap="gray")
self.im = ax.imshow(self.Y[:, :, self.ind], cmap="jet", alpha=0.25)
self.update()
def onscroll(self, event):
print("%s %s" % (event.button, event.step))
if event.button == 'up':
self.ind = (self.ind + 1) % self.slices
else:
self.ind = (self.ind - 1) % self.slices
self.update()
def update(self):
self.im.set_data(self.X[:, :, self.ind])
self.im.set_data(self.Y[:, :, self.ind])
self.ax.set_ylabel('slice %s' % self.ind)
self.im.axes.figure.canvas.draw()
def plot3d(image1, image2):
image1 = np.rot90(image1, k=-1)
image2 = np.rot90(image2, k=-1)
fig, ax = plt.subplots(1, 1)
tracker = IndexTracker(ax, image1, image2)
fig.canvas.mpl_connect('scroll_event', tracker.onscroll)
plt.show()
if __name__ == "__main__":
img1 = np.array([[[0, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 0, 0], [1, 1, 1], [0, 0, 0]],
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]])
img2 = np.array([[[0, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 1, 0], [0, 1, 0], [0, 1, 0]],
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]])
plot3d(img1, img2)
你知道如何使用 matplotlib 解决给定的问题吗?理想情况下,通过扩展包含 IndexTracker class.
的第一个代码片段编辑: 添加第二个图像作为 plot3d() 调用的参数
幸运的是,如果您分别跟踪两个 Axes.imshow
对象(由 plt.imshow
返回),那么 matplotlib 将为您处理图像的分层。然后,您可以对每个单独使用 set_data。这样做时,您需要为每个图像保持相同的颜色图和 alpha 值,您可以使用 im.to_rgba
和 im.get_alpha
的组合来完成此操作。以下是您需要对 class 进行的修改,以实现此目的:
class IndexTracker(object):
def __init__(self, ax, X, Y):
...
self.im1 = ax.imshow(self.X[:, :, self.ind], cmap="gray")
self.im2 = ax.imshow(self.Y[:, :, self.ind], cmap="jet", alpha=.25)
...
def update(self):
im1_data = self.im1.to_rgba(self.X[:, :, self.ind], alpha=self.im1.get_alpha())
im2_data = self.im2.to_rgba(self.Y[:, :, self.ind], alpha=self.im2.get_alpha())
self.im1.set_data(im1_data)
self.im2.set_data(im2_data)
...