大图像堆栈处理后,matplotlib wxPython后端崩溃

在处理大型图像堆栈时,我陷入了wxAssertionError问题(如下所示)。让我举例说明。

我已经使用只有面板,按钮和量规的wxPython制作了一个界面。

用户单击按钮后,代码将读取一堆8位二进制图像(1500 x 100 x 50),在面板上显示第一张图像并开始处理该堆栈。处理步骤意味着一个循环,在该循环中,将来自堆栈的每个图像标记并绘制在图中(不在面板中)。该图将保存并在每次迭代中关闭。代码如下所示:

# Label and save big image stack
import wx
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
class CanvasPanelA1(wx.Panel):
    def __init__(self,parent,ID):
        wx.Panel.__init__(self,ID,style=wx.SUNKEN_BORDER)

        self.figure = Figure()
        self.figure.set_facecolor("BLACK")
        self.canvas = FigureCanvas(self,-1,self.figure)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas,1,wx.LEFT | wx.TOP | wx.EXPAND)
        self.SetSizer(self.sizer)
        self.Fit()

    def OnPlot(self,event):
        self.frame = frame
        from numpy import amin,amax
        self.vmin = amin(frame.video)
        self.vmax = amax(frame.video)
        self.nframes = frame.video.shape[0]
        self.axes = self.figure.add_subplot(111)
        self.axes.imshow(frame.video[0],cmap='gray',vmin=self.vmin,vmax=self.vmax)
        self.axes.axis('off')
        self.canvas.draw()
        self.SetSizer(self.sizer)
        frame.Layout()

class MyFrame(wx.Frame):
    def __init__(self,title):
        wx.Frame.__init__(self,title)
        self.panel = CanvasPanelA1(self,wx.ID_ANY)
        self.panel.SetMinSize((200,200))
        self.button_RUN = wx.Button(self,label="Run")
        self.gauge = wx.Gauge(self,range = 100,size = (250,25),style = wx.GA_HORIZONTAL)
        mainSizer = wx.BoxSizer(wx.VERTICAL)
        mainSizer.Add(self.panel,3,wx.EXPAND)

        mainSizer.Add(self.button_RUN,flag=wx.CENTER|wx.ALL)
        mainSizer.Add(self.gauge,flag=wx.CENTER|wx.EXPAND)
        self.button_RUN.Bind(wx.EVT_BUTTON,self.OnRun)
        self.SetSizer(mainSizer)
        self.SetautoLayout(True)
        self.Layout()
    def OnRun(self,event):
        from skimage.color import label2rgb 
        from skimage.measure import label
        import matplotlib as mpl
        import matplotlib.pyplot as plt
        from skimage import io
        from skimage.util import img_as_ubyte

        #read video
        video_name = './video1.tif'
        self.video = io.imread(video_name,as_gray=False,plugin='tifffile')
        self.video = img_as_ubyte(self.video)
        self.nframes = self.video.shape[0]
        self.gauge.SetRange(self.nframes-1)

        #show one image on panel
        self.panel.OnPlot(wx.EVT_DISPLAY_CHANGED)
        self.panel.Refresh()

        plt.ioff()
        for fr in range(self.nframes):
            print('frame=',fr)
            label_image = label(self.video[fr],background=0) 
            image_label_overlay = label2rgb(label_image,bg_label=0)
            fig,ax = plt.subplots(figsize=(10,6))
            ax.imshow(image_label_overlay)
            plt.axis('off')
            imname = 'imgout'+str(fr).zfill(len(str(self.nframes)))+'.tif'
            output_path = './Outputs/'+imname
            plt.savefig(output_path,bbox_inches='tight',facecolor='black',edgecolor='none')
            plt.close(fig)
            self.gauge.Setvalue(fr)
        plt.ion()

app = wx.App()
frame = MyFrame(None,"Label videos")
frame.Show()
app.MainLoop()  

到目前为止,此代码在较小的堆栈上仍然有效,但是一旦我提供的图像堆栈大于〜1250帧,就会出现以下错误:

File "C:\Users\...\lib\site-packages\matplotlib\backends\backend_wx.py",line 1413,in _init_toolbar    
self.Realize()    
**wxAssertionError**: C++ assertion "Assert failure" failed at ..\..\src\msw\toolbar.cpp(938) in wxToolBar::Realize(): Could not add bitmap to toolbar

由于此错误似乎与工具栏有关,因此我不使用它,因此我尝试使用mpl.rcParams['toolbar'] = 'None'来禁用它,并将其放在循环之前,但是随后出现另一个AssertionError:

File "C:\Users\...\lib\site-packages\matplotlib\backends\backend_wx.py",line 1585,in __init__
self.setfieldsCount(2)
**wxAssertionError**: C++ assertion "m_hdc" failed at ..\..\src\msw\textmeasure.cpp(64) in wxTextMeasure::Beginmeasuring(): Must not be used with non-native wxDCs

我还尝试使用wx.CallAfter(self.gauge.Setvalue,fr)来避免在绘制和保存图像时更新主界面,但是效果不佳。

有人知道是什么原因造成的吗?

以下是我的软件包版本:
康达4.4.1
python 3.6.8
wxPython 4.0.6
间谍3.3.6
scikit-image 0.15.0
matplotlib 3.1.1
numpy 1.16.4

zzzz1287 回答:大图像堆栈处理后,matplotlib wxPython后端崩溃

距离我发布此问题已经4个月了,显然没有人知道答案。

我想说的是,在处理大量数据时,matplotlib wxpython后端存在一些错误。

,

好的,我想我根据this answer解决了类似的问题。 看起来,即使在循环内关闭了该图,也不应在循环内创建一个新图。每次循环迭代后,我的RAM都在增加,而与关闭每个新图无关。

解决方案:在循环之前创建图形实例。然后,在循环内绘制(如果需要,可以保存),而不是关闭图形,只需用plt.clf()将其清除即可。如下例所示,仅在循环后关闭图形:

fig,ax = plt.subplots(figsize=(10,6)) #create figure and axes
for fr in range(self.nframes):
    print('frame=',fr)
    label_image = label(self.video[fr],background=0) #some processing
    image_label_overlay = label2rgb(label_image,bg_label=0)   
    ax.imshow(image_label_overlay) #plot the image
    plt.axis('off')
    imname = 'imgout'+str(fr).zfill(len(str(self.nframes)))+'.tif'  
    output_path = os.path.join('.',dirname,imname)
    plt.savefig(output_path,bbox_inches='tight',facecolor='black',edgecolor='none') #save the figure
    self.gauge.SetValue(fr) #update gauge bar
    plt.clf() #clear current figure
plt.close(fig) #closes figure
本文链接:https://www.f2er.com/3012755.html

大家都在问