将Python Opencv图像(numpy数组)转换为PyQt QPixmap图像

27

我正尝试将Python OpenCV图像转换为QPixmap。

我按照页面链接中的说明进行操作,我的代码附在下面。

img = cv2.imread('test.png')[:,:,::1]/255. 
imgDown = cv2.pyrDown(img)
imgDown = np.float32(imgDown)        
cvRGBImg = cv2.cvtColor(imgDown, cv2.cv.CV_BGR2RGB)
qimg = QtGui.QImage(cvRGBImg.data,cvRGBImg.shape[1], cvRGBImg.shape[0], QtGui.QImage.Format_RGB888)
pixmap01 = QtGui.QPixmap.fromImage(qimg)
self.image01TopTxt = QtGui.QLabel('window',self)
self.imageLable01 = QtGui.QLabel(self)
self.imageLable01.setPixmap(pixmap01)

代码没有编译和运行时错误,但转换是错误的,我只得到了一些噪点图像。我不确定问题在哪里。有人能帮忙吗?

9个回答

48

使用此方法将cvImage转换为QImage,其中cvImage是原始图像。

height, width, channel = cvImg.shape
bytesPerLine = 3 * width
qImg = QImage(cvImg.data, width, height, bytesPerLine, QImage.Format_RGB888)

将Qimage设置为标签并使用setPixmap函数,参数为Qimage。它有效!


1
我必须显式地创建 QPixmapself.imageLable01.setPixmap(QPixmap(qImg)) 并传递 bytesPerLine + 1 - jfs
1
不一定非得是RGB888格式,根据qt5文档(https://doc.qt.io/qt-5/qimage.html#image-formats)提供的支持格式列表进行选择。当然,您需要确保您的numpy数组具有正确的数据。 - Mark Carpenter Jr
2
使用OpenCV时,您需要使用QImage.Format_BGR888,因为OpenCV使用BGR而不是RGB。 - fferri
@fferri 当我尝试使用 Format_BGR888 时,出现了错误 type object 'QImage' has no attribute 'Format_BGR888'。但是使用 Format_RGB888 就可以正常工作。为什么? - s.paszko
@s.paszko QImage.Format_BGR888 在Qt 5.14中被添加,请升级。 - fferri
显示剩余3条评论

23

仅仅是作为AdityaIntwala回答的补充,如果图像看起来是红色或蓝色的,那是因为格式不是RGB,而是BGR(相反的顺序)。这种情况下,使用QImage.rgbSwapped方法进行校正:

height, width, channel = cvImg.shape
bytesPerLine = 3 * width
qImg = QImage(cvImg.data, width, height, bytesPerLine, QImage.Format_RGB888).rgbSwapped()

8
#image is the numpy array that you got from cv2.imread(example_image.jpg)

image = QtGui.QImage(image, image.shape[1],\
                            image.shape[0], image.shape[1] * 3,QtGui.QImage.Format_RGB888)
pix = QtGui.QPixmap(image)

self.scene.addPixmap(pix)

5
抱歉增加了这么多回答,但是因为这是唯一对我有效的方法,所以我想提供帮助以防其他人遇到同样的问题。
正如在GitHub上提到的那样,
首先将numpy数组/ndarray包装在np.require(array, np.uint8, 'C')调用中,例如:
arr2 = np.require(arr, np.uint8, 'C')
qImg = QtGui.QImage(arr2, width, height, QtGui.QImage.Format_RGB888)

3

这是我的看法:

def convert_nparray_to_QPixmap(self,img):
    w,h,ch = img.shape
    # Convert resulting image to pixmap
    if img.ndim == 1:
        img =  cv2.cvtColor(img,cv2.COLOR_GRAY2RGB)

    qimg = QImage(img.data, h, w, 3*h, QImage.Format_RGB888) 
    qpixmap = QPixmap(qimg)

    return qpixmap

3

这里有最简单的方法:

from PIL.ImageQt import ImageQt 
from PIL import Image
from PySide2.QtGui import QPixmap
import cv2


# Convert an opencv image to QPixmap
def convertCvImage2QtImage(cv_img):
    rgb_image = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
    PIL_image = Image.fromarray(rgb_image).convert('RGB')
    return QPixmap.fromImage(ImageQt(PIL_image))

1

AdityaIntwala的答案接近了,但是对我来说没有用。cvImg.data出现了一个错误,像是“argument 1 has unexpected type 'memoryview'”。所以我删除了'cvImg.data'并将cvImg.tobytes()作为字节传递,这样就可以了。

height, width, channel = cvImg.shape
bytesPerLine = 3 * width
qImg = QImage(cvImg.tobytes(), width, height, bytesPerLine, QImage.Format_RGB888).rgbSwapped()

然后,我已经将像素图设置如下所示。
self.imageLabel.setPixmap(QPixmap(qImg))

0
  image=cv2.imread("your_image.png")
  image = QtGui.QImage(image, image.shape[1],image.shape[0], image.shape[1] * 3, QtGui.QImage.Format_BGR888)
  pix = QtGui.QPixmap(image)
  self.image.setPixmap(QtGui.QPixmap(pix))

你好,欢迎来到 Stack Overflow。仅发布代码块的答案并不推荐,最好在其周围添加一些文本来解释它的工作原理和原因。 - Luke_

0
使用OpenCV读取图像时,输出的格式为BGR。但是,在运行QImage之前,您需要将BGR转换为RGB。
请使用 cv2.cvtColor(img,cv2.COLOR_BGR2RGB) 进行转换。如果您使用其他解决方案(例如 img = img[:,:,(2,1,0)])将BGR转换为RGB,则可能不完整。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接