【问题标题】:How to configure color when convert CV2 numpy array to QImage?将CV2 numpy数组转换为QImage时如何配置颜色?
【发布时间】:2013-09-07 19:11:54
【问题描述】:

程序基于pyqt和opencv。我计划在使用 QT 作为 GUI 的同时使用 opencv 读取和处理图像。

当我打开一个灰色图像时,结果是好的。但是打开彩色图像时会改变图像的颜色。我想这是因为我将 numpy 数组转换为 OImage 类型时犯了错误,但我不知道如何纠正它。

# -*- coding: utf-8 -*-
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys

import cv2
from cv2 import cv

QTextCodec.setCodecForTr(QTextCodec.codecForName("utf8"))

class MainWindow(QMainWindow):
    def __init__(self,parent=None):
        super(MainWindow,self).__init__(parent)
        self.setWindowTitle("Show Image with pyqt")

        self.imageLabel=QLabel()
        self.imageLabel.setSizePolicy(QSizePolicy.Ignored,QSizePolicy.Ignored)
        self.setCentralWidget(self.imageLabel)

        self.image=QImage()

        self.createActions()
        self.createMenus()

        self.cv_img = None

    def createActions(self):
        self.fileOpenAction=QAction(QIcon(":/fileopen.png"),self.tr("Open"),self)
        self.fileOpenAction.setShortcut("Ctrl+O")
        self.fileOpenAction.setStatusTip(self.tr("Open the file"))
        self.connect(self.fileOpenAction,SIGNAL("triggered()"),self.slotOpenFile)

        self.exitAction=QAction(QIcon(":/filequit.png"),self.tr("Quit"),self)
        self.exitAction.setShortcut("Ctrl+Q")
        self.setStatusTip(self.tr("Quit"))
        self.connect(self.exitAction,SIGNAL("triggered()"),self.close)

    def createMenus(self):
        fileMenu=self.menuBar().addMenu(self.tr("File"))
        fileMenu.addAction(self.fileOpenAction)
        fileMenu.addAction(self.exitAction)


    def slotOpenFile(self):
        fileName=QFileDialog.getOpenFileName(self,self.tr("Open a file"),\
            ".",self.tr("Image File(*.png *.jpg *.jpeg *.bmp)"))

        cvfilename=fileName.toLocal8Bit().data()

        if fileName.isEmpty()==False:

            cvfilename=fileName.toLocal8Bit().data() #convert Qstring to char*
            self.cv_img = cv2.imread(cvfilename) #read image with opencv
            cv2.imshow("Show Image with Opencv",self.cv_img) #show image with opencv, this is the right result

            self.image =QImage(self.cv_img.tostring(),\
                self.cv_img.shape[0],self.cv_img.shape[1],QImage.Format_RGB888) #convert numpy array to QImage
            self.imageLabel.setPixmap(QPixmap.fromImage(self.image))
            self.resize(self.image.width(),self.image.height())

app=QApplication(sys.argv)
main=MainWindow()
main.show()
app.exec_()

【问题讨论】:

    标签: python qt opencv numpy pyqt


    【解决方案1】:

    您需要将图像数据从 BGR 转换为 RGB。您还需要交换宽度和高度(见下文)——您的代码仅适用于具有相同宽度和高度的图像。

    self.cv_img = cv2.imread(cvfilename)
    
    if self.cv_img != None:
        # Notice the dimensions.
        height, width, bytesPerComponent = cv_img.shape
        bytesPerLine = bytesPerComponent * width;
    
        cv2.imshow("Show Image with Opencv", self.cv_img)
    
        # Convert to RGB for QImage.
        cv2.cvtColor(self.cv_img, cv.CV_BGR2RGB, self.cv_img)
    
        self.image = QImage(self.cv_img.data, width, height, bytesPerLine, QImage.Format_RGB888)
    

    【讨论】:

    • 按照您的建议修改后,代码可以很好地显示PNG和BMP图像,但是对于JPG图像有一种偏移。你知道为什么吗?谢谢。
    • 好的,已修复。您需要 bytesPerLine 值(我认为它始终为 3)。
    • 很抱歉,但是使用“self.image = QImage(self.cv_img.data, width, height, 3, QImage.Format_RGB888)”将不再显示图像:(
    • 哦抱歉,基本上应该是“bytesPerLine = 3 * width”(固定)。
    【解决方案2】:

    我知道这是一个很老的线程,但对我来说 cv2.cvtColor 的工作速度真的很慢。 我发现了另一个功能,可以帮助那些将来需要的人(我花了很长时间才找到这个补救措施):

    def cv2_to_qimage(cv_img):
    
        height, width, bytesPerComponent = cv_img.shape
        bgra = np.zeros([height, width, 4], dtype=np.uint8)
        bgra[:, :, 0:3] = cv_img
        return QtGui.QImage(bgra.data, width, height, QtGui.QImage.Format_RGB32)
    

    希望对你有用

    【讨论】:

      【解决方案3】:

      以下代码对 openCV3.x 版本进行了 color-filter 更新。代码示例来自hluk

      import cv2
      from cv2 import CV
      
      ...<snippet>...
      
      self.cv_img = cv2.imread(cvfilename)
      
      if self.cv_img != None:
          # Notice the dimensions.
          height, width, bytesPerComponent = cv_img.shape
          bytesPerLine = bytesPerComponent * width;
      
          cv2.imshow("Show Image with Opencv", self.cv_img)
      
          # Convert to RGB for QImage.
          cv2.cvtColor(self.cv_img, cv2.COlOR_BGR2RGB, self.cv_img)
      
          self.image = QImage(self.cv_img.data, width, height, bytesPerLine, QImage.Format_RGB888)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-30
        • 1970-01-01
        • 1970-01-01
        • 2022-01-10
        • 2021-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多