В чем разница между изображением opencv BGR и его RGB-изображением в обратной версии [:,:, :: - 1]? - PullRequest
2 голосов
/ 02 апреля 2019

Я пытаюсь показать изображение opencv с помощью QLabel. Я получил две разные версии изображения: первая - это изображение BGR opencv, вторая - изображение RGB с использованием изображения [:,:, :: - 1], версия 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 Ответ

4 голосов
/ 02 апреля 2019

Как вы заметили, opencv читает изображение в формате BGR, но QImage в RGB, в вашем первом методе вы конвертируете в 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 использует представление памяти для оптимизации определенных задач.И в этом случае при выполнении src[:,:,::-1] один из способов оптимизации заключается не в изменении данных, а в способе доступа к данным, это осуществляется с помощью протокола буфера .

.case 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

Другим решением является использование cvtColor() функции opencv, которая при изменении данных:

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