opencv BGR 图像和它的反向版本 RGB 图像 [:,:,::-1] 有什么区别?
What is the difference between an opencv BGR image and its reverse version RGB image[:,:,::-1]?
我正在尝试显示带有 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))
正如您所注意到的,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
我正在尝试显示带有 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))
正如您所注意到的,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