&YO 2023-02-15 10:44 采纳率: 66.7%
浏览 103
已结题

python, Pyqt5的图像显示问题

我想使用python的pyqt5编写一个QLabel显示图片,直接读取图片为QPixmap后用setPixmap显示图片的时候正常,在使用PIL.image读取图片为PIL.Image类型后再用ImageQt.toqpixmap转换为QPixmap后就无法显示图片了,程序跑了直接退出也不报错,debug也是直接退出。这个有什么解决方案吗。ps:不直接使用Qpixmap是因为某个项目里面用到PIL.Image进行运算,运算后需要转换为Qpixmap进行显示
补充,我自己在找解决办法的时候发现,我将PIL.Image类型转化为ndarray后直接用matplotlib进行显示是可以的,但是转换为Pixmap又不行了。后面我尝试随机生成一个RGB数据数组转换为Pixmap发现也无法显示。由于程序直接退出不报错,不知道问题所在,下面是我的测试代码。

from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 300)
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(60, 90, 261, 151))
        self.label.setStyleSheet("background-color:rgb(85, 170, 255)")
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(50, 30, 75, 23))
        self.pushButton.setObjectName("pushButton")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.label.setText(_translate("Form", "Label"))
        self.pushButton.setText(_translate("Form", "PushButton"))

import sys

from PIL import Image, ImageQt
from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow
import numpy as np

from testLabel import Ui_Form
import cv2

class MyMainForm(QMainWindow, Ui_Form):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.pushButton.clicked.connect(self.openPicture)


    def openPicture(self):

        # pix = Image.open('result.jpg')
        # pix = ImageQt.toqpixmap(pix)
        # img = cv2.imread('result.jpg')
        # pix = QtGui.QPixmap('result.jpg')
        # self.label.setScaledContents(True)
        img = np.random.randint(0, 255, [10, 60, 3], np.uint8)
        img = img.astype("uint8")
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img = QtGui.QImage(img, img.shape[1], img.shape[0], img.shape[1] * 3, QtGui.QImage.Format_RGB888)


        self.label.setPixmap(img)


if __name__ == '__main__':
    QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
    app = QtWidgets.QApplication(sys.argv)
    my = MyMainForm()
    my.show()
    sys.exit(app.exec_())
  • 写回答

7条回答 默认 最新

  • qq_46161207 2023-02-15 11:53
    关注

    你的代码中,使用QImage对象替换了QPixmap对象来显示图片,由于QImage对象是只读的,因此您无法在QImage对象上执行操作。你需要将QImage对象转换为QPixmap对象,然后再将其设置为标签的图像。这是修改以后的代码

    from PyQt5 import QtCore, QtGui, QtWidgets
    class Ui_Form(object):
        def setupUi(self, Form):
            Form.setObjectName("Form")
            Form.resize(400, 300)
            self.label = QtWidgets.QLabel(Form)
            self.label.setGeometry(QtCore.QRect(60, 90, 261, 151))
            self.label.setStyleSheet("background-color:rgb(85, 170, 255)")
            self.label.setObjectName("label")
            self.pushButton = QtWidgets.QPushButton(Form)
            self.pushButton.setGeometry(QtCore.QRect(50, 30, 75, 23))
            self.pushButton.setObjectName("pushButton")
    
            self.retranslateUi(Form)
            QtCore.QMetaObject.connectSlotsByName(Form)
    
        def retranslateUi(self, Form):
            _translate = QtCore.QCoreApplication.translate
            Form.setWindowTitle(_translate("Form", "Form"))
            self.label.setText(_translate("Form", "Label"))
            self.pushButton.setText(_translate("Form", "PushButton"))
    
    import sys
    
    from PIL import Image, ImageQt
    from PyQt5 import QtGui, QtCore, QtWidgets
    from PyQt5.QtWidgets import QMainWindow
    import numpy as np
    
    from testLabel import Ui_Form
    import cv2
    
    class MyMainForm(QMainWindow, Ui_Form):
        def __init__(self):
            super().__init__()
            self.setupUi(self)
            self.pushButton.clicked.connect(self.openPicture)
    
    
        def openPicture(self):
    
            # pix = Image.open('result.jpg')
            # pix = ImageQt.toqpixmap(pix)
            # img = cv2.imread('result.jpg')
            # pix = QtGui.QPixmap('result.jpg')
            # self.label.setScaledContents(True)
            img = np.random.randint(0, 255, [10, 60, 3], np.uint8)
            img = img.astype("uint8")
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            img = QtGui.QImage(img, img.shape[1], img.shape[0], img.shape[1] * 3, QtGui.QImage.Format_RGB888)
    
            pixmap = QtGui.QPixmap.fromImage(img)
            self.label.setPixmap(pixmap)
    
    
    if __name__ == '__main__':
        QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
        app = QtWidgets.QApplication(sys.argv)
        my = MyMainForm()
        my.show()
        sys.exit(app.exec_())
    

    如果能解决问题,望采纳

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
  • BitGPT 2023-02-15 11:02
    关注

    该回答引用ChatGPT
    您的程序在将 PIL.Image 转换为 QPixmap 后无法显示图片,可能有几种原因。下面是一些可能导致此问题的原因和对应的解决方案:

    1、路径问题:请确保您在使用 PIL.Image 读取图像时提供了正确的路径,否则可能会读取不到图像。
    2、格式问题:请确保您使用的图像格式受到 PIL 库支持。例如,某些旧版的 BMP 文件可能无法在 PIL 中正确地解码。您可以尝试使用不同的图像格式来测试您的代码。
    3、Qt 主循环问题:在使用 QPixmap 显示图像之前,您需要确保已经创建了 Qt 主循环。如果您的应用程序没有创建主循环,则可能无法显示图像。您可以使用 QApplication 类创建主循环。

    以下是一个简单的示例代码,演示了如何使用 PIL.Image 将图像转换为 QPixmap 并在 QLabel 中显示:

    import sys
    from PIL import Image
    from PyQt5.QtCore import Qt
    from PyQt5.QtGui import QPixmap
    from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout
    
    
    class ImageLabel(QLabel):
        def __init__(self, pixmap):
            super().__init__()
            self.setPixmap(pixmap)
            self.setAlignment(Qt.AlignCenter)
    
    
    class MainWindow(QWidget):
        def __init__(self, image_path):
            super().__init__()
    
            # 读取图像
            image = Image.open(image_path)
    
            # 将 PIL.Image 转换为 QPixmap
            pixmap = QPixmap.fromImage(ImageQt(image))
    
            # 创建 QLabel 并在其中显示图像
            label = ImageLabel(pixmap)
    
            # 将 QLabel 添加到主窗口中
            layout = QVBoxLayout(self)
            layout.addWidget(label)
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
    
        # 创建主窗口并显示
        window = MainWindow('path/to/your/image.png')
        window.show()
    
        # 进入主循环
        sys.exit(app.exec_())
    
    
    
    

    在这个示例代码中,我们使用 Image.open() 方法读取图像,并将 PIL.Image 对象传递给 ImageQt() 函数,该函数将图像转换为 QImage。然后,我们使用 QPixmap.fromImage() 将 QImage 转换为 QPixmap 对象。最后,我们创建了一个继承自 QLabel 的 ImageLabel 类,以显示图像并设置居中对齐。
    如果你的应用程序中没有创建主循环,则可以使用 QApplication 类创建一个。在这个示例代码中,我们通过调用 QApplication() 函数来创建一个应用程序对象,并通过调用 exec_() 方法启动主循环。

    评论 编辑记录
  • 阿_旭 2023-02-15 11:20
    关注

    图片转换代码’

    import PIL
    from PIL import Image
    from PIL.ImageQt import ImageQt
    pix = Image.open('./11.jpg')
    qpixmap = PIL.ImageQt.toqpixmap(pix)
    
    

    完整代码如下,可正常显示

    import sys
    import PIL
    from PIL import Image
    from PIL.ImageQt import ImageQt
    from PyQt5 import QtGui, QtCore, QtWidgets
    from PyQt5.QtWidgets import QMainWindow
    import numpy as np
    
    from testLabel import Ui_Form
    import cv2
    
    class MyMainForm(QMainWindow, Ui_Form):
        def __init__(self):
            super().__init__()
            self.setupUi(self)
            self.pushButton.clicked.connect(self.openPicture)
    
    
        def openPicture(self):
            pix = Image.open('./11.jpg')
            qpixmap = PIL.ImageQt.toqpixmap(pix)
    
            self.label.setPixmap(qpixmap)
    
    
    if __name__ == '__main__':
        QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
        app = QtWidgets.QApplication(sys.argv)
        my = MyMainForm()
        my.show()
        sys.exit(app.exec_())
    
    
    
    评论
  • PythonJavaC++go 2023-02-15 11:29
    关注

    你好,

    根据你的代码,我发现你的问题可能是由于你没有正确地将numpy数组转换为QPixmap导致的。你的代码中,你使用了QImage的构造函数,将numpy数组转换为QImage对象,但是你没有给QImage指定正确的格式。你的numpy数组是RGB格式的,但是你给QImage指定了Format_RGB888,这是错误的。Format_RGB888是指每个像素由三个字节表示,分别是红色、绿色和蓝色,而不是RGB格式。你应该使用Format_RGB32,这是指每个像素由四个字节表示,分别是红色、绿色、蓝色和alpha通道,这才是RGB格式。

    为了解决这个问题,你可以在转换numpy数组为QImage时,使用Format_RGB32,而不是Format_RGB888。或者,你可以使用QImage的fromData方法,直接将numpy数组的数据作为参数,这样QImage会自动识别格式。下面是修改后的代码:

    from PyQt5 import QtCore, QtGui, QtWidgets
    class Ui_Form(object):
        def setupUi(self, Form):
            Form.setObjectName("Form")
            Form.resize(400, 300)
            self.label = QtWidgets.QLabel(Form)
            self.label.setGeometry(QtCore.QRect(60, 90, 261, 151))
            self.label.setStyleSheet("background-color:rgb(85, 170, 255)")
            self.label.setObjectName("label")
            self.pushButton = QtWidgets.QPushButton(Form)
            self.pushButton.setGeometry(QtCore.QRect(50, 30, 75, 23))
            self.pushButton.setObjectName("pushButton")
     
            self.retranslateUi(Form)
            QtCore.QMetaObject.connectSlotsByName(Form)
     
        def retranslateUi(self, Form):
            _translate = QtCore.QCoreApplication.translate
            Form.setWindowTitle(_translate("Form", "Form"))
            self.label.setText(_translate("Form", "Label"))
            self.pushButton.setText(_translate("Form", "PushButton"))
     import sys
     
    from PIL import Image, ImageQt
    from PyQt5 import QtGui, QtCore, QtWidgets
    from PyQt5.QtWidgets import QMainWindow
    import numpy as np
     
    from testLabel import Ui_Form
    import cv2
     
    class MyMainForm(QMainWindow, Ui_Form):
        def __init__(self):
            super().__init__()
            self.setupUi(self)
            self.pushButton.clicked.connect(self.openPicture)
     
     
        def openPicture(self):
     
            img = np.random.randint(0, 255, [10, 60, 3], np.uint8)
            img = img.astype("uint8")
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            # img = QtGui.QImage(img, img.shape[1], img.shape[0], img.shape[1] * 3, QtGui.QImage.Format_RGB32) # 使用Format_RGB32
            img = QtGui.QImage.fromData(img) # 或者使用fromData方法
            self.label.setPixmap(QtGui.QPixmap.fromImage(img)) # 将QImage转换为QPixmap
     
    if __name__ == '__main__':
        QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
        app = QtWidgets.QApplication(sys.argv)
        my = MyMainForm()
        my.show()
        sys.exit(app.exec_())
    
    评论
  • GISer Liu 2023-02-15 12:12
    关注

    你的代码中没有问题,不过在显示 QPixmap 时,你需要调用 'label.setScaledContent(True)
    代码如下:

    self.label.setScaledContents(True)
    

    如下所示:

    def openPicture(self):
        img = np.random.randint(0, 255, [10, 60, 3], np.uint8)
        img = img.astype("uint8")
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img = QtGui.QImage(img, img.shape[1], img.shape[0], img.shape[1] * 3, QtGui.QImage.Format_RGB888)
        pixmap = QtGui.QPixmap.fromImage(img)
        self.label.setPixmap(pixmap)
        self.label.setScaledContents(True)
    

    这个应该能解决你的问题

    评论 编辑记录
  • CSDN-Ada助手 CSDN-AI 官方账号 2023-02-15 12:24
    关注
    评论
  • glpaiai 2023-02-15 13:43
    关注

    解决方案:
    可以尝试使用QImage类来显示图片,而不是QPixmap类,因为QPixmap类只支持本地图片,而QImage类可以直接使用ndarray类型的图像。另外,如果你想使用QPixmap类,可以使用cv2.imencode()函数将ndarray类型的图片转换为JPEG或PNG格式,然后使用QPixmap类将其转换为QPixmap类。

    评论
查看更多回答(6条)

报告相同问题?

问题事件

  • 系统已结题 2月24日
  • 已采纳回答 2月16日
  • 创建了问题 2月15日

悬赏问题

  • ¥15 Java环境配了,但启用不成功。
  • ¥15 求一个智能家居控制的代码
  • ¥15 ad软件 pcb布线pcb规则约束编辑器where the object matpcb布线pcb规则约束编辑器where the object matchs怎么没有+15v只有no net
  • ¥15 虚拟机vmnet8 nat模式可以ping通主机,主机也能ping通虚拟机,但是vmnet8一直未识别怎么解决,其次诊断结果就是默认网关不可用
  • ¥20 求各位能用我能理解的话回答超级简单的一些问题
  • ¥15 yolov5双目识别输出坐标代码报错
  • ¥15 这个代码有什么语法错误
  • ¥15 给予STM32按键中断与串口通信
  • ¥15 使用QT实现can通信
  • ¥15 关于sp验证的一些东西,求告知如何解决,