utils.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. """图像格式转换工具。
  2. 该模块负责把 Orbbec SDK 的彩色帧转换为 OpenCV 常用 BGR 图像。
  3. """
  4. from typing import Any, Optional, Union
  5. import cv2
  6. import numpy as np
  7. from pyorbbecsdk import FormatConvertFilter, OBConvertFormat, OBFormat, VideoFrame
  8. def yuyv_to_bgr(frame: np.ndarray, width: int, height: int) -> np.ndarray:
  9. """将 YUYV 原始数据转换为 BGR 图像。"""
  10. yuyv = frame.reshape((height, width, 2))
  11. bgr_image = cv2.cvtColor(yuyv, cv2.COLOR_YUV2BGR_YUY2)
  12. return bgr_image
  13. def uyvy_to_bgr(frame: np.ndarray, width: int, height: int) -> np.ndarray:
  14. """将 UYVY 原始数据转换为 BGR 图像。"""
  15. uyvy = frame.reshape((height, width, 2))
  16. bgr_image = cv2.cvtColor(uyvy, cv2.COLOR_YUV2BGR_UYVY)
  17. return bgr_image
  18. def i420_to_bgr(frame: np.ndarray, width: int, height: int) -> np.ndarray:
  19. """将 I420 原始数据转换为 BGR 图像。"""
  20. y = frame[0:height, :]
  21. u = frame[height:height + height // 4].reshape(height // 2, width // 2)
  22. v = frame[height + height // 4:].reshape(height // 2, width // 2)
  23. yuv_image = cv2.merge([y, u, v])
  24. bgr_image = cv2.cvtColor(yuv_image, cv2.COLOR_YUV2BGR_I420)
  25. return bgr_image
  26. def nv21_to_bgr(frame: np.ndarray, width: int, height: int) -> np.ndarray:
  27. """将 NV21 原始数据转换为 BGR 图像。"""
  28. y = frame[0:height, :]
  29. uv = frame[height:height + height // 2].reshape(height // 2, width)
  30. yuv_image = cv2.merge([y, uv])
  31. bgr_image = cv2.cvtColor(yuv_image, cv2.COLOR_YUV2BGR_NV21)
  32. return bgr_image
  33. def nv12_to_bgr(frame: np.ndarray, width: int, height: int) -> np.ndarray:
  34. """将 NV12 原始数据转换为 BGR 图像。"""
  35. y = frame[0:height, :]
  36. uv = frame[height:height + height // 2].reshape(height // 2, width)
  37. yuv_image = cv2.merge([y, uv])
  38. bgr_image = cv2.cvtColor(yuv_image, cv2.COLOR_YUV2BGR_NV12)
  39. return bgr_image
  40. def determine_convert_format(frame: VideoFrame):
  41. """根据帧格式选择 SDK 可用的转换策略。"""
  42. if frame.get_format() == OBFormat.I420:
  43. return OBConvertFormat.I420_TO_RGB888
  44. elif frame.get_format() == OBFormat.MJPG:
  45. return OBConvertFormat.MJPG_TO_RGB888
  46. elif frame.get_format() == OBFormat.YUYV:
  47. return OBConvertFormat.YUYV_TO_RGB888
  48. elif frame.get_format() == OBFormat.NV21:
  49. return OBConvertFormat.NV21_TO_RGB888
  50. elif frame.get_format() == OBFormat.NV12:
  51. return OBConvertFormat.NV12_TO_RGB888
  52. elif frame.get_format() == OBFormat.UYVY:
  53. return OBConvertFormat.UYVY_TO_RGB888
  54. else:
  55. return None
  56. def frame_to_rgb_frame(frame: VideoFrame) -> Union[Optional[VideoFrame], Any]:
  57. """将任意支持格式帧转换为 RGB 帧。"""
  58. if frame.get_format() == OBFormat.RGB:
  59. return frame
  60. convert_format = determine_convert_format(frame)
  61. if convert_format is None:
  62. print("Unsupported format")
  63. return None
  64. print("covert format: {}".format(convert_format))
  65. convert_filter = FormatConvertFilter()
  66. convert_filter.set_format_convert_format(convert_format)
  67. rgb_frame = convert_filter.process(frame)
  68. if rgb_frame is None:
  69. print("Convert {} to RGB failed".format(frame.get_format()))
  70. return rgb_frame
  71. def frame_to_bgr_image(frame: VideoFrame) -> Union[Optional[np.array], Any]:
  72. """将 SDK 视频帧转换为 OpenCV BGR 图像。"""
  73. width = frame.get_width()
  74. height = frame.get_height()
  75. color_format = frame.get_format()
  76. data = np.asanyarray(frame.get_data())
  77. # 默认初始化为全黑图,后续按格式填充。
  78. image = np.zeros((height, width, 3), dtype=np.uint8)
  79. if color_format == OBFormat.RGB:
  80. image = np.resize(data, (height, width, 3))
  81. image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
  82. elif color_format == OBFormat.BGR:
  83. image = np.resize(data, (height, width, 3))
  84. image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
  85. elif color_format == OBFormat.YUYV:
  86. image = np.resize(data, (height, width, 2))
  87. image = cv2.cvtColor(image, cv2.COLOR_YUV2BGR_YUYV)
  88. elif color_format == OBFormat.MJPG:
  89. image = cv2.imdecode(data, cv2.IMREAD_COLOR)
  90. elif color_format == OBFormat.I420:
  91. image = i420_to_bgr(data, width, height)
  92. return image
  93. elif color_format == OBFormat.NV12:
  94. image = nv12_to_bgr(data, width, height)
  95. return image
  96. elif color_format == OBFormat.NV21:
  97. image = nv21_to_bgr(data, width, height)
  98. return image
  99. elif color_format == OBFormat.UYVY:
  100. image = np.resize(data, (height, width, 2))
  101. image = cv2.cvtColor(image, cv2.COLOR_YUV2BGR_UYVY)
  102. else:
  103. print("Unsupported color format: {}".format(color_format))
  104. return None
  105. return image