2012-11-18 67 views
3

我是一個新的Python用戶,並且想要進行一些簡單的圖像處理。基本上我會有一個動態的醫學圖像 - 一系列不同時間點的2D圖像,我想將它們存儲爲一個3D數組。由於掃描技術的性質,在某些成像幀期間可能偶爾出現患者運動,這使得數據不可用。我想刪除這些幀並重新編排陣列 - 新尺寸(n-1,256,256)。刪除該幀後,我想更新圖像顯示。什麼是實現這一目標的最佳途徑?這裏是我到目前爲止的骨架代碼:從3D數組中刪除圖像幀

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() 

回答

3

您的問題的簡短回答是使用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數組必須在內存中連續。因此,每次都會創建一個新的副本(並刪除舊的副本)。這會相對較慢,並且需要您有兩倍的可用內存空間來存儲陣列。

在你的情況,爲什麼不存儲一個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() 
+0

感謝您的幫助。二維數組列表聽起來像是一個明智的解決方案。 – moadeep