opencv BGR图像及其反向版本RGB图像[:,:,::-1]有什么区别?

时间:2019-04-02 06:21:23

标签: python opencv pyqt qimage

我正在尝试显示带有QLabel的opencv图像。我得到了两个不同版本的图像,第一个是opencv BGR图像,第二个是使用image [:,:,::-1]的RGB图像,BGR版本可以正常工作,但是RGB版本不起作用。

以下代码可以正常运行

src = cv.imread('image.jpg')
h,w,ch = src.shape
bytesPerLine = ch * w
qImg = QImage(src.data, w, h, bytesPerLine, QImage.Format_RGB888)
qImg = qImg.rgbSwapped()
self.ui.label.setPixmap(QPixmap.fromImage(qImg))


这些代码无效:

src = cv.imread('image.jpg')
src = src[:,:,::-1]
h,w,ch = src.shape
bytesPerLine = ch * w
qImg = QImage(src.data, w, h, bytesPerLine, QImage.Format_RGB888)
self.ui.label.setPixmap(QPixmap.fromImage(qImg))

1 个答案:

答案 0 :(得分:3)

您已经注意到opencv读取BGR格式的图像,但读取RGB的QImage,在第一种方法中,您无需转换就转换为QImage,然后使用rgbSwapped()方法进行转换。

通过测试我得到的第一种方法:

1000 loops, best of 5: 291 usec per loop

在第二种方法中,您尝试在将其转换为QImage之前执行此操作,但是当我执行它时,假设您也获得了它,则会出现以下错误。

Traceback (most recent call last):
  File "xxxx.py", line 18, in <module>
    qImg = QtGui.QImage(src.data, w, h, bytesPerLine, QtGui.QImage.Format_RGB888)
TypeError: arguments did not match any overloaded call:
  QImage(): too many arguments
  QImage(QSize, QImage.Format): argument 1 has unexpected type 'memoryview'
  QImage(int, int, QImage.Format): argument 1 has unexpected type 'memoryview'
  QImage(bytes, int, int, QImage.Format): argument 1 has unexpected type 'memoryview'
  QImage(sip.voidptr, int, int, QImage.Format): argument 1 has unexpected type 'memoryview'
  QImage(bytes, int, int, int, QImage.Format): argument 1 has unexpected type 'memoryview'
  QImage(sip.voidptr, int, int, int, QImage.Format): argument 1 has unexpected type 'memoryview'
  QImage(List[str]): argument 1 has unexpected type 'memoryview'
  QImage(str, format: str = None): argument 1 has unexpected type 'memoryview'
  QImage(QImage): argument 1 has unexpected type 'memoryview'
  QImage(Any): too many arguments

这是因为numpy使用memoryview来优化某些任务。在这种情况下,当进行src[:,:,::-1]优化的一种方法不是修改数据而是访问数据的方法时,这是通过Buffer Protocol完成的。

在这种情况下,QImage不支持此类数据,因此解决方案是使用tobytes()bytes()访问字节:

import cv2
from PyQt5 import QtGui, QtWidgets

if __name__ == '__main__':
    import sys
    src = cv2.imread('image.jpg')
    src = src[:,:,::-1]
    h, w, ch = src.shape
    bytesPerLine = ch * w
    qImg = QtGui.QImage(src.data.tobytes(), w, h, bytesPerLine, QtGui.QImage.Format_RGB888)
    # Or
    # qImg = QtGui.QImage(bytes(src.data), w, h, bytesPerLine, QtGui.QImage.Format_RGB888)
    app = QtWidgets.QApplication(sys.argv)
    w = QtWidgets.QLabel()
    w.setPixmap(QtGui.QPixmap.fromImage(qImg))
    w.show()
    sys.exit(app.exec_())

时间:

500 loops, best of 5: 523 usec per loop

另一种解决方案是使用opencv的cvtColor()函数,如果您修改数据,则该函数:

import cv2
from PyQt5 import QtGui, QtWidgets

if __name__ == '__main__':
    import sys
    src = cv2.imread('image.jpg')
    src = cv2.cvtColor(src, cv2.COLOR_BGR2RGB)
    h, w, ch = src.shape
    bytesPerLine = ch * w
    qImg = QtGui.QImage(src.data, w, h, bytesPerLine, QtGui.QImage.Format_RGB888)
    app = QtWidgets.QApplication(sys.argv)
    w = QtWidgets.QLabel()
    w.setPixmap(QtGui.QPixmap.fromImage(qImg))
    w.show()
    sys.exit(app.exec_())

时间:

1000 loops, best of 5: 263 usec per loop