Matplotlib RectangleSelector исчезает, когда новое изображение загружается в панель wx Python - PullRequest
2 голосов
/ 16 января 2020

У меня есть изображение на панели wx Python, которое я хочу отредактировать, выбрав с помощью Matplotlib RectangleSelector. У меня есть Image_Viewer класс, который др aws изображение. У меня есть класс 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()

1 Ответ

3 голосов
/ 16 января 2020

Я не могу протестировать ваш код, потому что у меня не установлен wx, но я почти уверен, что ваша проблема связана с тем, что вы создаете новую фигуру и новый холст каждый раз, когда загружаете новую картинку.

I Верьте, вы должны создать одну фигуру и один набор осей, а затем заменить содержимое этих осей на новую картинку вместо

например

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