Skip to content

Commit 5825a5b

Browse files
committed
Support opencv formats and make opencv write into buffer
1 parent 35f17f0 commit 5825a5b

File tree

1 file changed

+52
-11
lines changed

1 file changed

+52
-11
lines changed

linuxpy/video/qt.py

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -107,16 +107,23 @@ def loop(self):
107107
class MemMap(MemoryMap):
108108
def open(self):
109109
super().open()
110+
self.opencv = False
110111
format = self.format
111112
if pixel_format := FORMAT_MAP.get(format.pixel_format):
112113
self.data = bytearray(format.size)
113114
self.qimage = QtGui.QImage(self.data, format.width, format.height, pixel_format)
115+
elif format in OPENCV_FORMATS:
116+
self.data = bytearray(format.width * format.height * 3)
117+
self.qimage = QtGui.QImage(self.data, format.width, format.height, QtGui.QImage.Format.Format_RGB888)
118+
self.opencv = True
114119
else:
115120
self.data = None
116121
self.qimage = None
117122

118123
def raw_read(self, into=None):
119124
frame = super().raw_read(self.data)
125+
if self.data and frame.pixel_format in OPENCV_FORMATS:
126+
frame_to_rgb24(frame, self.data)
120127
frame.user_data = self.qimage
121128
return frame
122129

@@ -578,26 +585,59 @@ def to_qpixelformat(pixel_format: PixelFormat) -> QtGui.QPixelFormat | None:
578585

579586

580587
FORMAT_MAP = {
581-
PixelFormat.RGB24: QtGui.QImage.Format.Format_RGB888,
582-
PixelFormat.RGB32: QtGui.QImage.Format.Format_RGB32,
583-
PixelFormat.RGBA32: QtGui.QImage.Format.Format_RGBA8888,
584-
PixelFormat.ARGB32: QtGui.QImage.Format.Format_ARGB32,
585-
PixelFormat.XRGB32: QtGui.QImage.Format.Format_ARGB32,
586-
PixelFormat.GREY: QtGui.QImage.Format.Format_Grayscale8,
588+
PixelFormat.RGB24: QtGui.QImage.Format.Format_RGB888, # ok
589+
PixelFormat.BGR24: QtGui.QImage.Format.Format_BGR888, # ok
590+
PixelFormat.RGB565: QtGui.QImage.Format.Format_RGB16, # ok
591+
PixelFormat.RGBX555: QtGui.QImage.Format.Format_RGB555, # ok ? Transparency
592+
PixelFormat.XRGB444: QtGui.QImage.Format.Format_RGB444, # ok
593+
PixelFormat.RGB32: QtGui.QImage.Format.Format_ARGB32, # wrong
594+
PixelFormat.RGBA32: QtGui.QImage.Format.Format_RGBA8888, # wrong no image!
595+
PixelFormat.ARGB32: QtGui.QImage.Format.Format_ARGB32, # wrong
596+
PixelFormat.XRGB32: QtGui.QImage.Format.Format_RGB32, # wrong (same problem as RGB32)
597+
PixelFormat.GREY: QtGui.QImage.Format.Format_Grayscale8, # ok
598+
PixelFormat.Y16: QtGui.QImage.Format.Format_Grayscale16, # ok
599+
PixelFormat.RGBX32: QtGui.QImage.Format.Format_RGBX8888, # ok
600+
PixelFormat.RGBX1010102: QtGui.QImage.Format.Format_RGB30,
601+
}
602+
603+
OPENCV_FORMATS = {
604+
PixelFormat.YUYV,
605+
PixelFormat.YVYU,
606+
PixelFormat.UYVY,
607+
PixelFormat.YUV420,
608+
PixelFormat.NV12,
609+
PixelFormat.NV21,
587610
}
588611

589612

613+
def frame_to_rgb24(frame, into=None):
614+
import cv2
615+
616+
YUV_MAP = {
617+
PixelFormat.YUYV: cv2.COLOR_YUV2RGB_YUYV,
618+
PixelFormat.YVYU: cv2.COLOR_YUV2RGB_YVYU,
619+
PixelFormat.UYVY: cv2.COLOR_YUV2RGB_UYVY,
620+
PixelFormat.YUV420: cv2.COLOR_YUV2RGB_I420,
621+
PixelFormat.NV12: cv2.COLOR_YUV2RGB_NV12,
622+
PixelFormat.NV21: cv2.COLOR_YUV2RGB_NV21,
623+
}
624+
data = frame.array
625+
fmt = frame.pixel_format
626+
if fmt in {PixelFormat.NV12, PixelFormat.YUV420}:
627+
data.shape = frame.height * 3 // 2, frame.width, -1
628+
else:
629+
data.shape = frame.height, frame.width, -1
630+
return cv2.cvtColor(data, YUV_MAP[fmt], dst=into)
631+
632+
590633
def frame_to_qimage(frame: Frame) -> QtGui.QImage | None:
591634
"""Translates a Frame to a QImage"""
592635
data = frame.data
593636
if frame.pixel_format == PixelFormat.MJPEG:
594637
return QtGui.QImage.fromData(data, "JPG")
595-
elif frame.pixel_format == PixelFormat.YUYV:
596-
import cv2
597638

598-
data = frame.array
599-
data.shape = frame.height, frame.width, -1
600-
data = cv2.cvtColor(data, cv2.COLOR_YUV2BGR_YUYV)
639+
if frame.pixel_format in OPENCV_FORMATS:
640+
data = frame_to_rgb24(frame)
601641
fmt = QtGui.QImage.Format.Format_RGB888
602642
else:
603643
if (fmt := FORMAT_MAP.get(frame.pixel_format)) is None:
@@ -857,6 +897,7 @@ def stop():
857897
window = QtWidgets.QWidget()
858898
layout = QtWidgets.QHBoxLayout(window)
859899
video = QVideoWidget(camera)
900+
video.setMinimumSize(640, 480)
860901
panel = QControlPanel(camera)
861902
settings = QSettingsPanel(camera)
862903
layout.addWidget(settings)

0 commit comments

Comments
 (0)