我是一名新的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()
答案 0 :(得分:3)
对您的问题的简短回答是使用numpy.delete
。 E.g。
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数组必须在内存中连续。因此,每次都会创建一个新副本(并删除旧副本)。这将相对较慢,并且需要您拥有存储阵列所需的两倍可用内存空间。
在您的情况下,为什么不存储2D数组的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()