在Qt中显示matplotlib imshow输出 [英] show matplotlib imshow output in Qt

查看:418
本文介绍了在Qt中显示matplotlib imshow输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类型为np.float64的2D numpy数组,我想将其显示为QLabel中的图像(或任何其他有效方式):

I have a 2D numpy array of type np.float64, and I want to show it as an image in a QLabel (or any other valid way):

self.img = np.rot90(get_my_data()) # this line returns a 2D numpy array of type np.float64
self.qimg = QtGui.QImage(self.img, self.img.shape[0], self.img.shape[1], QtGui.QImage.Format_Grayscale8)
self.myLabel.setPixmap(QtGui.QPixmap(self.qimg))

我上面的代码返回以下错误:

My code above returning the following error:

TypeError: arguments did not match any overloaded call:
QImage(): too many arguments
QImage(QSize, QImage.Format): argument 1 has unexpected type 'numpy.ndarray'
QImage(int, int, QImage.Format): argument 1 has unexpected type 'numpy.ndarray'
QImage(bytes, int, int, QImage.Format): argument 1 has unexpected type 'numpy.ndarray'
QImage(sip.voidptr, int, int, QImage.Format): argument 1 has unexpected type 'numpy.ndarray'
QImage(bytes, int, int, int, QImage.Format): argument 1 has unexpected type 'numpy.ndarray'
QImage(sip.voidptr, int, int, int, QImage.Format): argument 1 has unexpected type 'numpy.ndarray'
QImage(List[str]): argument 1 has unexpected type 'numpy.ndarray'
QImage(str, format: str = None): argument 1 has unexpected type 'numpy.ndarray'
QImage(QImage): argument 1 has unexpected type 'numpy.ndarray'
QImage(Any): too many arguments

但是,如果我在第一行的末尾添加.copy(),那么它将起作用!但无法正确显示数据.

But, if I add .copy() at the end of the first line, then it works! but it doesn't display the data correctly.

self.img = np.rot90(get_my_data()).copy()
self.qimg = QtGui.QImage(self.img, self.img.shape[0], self.img.shape[1], QtGui.QImage.Format_Grayscale8)
self.myLabel.setPixmap(QtGui.QPixmap(self.qimg))

以下是与pyplot.imshow()相比标签显示的内容:

Here is what the label displays compared with pyplot.imshow():

self.img = 20 * np.log10(np.rot90(get_my_data()).copy())
self.qimg = QtGui.QImage(self.img, self.img.shape[0], self.img.shape[1], QtGui.QImage.Format_Grayscale8)
self.myLabel.setPixmap(QtGui.QPixmap(self.qimg))
pyplot.imshow(self.img)
pyplot.show()

pyplot.imshow()的结果是:

myLabel显示以下结果:

那么,我的代码有什么问题?

So, what is wrong with my code?

是否有更优雅的方式将2D numpy数组显示为图像?

Is there a more elegant way to display my 2D numpy array as an image?

推荐答案

据我所知,OP中有一个

From what I read the OP has an XY problem, that is, its objective is to show the output of imshow() in a Qt window, but ask about the attempt to display the data in a QImage.

imshow()方法不显示原始数据,而是根据docs指示的参数处理信息:

The imshow() method does not show raw data but processes the information based on the parameters as indicated by the docs:

matplotlib.pyplot.imshow(X,cmap = None,norm = None,Aspect = None, 插值=无,alpha =无,vmin =无,vmax =无,原点=无, 范围=无,形状=,filternorm = 1, filterrad = 4.0,imlim =,resample = None,url = None, *,data = None,** kwargs)

matplotlib.pyplot.imshow(X, cmap=None, norm=None, aspect=None, interpolation=None, alpha=None, vmin=None, vmax=None, origin=None, extent=None, shape=, filternorm=1, filterrad=4.0, imlim=, resample=None, url=None, *, data=None, **kwargs)

因此,如果要使用该数据获取图像,则必须实现该算法(可以检查matplotlib或类似软件的源代码来分析逻辑)

So if you want to obtain an image with that data you must implement that algorithm (you can check the source code of matplotlib or similar SW to analyze the logic)

如果我们专注于实际目标,那么最简单的解决方案是使用matplotlib的Qt后端来获取适当的画布,如下所示:

If we focus on the real objective then the simplest solution is to use the Qt backend of matplotlib to obtain the appropriate canvas as shown below:

import numpy as np

from PyQt5 import QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.figure import Figure


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.figure = Figure(figsize=(5, 3))
        self.canvas = FigureCanvas(self.figure)
        self.ax = self.figure.subplots()

        delta = 0.025
        x = y = np.arange(-3.0, 3.0, delta)
        X, Y = np.meshgrid(x, y)
        Z1 = np.exp(-(X ** 2) - Y ** 2)
        Z2 = np.exp(-((X - 1) ** 2) - (Y - 1) ** 2)
        Z = (Z1 - Z2) * 2

        self.ax.imshow(Z)
        self.ax.set_axis_off()

        self.setCentralWidget(self.canvas)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.resize(640, 480)
    w.show()

    sys.exit(app.exec_())

更新:

如果要不时显示数据,则可以使用QTimer来更新信息,如下所示:

If you want to display the data from time to time then you can use a QTimer that updates the information as I show below:

import random
import numpy as np

from PyQt5 import QtCore, QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.figure import Figure


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.figure = Figure(figsize=(5, 3))
        self.canvas = FigureCanvas(self.figure)
        self.ax = self.figure.subplots()
        self.ax.set_axis_off()

        self.setCentralWidget(self.canvas)

        timer = QtCore.QTimer(self)
        timer.timeout.connect(self.on_timeout)
        timer.start(100)

    def on_timeout(self):
        x0, y0 = random.uniform(-2, 2), random.uniform(-2, 2)
        delta = 0.025
        x = y = np.arange(-3.0, 3.0, delta)
        X, Y = np.meshgrid(x, y)
        Z1 = np.exp(-(X ** 2) - Y ** 2)
        Z2 = np.exp(-((X - x0) ** 2) - (Y - y0) ** 2)
        Z = (Z1 - Z2) * 2
        self.ax.imshow(Z)
        self.canvas.draw()


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.resize(640, 480)
    w.show()

    sys.exit(app.exec_())

另一方面,如果您想实时拥有软件,则GUI将限制该目标.建议每N个样本显示一次数据,以防止GUI被阻止,并且用户可以查看和分析信息.人眼非常慢,因此即使存在每毫秒显示图像的技术,我们的视觉也不会欣赏它,我们的视觉需要60ms的时间来处理图像,因此,即使频率优越,设备也可以以30Hz的频率工作不会观察到改善.

On the other hand, if you want to have a SW in real time then the GUI will limit that objective. It is advisable to show the data every N samples so that the GUI is not blocked and the user can view and analyze the information. The human eye is very slow, so even if the technology exists to display images every microsecond, our vision would not appreciate it, our vision requires 60ms to process the image, therefore the devices are designed to work at 30Hz since if the frequency were superior improvement would not be observed.

这篇关于在Qt中显示matplotlib imshow输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆