Numpy 显示matplotlib imshow输出(以Qt为单位)

Numpy 显示matplotlib imshow输出(以Qt为单位),numpy,pyqt5,python-3.6,qimage,qpixmap,Numpy,Pyqt5,Python 3.6,Qimage,Qpixmap,我有一个np.float64类型的2D numpy数组,我想用QLabel(或任何其他有效方式)将其显示为图像: 上面的“我的代码”返回以下错误: 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, in

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

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

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()
,那么它就可以工作了!但它不能正确显示数据

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()相比显示的内容:

pyplot.imshow()的结果是:

myLabel
则显示以下结果:

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


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

据我所知,OP有一个,即它的目标是在Qt窗口中显示imshow()的输出,但询问是否尝试在QImage中显示数据

该方法不显示原始数据,而是根据文档所示的参数处理信息:

matplotlib.pyplot.imshow(X,cmap=None,norm=None,aspect=None, 插值=无,alpha=无,vmin=无,vmax=无,原点=无, 范围=无,形状=,过滤器形式=1, filterrad=4.0,imlim=,重采样=None,url=None, *,数据=无,**kwargs)

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

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

将numpy导入为np
从PyQt5导入QtWidgets
从matplotlib.backends.backend_qt5agg导入FigureCanvas
从matplotlib.figure导入图形
类MainWindow(QtWidgets.QMainWindow):
def uuu init uuu(self,parent=None):
super()。\uuuu init\uuuu(父级)
self.figure=图(figsize=(5,3))
self.canvas=FigureCanvas(self.figure)
self.ax=self.figure.subplots()
增量=0.025
x=y=np.arange(-3.0,3.0,delta)
十、 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)
如果名称=“\uuuuu main\uuuuuuuu”:
导入系统
app=qtwidts.QApplication(sys.argv)
w=主窗口()
w、 调整大小(640480)
w、 show()
sys.exit(app.exec_())

更新:

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

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就不会被阻塞,用户可以查看和分析信息。人眼的速度非常慢,因此即使存在每微秒显示图像的技术,我们的视觉也不会欣赏它,我们的视觉需要60毫秒来处理图像,因此,设备设计为在30Hz下工作,因为如果频率较高,则无法观察到改善。

获取我的数据()
获得的值的范围是多少?因为如果它们是浮点值,则不能按原样使用它们。图像格式接受1、8、16、24、32或64位(作为“整数值”)格式。如果知道数据的范围,则可以将数组转换为整数值。例如,如果它们介于0和1之间,类似的内容可能会起作用(假设您需要8位转换):
self.img=np.multiply(get_my_data(),127)。astype('int8')
@musicamante我的一个示例的范围是[3.2101597817728964e-05 12684375.661213763],通常我无法确定最大值和最小值,那么如何应对呢?以及如何使用QImage显示生成的int8类型的2D numpy数组?谢谢你。@eyllanesc我希望如此,但这是的一个相当大的实现。然而,正如您所看到的,我使用的是结果的
20*np.log10
get_my_data()
的结果是$| STFT | ^2$,因为我需要尽可能简单地在窗口的特定区域显示音频数据的实时频谱图,无论使用什么小部件。但是,我使用PyQtGraph显示实时音频数据,与Matplotlib相比,它的绘图速度非常快。因此,如果您编辑您的答案以显示实时光谱图(如上图所示为2D图像),我将非常感激。谢谢。@catfour您所表示的支持XY问题,我建议您重写您的问题以表明您的真正目标,在标题中您表示您希望转换为QImage,但真正的问题是您希望获得与matplotlib的imshow方法所显示的相等的QImage
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()
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_())