Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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))
like image 858
Yifeng_Li Avatar asked Oct 18 '25 08:10

Yifeng_Li


1 Answers

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
like image 136
eyllanesc Avatar answered Oct 20 '25 21:10

eyllanesc