0

I'm trying to create a PyQt5 matplotlib widget which shows processed/annotated images as they are processed. The main project is a larger pyqt GUI for computer vision which has a separate thread for the image processing and emits signals containing the images.

However, I have not been able to get a MWE matplotlib canvas to display images (imshow) in a loop. I tried modifying various examples online that do this for plotting single lines but cannot replicate the functionality with images.

Using Matplotlib 3.7.2 and PyQt5.

I expect using pyqtgraph instead would also work but I'd prefer to keep matplotlib since this is not a critical feature.

My current minimal-not-working example is the following code from a line-plotting example here but modified to show images instead. The image display does not update but the terminal printout indicates the data should be changing every 500ms. Even clearing the canvas does not affect the display.

import sys
import random
import matplotlib
import numpy as np
matplotlib.use('Qt5Agg')

from PyQt5 import QtCore, QtWidgets

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure


class MplCanvas(FigureCanvas):

    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)
        super(MplCanvas, self).__init__(fig)

class MainWindow(QtWidgets.QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.canvas = MplCanvas(self, width=5, height=4, dpi=100)
        self.setCentralWidget(self.canvas)

        self.imgdata = np.ones((10,10))

        # We need to store a reference to the plot
        # somewhere, so we can apply the new data to it.
        self._plot_ref = None
        self.update_plot()

        self.show()

        # Setup a timer to trigger the redraw by calling update_plot.
        self.timer = QtCore.QTimer()
        self.timer.setInterval(500)
        self.timer.timeout.connect(self.update_plot)
        self.timer.start()

    def update_plot(self):
        # Create random images each call to update
        self.imgdata = np.ones((10,10))+ random.randint(0, 10)
        print(self.imgdata.sum())

        # Use references to plot to lower overhead
        if self._plot_ref is None:
            # First time we have no plot reference, so do a normal plot.
            # .plot returns a list of line <reference>s, as we're
            # only getting one we can take the first element.
            plot_refs = self.canvas.axes.imshow(self.imgdata)
            self._plot_ref = plot_refs
        else:
            # We have a reference, we can use it to update the data for that line.
            self._plot_ref.set_data(self.imgdata)

        # Trigger the canvas to update and redraw.
        self.canvas.draw()

app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
app.exec_()
Magnus
  • 1

0 Answers0