3

我是一个新的 Python 用户,想做一些简单的图像处理。本质上,我将拥有一个动态医学图像——在不同时间点的一系列 2D 图像,我想将其存储为 3D 数组。由于扫描技术的性质,在某些成像帧期间可能会偶尔出现患者运动,从而使数据无法使用。我想删除这样的帧并重铸数组 - 新维度(n-1、256、256)。删除框架后,我想更新图像显示。实现这一目标的最佳方法是什么?这是我到目前为止的骨架代码:

import dicom
import numpy as np
import pylab 
from matplotlib.widgets import Slider, Button

ds = dicom.read_file("/home/moadeep/Dropbox/FS1.dcm")
#data = ds.pixel_array
data = np.random.rand(16,256,256)
nframes = data.shape[0]

ax = pylab.subplot(111)
pylab.subplots_adjust(left=0.25, bottom=0.25)

frame = 0
l = pylab.imshow(data[frame,:,:]) #shows 1024x256 imagge, i.e. 0th frame*

axcolor = 'lightgoldenrodyellow'
axframe = pylab.axes([0.35, 0.1, 0.5, 0.03], axisbg=axcolor)

#add slider to scroll image frames
sframe = Slider(axframe, 'Frame', 0, nframes, valinit=0,valfmt='%1d'+'/'+str(nframes))

ax_delete = pylab.axes([0.8,0.025,0.1,0.04], axisbg=axcolor)

#add slider to scroll image frames

#Delete button to delete frame from data set
bDelete = Button(ax_delete, 'Delete')

def update(val):
    frame = np.around(sframe.val)
    pylab.subplot(111)
    pylab.subplots_adjust(left=0.25, bottom=0.25)
    pylab.imshow(data[frame,:,:])

sframe.on_changed(update)

pylab.gray()
pylab.show()
4

1 回答 1

4

您的问题的简短答案是 use numpy.delete。例如

import numpy as np
data = np.arange(1000).reshape((10,10,10))

# Delete the third slice along the first axis 
# (note that you can delete multiple slices at once)
data = np.delete(data, [2], axis=0)

print data.shape

但是,如果您要多次删除单个切片,这是一种糟糕的方法。

更长的答案是避免每次要删除切片时都这样做。

Numpy 数组在内存中必须是连续的。因此,这将每次制作一个新副本(并删除旧副本)。这将相对较慢,并且需要您有两倍的可用内存空间来存储数组。

在您的情况下,为什么不存储二维数组的 python 列表?这样你就可以毫无问题地弹出你不想要的切片。如果您之后需要它作为 3D 数组,只需使用numpy.dstack它来创建它。

当然,如果您需要进行 3D 处理,则需要 3D 数组。因此,另一种方法是存储“坏”索引列表并在最后使用删除它们numpy.delete(请注意,要删除的项目是一个列表,因此您可以传入“坏”索引列表)。


附带说明一下,您更新图像的方式将非常缓慢。

您正在创建大量图像,因此每次都会重新绘制每个图像,并且随着您的继续,更新将变得非常缓慢。

您最好设置图像的数据 ( im.set_data(next_slice)) 而不是每次都创建一个新图像。

更好的是,使用 blitting,但对于 matplotlib 中的图像数据,由于 matplotlib 对图像的缓慢重新缩放,它不如其他类型的绘图那么有利。

举个简单的例子:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider

def main():
    # Set up 3D coordinates from -10 to 10 over a 200x100x100 "open" grid
    x, y, z = np.ogrid[-10:10:200j, -10:10:100j, -10:10:100j]

    # Generate a cube of interesting data
    data= np.sin(x*y*z) / (x*y*z)

    # Visualize it
    viewer = VolumeViewer(data)
    viewer.show()

class VolumeViewer(object):
    def __init__(self, data):
        self.data = data
        self.nframes = self.data.shape[0]

        # Setup the axes.
        self.fig, self.ax = plt.subplots()
        self.slider_ax = self.fig.add_axes([0.2, 0.03, 0.65, 0.03])

        # Make the slider
        self.slider = Slider(self.slider_ax, 'Frame', 1, self.nframes, 
                            valinit=1, valfmt='%1d/{}'.format(self.nframes))
        self.slider.on_changed(self.update)

        # Plot the first slice of the image
        self.im = self.ax.imshow(data[0,:,:])

    def update(self, value):
        frame = int(np.round(value - 1))

        # Update the image data
        dat = self.data[frame,:,:]
        self.im.set_data(dat)

        # Reset the image scaling bounds (this may not be necessary for you)
        self.im.set_clim([dat.min(), dat.max()])

        # Redraw the plot
        self.fig.canvas.draw()

    def show(self):
        plt.show()

if __name__ == '__main__':
    main()
于 2012-11-18T17:56:01.957 回答