简体   繁体   中英

What is the difference between an opencv BGR image and its reverse version RGB image[:,:,::-1]?

I'm trying to show an opencv image with a QLabel. I got two different versions of the image, first one is the opencv BGR image, the second one is the RGB image using image[:,:,::-1], the BGR version works fine but the RGB version doesn't work.

The following code works fine

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))


These code doesn't work :

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))

As you have noticed opencv reads the image in BGR format but QImage in RGB, in your first method you convert to QImage without doing the conversion and then you use rgbSwapped() method to do the conversion.

By testing the first method I get:

1000 loops, best of 5: 291 usec per loop

In the second method you try to do it before converting it to QImage but when I execute it I get the following error presuming that you also get it.

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

And this is because numpy uses memoryview to optimize certain tasks. And in this case when doing src[:,:,::-1] one way to optimize is not to modify the data but the way to access the data, this is done through the Buffer Protocol .

And in this case QImage does not support this type of data, so the solution is to access the bytes using the tobytes() or 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_())

Time:

500 loops, best of 5: 523 usec per loop

Another solution is to use the cvtColor() function of opencv that if you modify the data:

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_())

Time:

1000 loops, best of 5: 263 usec per loop

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM