2

我在 wxPython 面板中有一个图像,我想通过选择 Matplotlib 来编辑它RectangleSelector。我有一个Image_Viewer绘制图像的类。我有一个Editor类,RectangleSelector功能所在的位置。Editor继承自Image_Viewer。最后,控制面板包含文件选择器按钮。该程序从通过Image_Viewer绘图函数加载的默认图像开始。我可以RectangleSelector很好地使用。但是当我加载一个新图像时,它也通过Image_Viewer绘图功能加载,所有连接都RectangleSelector消失了。

我试图尽可能地减少代码,但整个代码是多标签笔记本的一部分,因此存在wx.lib.agw.aui其他可能的特质。

import os
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
import wx
import wx.lib.agw.aui as aui
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.widgets import RectangleSelector
from matplotlib.patches import Rectangle

# ------------------variables-------------------
# Base path
pth = os.path.dirname(os.path.abspath('__file__'))
# folder for gui graphics
gui_graphics = pth + '/gui_graphics'
# temp file for initial image handling
img_pth = os.path.join(pth, "tmp_img.png")
# Folders, subfolders for processed images
all_cats = pth + '/Cats'
new_cats = all_cats + '/new_cats'

min_img_wndw = 295      # min size of top panels
img_y, img_x = 64, 64   # raw cat size

class Image_Viewer(wx.Panel):
    def __init__(self, parent):
        super(Image_Viewer, self).__init__(parent)
        #load image
        im_pth = new_cats + '/av_cat'
        files = os.listdir(im_pth)
        im_pths = [os.path.join(im_pth, im_name) for im_name in files]
        try:
            self.img = max(im_pths, key=os.path.getctime)
            self.image = cv.imread(self.img)
        except:
            self.image = np.zeros((img_x, img_y), np.uint8)

        self.figure = Figure()
        self.draw(self.image)

    def draw(self, image):
        plt.close(self.figure)
        self.figure.clf()
        self.axes = self.figure.add_axes([0, 0, 1, 1])
        self.axes.axis('off')
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.EXPAND)
        self.SetSizer(self.sizer)
        self.axes.imshow(image, cmap='gray', vmin=0, vmax=255)
        self.canvas.draw()

class Editor(Image_Viewer):
    def __init__(self, parent):
        super(Editor, self).__init__(parent)

        self.RS = RectangleSelector(self.axes, self.on_click,
                                    drawtype='box', useblit=True,
                                    button=[1, 3],  # don't use middle button
                                    minspanx=5, minspany=5,
                                    spancoords='pixels',
                                    interactive=True)
        #self.canvas.draw()
        cid = self.canvas.mpl_connect('MouseEvent', self.on_click)
        print(cid)

    def on_click(self, eclick, erelease):
        print("You clicked")
        'eclick and erelease are the press and release events'
        x1, y1 = eclick.xdata, eclick.ydata
        x2, y2 = erelease.xdata, erelease.ydata
        w = int(x2-x1)
        h = int(y2 - y1)

class control_Panel(wx.Panel):
    def __init__(self, parent, image_panel):     #, image_panel, terminal_panel
        wx.Panel.__init__(self, parent=parent)
        #self.panel = wx.Panel(self, -1, size=(580, 180))
        self.screen = image_panel

        self.pth = os.path.dirname(os.path.abspath('__file__'))
        fileDlgBtn = wx.Button(self, label="Get Cats")
        fileDlgBtn.Bind(wx.EVT_BUTTON, self.OnOpen)

    def OnOpen(self, event):
        with wx.FileDialog(self, "Open image file", wildcard="PNG files (*.png)|*.png",
                           style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:

            if fileDialog.ShowModal() == wx.ID_CANCEL:
                return     # the user changed their mind

            # Proceed loading the file chosen by the user
            pathname = fileDialog.GetPath()
            image = cv.imread(pathname)
            self.screen.draw(image)

class explorer_panel(wx.Panel):
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)
        bSplitter = wx.SplitterWindow(self)
        image_panel = Editor(bSplitter)
        panelThree = control_Panel(bSplitter, image_panel)  

        bSplitter.SplitHorizontally(image_panel, panelThree)
        bSplitter.SetSashGravity(0.5)

        bSplitter.SetMinimumPaneSize(min_img_wndw)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(bSplitter, 1, wx.EXPAND)
        self.SetSizer(sizer)

class Main(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(
            self, 
            parent = None, 
            title = "Borges Infinite Image", 
            size = (600,550)
            )
        self.SetIcon(wx.Icon(gui_graphics + '/Abe.png'))

        panel = wx.Panel(self)
        notebook = aui.AuiNotebook(panel)
        explorer = explorer_panel(notebook)
        notebook.AddPage(explorer, 'Explorer')
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(notebook, 1, wx.ALL|wx.EXPAND, 5)
        panel.SetSizer(sizer)

if __name__ == "__main__":
    app = wx.App()
    frame = Main()
    frame.Show()
    app.MainLoop()
4

1 回答 1

3

我无法测试您的代码,因为我没有安装 wx atm,但我很确定您的问题源于您每次加载新图片时创建一个新图形和新画布。

我相信你应该创建一个图和一组轴,然后用新图片替换这个轴的内容

例如

class Image_Viewer(wx.Panel):
    def __init__(self, parent):
        (...)

        self.figure = Figure()
        self.axes = self.figure.add_axes([0, 0, 1, 1])
        self.axes.axis('off')
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.EXPAND)
        self.SetSizer(self.sizer)
        self.draw(self.image)

    def draw(self, image):
       self.axes.cla()
       self.axes.imshow(image, cmap='gray', vmin=0, vmax=255)
       self.canvas.draw()
于 2020-01-16T09:11:59.113 回答