pyorbbec 1.0.1.25__cp310-cp310-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. OrbbecSDK.dll +0 -0
  2. OrbbecSDK.lib +0 -0
  3. OrbbecSDKConfig-release.cmake +19 -0
  4. OrbbecSDKConfig.cmake +104 -0
  5. OrbbecSDKConfig.xml +2332 -0
  6. extensions/depthengine/depthengine.dll +0 -0
  7. extensions/depthengine/depthengine.lib +0 -0
  8. extensions/filters/FilterProcessor.dll +0 -0
  9. extensions/filters/ob_priv_filter.dll +0 -0
  10. extensions/firmwareupdater/firmwareupdater.dll +0 -0
  11. extensions/frameprocessor/ob_frame_processor.dll +0 -0
  12. pyorbbec/__init__.py +1 -0
  13. pyorbbec/__version__.py +10 -0
  14. pyorbbec/config/OrbbecSDKConfig.md +222 -0
  15. pyorbbec/config/OrbbecSDKConfig.xml +2332 -0
  16. pyorbbec/config/multi_device_sync_config.json +28 -0
  17. pyorbbec/examples/.gitkeep +0 -0
  18. pyorbbec/examples/README.md +26 -0
  19. pyorbbec/examples/callback.py +303 -0
  20. pyorbbec/examples/color.py +64 -0
  21. pyorbbec/examples/coordinate_transform.py +184 -0
  22. pyorbbec/examples/depth.py +107 -0
  23. pyorbbec/examples/depth_work_mode.py +59 -0
  24. pyorbbec/examples/device_firmware_update.py +155 -0
  25. pyorbbec/examples/device_optional_depth_presets_update.py +142 -0
  26. pyorbbec/examples/enumerate.py +118 -0
  27. pyorbbec/examples/hdr.py +216 -0
  28. pyorbbec/examples/hot_plug.py +160 -0
  29. pyorbbec/examples/hw_d2c_align.py +135 -0
  30. pyorbbec/examples/imu.py +60 -0
  31. pyorbbec/examples/infrared.py +148 -0
  32. pyorbbec/examples/logger.py +55 -0
  33. pyorbbec/examples/metadata.py +64 -0
  34. pyorbbec/examples/multi_device.py +169 -0
  35. pyorbbec/examples/multi_streams.py +219 -0
  36. pyorbbec/examples/net_device.py +177 -0
  37. pyorbbec/examples/playback.py +277 -0
  38. pyorbbec/examples/point_cloud.py +90 -0
  39. pyorbbec/examples/post_processing.py +119 -0
  40. pyorbbec/examples/preset.py +67 -0
  41. pyorbbec/examples/quick_start.py +90 -0
  42. pyorbbec/examples/recorder.py +238 -0
  43. pyorbbec/examples/requirements.txt +9 -0
  44. pyorbbec/examples/save_image_to_disk.py +106 -0
  45. pyorbbec/examples/sync_align.py +109 -0
  46. pyorbbec/examples/two_devices_sync.py +233 -0
  47. pyorbbec/examples/utils.py +127 -0
  48. pyorbbec-1.0.1.25.dist-info/METADATA +12 -0
  49. pyorbbec-1.0.1.25.dist-info/RECORD +138 -0
  50. pyorbbec-1.0.1.25.dist-info/WHEEL +5 -0
  51. pyorbbec-1.0.1.25.dist-info/licenses/LICENSE +202 -0
  52. pyorbbec-1.0.1.25.dist-info/licenses/NOTICE +1 -0
  53. pyorbbec-1.0.1.25.dist-info/top_level.txt +1 -0
  54. pyorbbecsdk/OrbbecSDK.dll +0 -0
  55. pyorbbecsdk/OrbbecSDK.lib +0 -0
  56. pyorbbecsdk/OrbbecSDKConfig-release.cmake +19 -0
  57. pyorbbecsdk/OrbbecSDKConfig.cmake +104 -0
  58. pyorbbecsdk/OrbbecSDKConfig.xml +2332 -0
  59. pyorbbecsdk/__init__.py +1 -0
  60. pyorbbecsdk/__version__.py +10 -0
  61. pyorbbecsdk/config/OrbbecSDKConfig.md +222 -0
  62. pyorbbecsdk/config/OrbbecSDKConfig.xml +2332 -0
  63. pyorbbecsdk/config/multi_device_sync_config.json +28 -0
  64. pyorbbecsdk/examples/.gitkeep +0 -0
  65. pyorbbecsdk/examples/README.md +26 -0
  66. pyorbbecsdk/examples/callback.py +303 -0
  67. pyorbbecsdk/examples/color.py +64 -0
  68. pyorbbecsdk/examples/coordinate_transform.py +184 -0
  69. pyorbbecsdk/examples/depth.py +107 -0
  70. pyorbbecsdk/examples/depth_work_mode.py +59 -0
  71. pyorbbecsdk/examples/device_firmware_update.py +155 -0
  72. pyorbbecsdk/examples/device_optional_depth_presets_update.py +142 -0
  73. pyorbbecsdk/examples/enumerate.py +118 -0
  74. pyorbbecsdk/examples/hdr.py +216 -0
  75. pyorbbecsdk/examples/hot_plug.py +160 -0
  76. pyorbbecsdk/examples/hw_d2c_align.py +135 -0
  77. pyorbbecsdk/examples/imu.py +60 -0
  78. pyorbbecsdk/examples/infrared.py +148 -0
  79. pyorbbecsdk/examples/logger.py +55 -0
  80. pyorbbecsdk/examples/metadata.py +64 -0
  81. pyorbbecsdk/examples/multi_device.py +169 -0
  82. pyorbbecsdk/examples/multi_streams.py +219 -0
  83. pyorbbecsdk/examples/net_device.py +177 -0
  84. pyorbbecsdk/examples/playback.py +277 -0
  85. pyorbbecsdk/examples/point_cloud.py +90 -0
  86. pyorbbecsdk/examples/post_processing.py +119 -0
  87. pyorbbecsdk/examples/preset.py +67 -0
  88. pyorbbecsdk/examples/quick_start.py +90 -0
  89. pyorbbecsdk/examples/recorder.py +238 -0
  90. pyorbbecsdk/examples/requirements.txt +9 -0
  91. pyorbbecsdk/examples/save_image_to_disk.py +106 -0
  92. pyorbbecsdk/examples/sync_align.py +109 -0
  93. pyorbbecsdk/examples/two_devices_sync.py +233 -0
  94. pyorbbecsdk/examples/utils.py +127 -0
  95. pyorbbecsdk/extensions/depthengine/depthengine.dll +0 -0
  96. pyorbbecsdk/extensions/depthengine/depthengine.lib +0 -0
  97. pyorbbecsdk/extensions/filters/FilterProcessor.dll +0 -0
  98. pyorbbecsdk/extensions/filters/ob_priv_filter.dll +0 -0
  99. pyorbbecsdk/extensions/firmwareupdater/firmwareupdater.dll +0 -0
  100. pyorbbecsdk/extensions/frameprocessor/ob_frame_processor.dll +0 -0
  101. pyorbbecsdk/pyorbbecsdk/__init__.py +1 -0
  102. pyorbbecsdk/pyorbbecsdk/__version__.py +10 -0
  103. pyorbbecsdk/pyorbbecsdk/config/OrbbecSDKConfig.md +222 -0
  104. pyorbbecsdk/pyorbbecsdk/config/OrbbecSDKConfig.xml +2332 -0
  105. pyorbbecsdk/pyorbbecsdk/config/multi_device_sync_config.json +28 -0
  106. pyorbbecsdk/pyorbbecsdk/examples/.gitkeep +0 -0
  107. pyorbbecsdk/pyorbbecsdk/examples/README.md +26 -0
  108. pyorbbecsdk/pyorbbecsdk/examples/callback.py +303 -0
  109. pyorbbecsdk/pyorbbecsdk/examples/color.py +64 -0
  110. pyorbbecsdk/pyorbbecsdk/examples/coordinate_transform.py +184 -0
  111. pyorbbecsdk/pyorbbecsdk/examples/depth.py +107 -0
  112. pyorbbecsdk/pyorbbecsdk/examples/depth_work_mode.py +59 -0
  113. pyorbbecsdk/pyorbbecsdk/examples/device_firmware_update.py +155 -0
  114. pyorbbecsdk/pyorbbecsdk/examples/device_optional_depth_presets_update.py +142 -0
  115. pyorbbecsdk/pyorbbecsdk/examples/enumerate.py +118 -0
  116. pyorbbecsdk/pyorbbecsdk/examples/hdr.py +216 -0
  117. pyorbbecsdk/pyorbbecsdk/examples/hot_plug.py +160 -0
  118. pyorbbecsdk/pyorbbecsdk/examples/hw_d2c_align.py +135 -0
  119. pyorbbecsdk/pyorbbecsdk/examples/imu.py +60 -0
  120. pyorbbecsdk/pyorbbecsdk/examples/infrared.py +148 -0
  121. pyorbbecsdk/pyorbbecsdk/examples/logger.py +55 -0
  122. pyorbbecsdk/pyorbbecsdk/examples/metadata.py +64 -0
  123. pyorbbecsdk/pyorbbecsdk/examples/multi_device.py +169 -0
  124. pyorbbecsdk/pyorbbecsdk/examples/multi_streams.py +219 -0
  125. pyorbbecsdk/pyorbbecsdk/examples/net_device.py +177 -0
  126. pyorbbecsdk/pyorbbecsdk/examples/playback.py +277 -0
  127. pyorbbecsdk/pyorbbecsdk/examples/point_cloud.py +90 -0
  128. pyorbbecsdk/pyorbbecsdk/examples/post_processing.py +119 -0
  129. pyorbbecsdk/pyorbbecsdk/examples/preset.py +67 -0
  130. pyorbbecsdk/pyorbbecsdk/examples/quick_start.py +90 -0
  131. pyorbbecsdk/pyorbbecsdk/examples/recorder.py +238 -0
  132. pyorbbecsdk/pyorbbecsdk/examples/requirements.txt +9 -0
  133. pyorbbecsdk/pyorbbecsdk/examples/save_image_to_disk.py +106 -0
  134. pyorbbecsdk/pyorbbecsdk/examples/sync_align.py +109 -0
  135. pyorbbecsdk/pyorbbecsdk/examples/two_devices_sync.py +233 -0
  136. pyorbbecsdk/pyorbbecsdk/examples/utils.py +127 -0
  137. pyorbbecsdk/pyorbbecsdk.cp310-win_amd64.pyd +0 -0
  138. pyorbbecsdk.cp310-win_amd64.pyd +0 -0
@@ -0,0 +1,233 @@
1
+ # ******************************************************************************
2
+ # Copyright (c) 2024 Orbbec 3D Technology, Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http:# www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ # ******************************************************************************
16
+ import json
17
+ import os
18
+ from queue import Queue
19
+ from typing import List
20
+
21
+ import cv2
22
+ import numpy as np
23
+
24
+ from pyorbbecsdk import *
25
+ from utils import frame_to_bgr_image
26
+
27
+ MAX_DEVICES = 2
28
+ curr_device_cnt = 0
29
+
30
+ MAX_QUEUE_SIZE = 5
31
+ ESC_KEY = 27
32
+
33
+ color_frames_queue: List[Queue] = [Queue() for _ in range(MAX_DEVICES)]
34
+ depth_frames_queue: List[Queue] = [Queue() for _ in range(MAX_DEVICES)]
35
+ serial_number_list: List[str] = ["" for _ in range(MAX_DEVICES)]
36
+ has_color_sensor: List[bool] = [False for _ in range(MAX_DEVICES)]
37
+ stop_rendering = False
38
+ multi_device_sync_config = {}
39
+ # config_file_path current file path
40
+ config_file_path = os.path.join(
41
+ os.path.abspath(os.path.dirname(__file__)),
42
+ "../config/multi_device_sync_config.json",
43
+ )
44
+
45
+
46
+ def sync_mode_from_str(sync_mode_str: str) -> OBMultiDeviceSyncMode:
47
+ # to lower case
48
+ sync_mode_str = sync_mode_str.upper()
49
+ if sync_mode_str == "FREE_RUN":
50
+ return OBMultiDeviceSyncMode.FREE_RUN
51
+ elif sync_mode_str == "STANDALONE":
52
+ return OBMultiDeviceSyncMode.STANDALONE
53
+ elif sync_mode_str == "PRIMARY":
54
+ return OBMultiDeviceSyncMode.PRIMARY
55
+ elif sync_mode_str == "SECONDARY":
56
+ return OBMultiDeviceSyncMode.SECONDARY
57
+ elif sync_mode_str == "SECONDARY_SYNCED":
58
+ return OBMultiDeviceSyncMode.SECONDARY_SYNCED
59
+ elif sync_mode_str == "SOFTWARE_TRIGGERING":
60
+ return OBMultiDeviceSyncMode.SOFTWARE_TRIGGERING
61
+ elif sync_mode_str == "HARDWARE_TRIGGERING":
62
+ return OBMultiDeviceSyncMode.HARDWARE_TRIGGERING
63
+ else:
64
+ raise ValueError(f"Invalid sync mode: {sync_mode_str}")
65
+
66
+
67
+ def on_new_frame_callback(frames: FrameSet, index: int):
68
+ global color_frames_queue, depth_frames_queue
69
+ global MAX_QUEUE_SIZE
70
+ assert index < MAX_DEVICES
71
+ color_frame = frames.get_color_frame()
72
+ depth_frame = frames.get_depth_frame()
73
+ if color_frame is not None:
74
+ if color_frames_queue[index].qsize() >= MAX_QUEUE_SIZE:
75
+ color_frames_queue[index].get()
76
+ color_frames_queue[index].put(color_frame)
77
+ if depth_frame is not None:
78
+ if depth_frames_queue[index].qsize() >= MAX_QUEUE_SIZE:
79
+ depth_frames_queue[index].get()
80
+ depth_frames_queue[index].put(depth_frame)
81
+
82
+
83
+ def rendering_frames():
84
+ global color_frames_queue, depth_frames_queue
85
+ global curr_device_cnt
86
+ global stop_rendering
87
+ global serial_number_list
88
+ while not stop_rendering:
89
+ for i in range(curr_device_cnt):
90
+ color_frame = None
91
+ depth_frame = None
92
+ if not color_frames_queue[i].empty():
93
+ color_frame = color_frames_queue[i].get()
94
+ if not depth_frames_queue[i].empty():
95
+ depth_frame = depth_frames_queue[i].get()
96
+ if color_frame is None and depth_frame is None:
97
+ continue
98
+
99
+ # print serial number, color timestamp, depth timestamp, break line
100
+ if color_frame is not None:
101
+ print(f"device#{i}, color frame timestamp: {color_frame.get_timestamp_us()} us , system timestamp: {color_frame.get_system_timestamp_us()} us")
102
+ if depth_frame is not None:
103
+ print(f"device#{i}, depth frame timestamp: {depth_frame.get_timestamp_us()} us , system timestamp: {depth_frame.get_system_timestamp_us()} us")
104
+ color_image = None
105
+ depth_image = None
106
+ color_width, color_height = 0, 0
107
+ if color_frame is not None:
108
+ color_width, color_height = (
109
+ color_frame.get_width(),
110
+ color_frame.get_height(),
111
+ )
112
+ color_image = frame_to_bgr_image(color_frame)
113
+ if depth_frame is not None:
114
+ width = depth_frame.get_width()
115
+ height = depth_frame.get_height()
116
+ scale = depth_frame.get_depth_scale()
117
+ depth_format = depth_frame.get_format()
118
+ if depth_format != OBFormat.Y16:
119
+ print("depth format is not Y16")
120
+ continue
121
+ depth_data = np.frombuffer(depth_frame.get_data(), dtype=np.uint16)
122
+ depth_data = depth_data.reshape((height, width))
123
+
124
+ depth_data = depth_data.astype(np.float32) * scale
125
+
126
+ depth_image = cv2.normalize(
127
+ depth_data, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U
128
+ )
129
+ depth_image = cv2.applyColorMap(depth_image, cv2.COLORMAP_JET)
130
+
131
+ if color_image is not None and depth_image is not None:
132
+ window_size = (color_width // 2, color_height // 2)
133
+ color_image = cv2.resize(color_image, window_size)
134
+ depth_image = cv2.resize(depth_image, window_size)
135
+ image = np.hstack((color_image, depth_image))
136
+ elif depth_image is not None and not has_color_sensor[i]:
137
+ image = depth_image
138
+ else:
139
+ continue
140
+ cv2.imshow("Device {}".format(i), image)
141
+ key = cv2.waitKey(1)
142
+ if key == ord("q") or key == ESC_KEY:
143
+ return
144
+
145
+
146
+ def start_streams(pipelines: List[Pipeline], configs: List[Config]):
147
+ index = 0
148
+ for pipeline, config in zip(pipelines, configs):
149
+ pipeline.start(
150
+ config,
151
+ lambda frame_set, curr_index=index: on_new_frame_callback(
152
+ frame_set, curr_index
153
+ ),
154
+ )
155
+ index += 1
156
+
157
+
158
+ def stop_streams(pipelines: List[Pipeline]):
159
+ for pipeline in pipelines:
160
+ pipeline.stop()
161
+
162
+
163
+ def read_config(config_file: str):
164
+ global multi_device_sync_config
165
+ with open(config_file, "r") as f:
166
+ config = json.load(f)
167
+ for device in config["devices"]:
168
+ multi_device_sync_config[device["serial_number"]] = device
169
+ print(f"Device {device['serial_number']}: {device['config']['mode']}")
170
+
171
+
172
+ def main():
173
+ global config_file_path
174
+ read_config(config_file_path)
175
+ ctx = Context()
176
+ device_list = ctx.query_devices()
177
+ global curr_device_cnt
178
+ curr_device_cnt = device_list.get_count()
179
+ if curr_device_cnt == 0:
180
+ print("No device connected")
181
+ return
182
+ if curr_device_cnt > MAX_DEVICES:
183
+ print("Too many devices connected")
184
+ return
185
+ pipelines: List[Pipeline] = []
186
+ configs: List[Config] = []
187
+ global has_color_sensor
188
+ for i in range(device_list.get_count()):
189
+ device = device_list.get_device_by_index(i)
190
+ pipeline = Pipeline(device)
191
+ config = Config()
192
+ serial_number = device.get_device_info().get_serial_number()
193
+ serial_number_list[i] = serial_number
194
+ sync_config_json = multi_device_sync_config[serial_number]
195
+ sync_config = device.get_multi_device_sync_config()
196
+ sync_config.mode = sync_mode_from_str(sync_config_json["config"]["mode"])
197
+ sync_config.color_delay_us = sync_config_json["config"]["color_delay_us"]
198
+ sync_config.depth_delay_us = sync_config_json["config"]["depth_delay_us"]
199
+ sync_config.trigger_out_enable = sync_config_json["config"]["trigger_out_enable"]
200
+ sync_config.trigger_out_delay_us = sync_config_json["config"]["trigger_out_delay_us"]
201
+ sync_config.frames_per_trigger = sync_config_json["config"]["frames_per_trigger"]
202
+ print(f"Device {serial_number} sync config: {sync_config}")
203
+ device.set_multi_device_sync_config(sync_config)
204
+ try:
205
+ profile_list = pipeline.get_stream_profile_list(OBSensorType.COLOR_SENSOR)
206
+ color_profile: VideoStreamProfile = (
207
+ profile_list.get_default_video_stream_profile()
208
+ )
209
+ config.enable_stream(color_profile)
210
+ has_color_sensor[i] = True
211
+ except OBError as e:
212
+ print(e)
213
+ has_color_sensor[i] = False
214
+ profile_list = pipeline.get_stream_profile_list(OBSensorType.DEPTH_SENSOR)
215
+ depth_profile = profile_list.get_default_video_stream_profile()
216
+ config.enable_stream(depth_profile)
217
+ config.enable_stream(depth_profile)
218
+ pipelines.append(pipeline)
219
+ configs.append(config)
220
+ global stop_rendering
221
+ start_streams(pipelines, configs)
222
+ ctx.enable_multi_device_sync(60000)
223
+ try:
224
+ rendering_frames()
225
+ stop_streams(pipelines)
226
+ except KeyboardInterrupt:
227
+ stop_rendering = True
228
+ stop_streams(pipelines)
229
+ cv2.destroyAllWindows()
230
+
231
+
232
+ if __name__ == "__main__":
233
+ main()
@@ -0,0 +1,127 @@
1
+ # ******************************************************************************
2
+ # Copyright (c) 2024 Orbbec 3D Technology, Inc
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http:# www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ # ******************************************************************************
16
+ from typing import Union, Any, Optional
17
+
18
+ import cv2
19
+ import numpy as np
20
+
21
+ from pyorbbecsdk import FormatConvertFilter, VideoFrame
22
+ from pyorbbecsdk import OBFormat, OBConvertFormat
23
+
24
+
25
+ def yuyv_to_bgr(frame: np.ndarray, width: int, height: int) -> np.ndarray:
26
+ yuyv = frame.reshape((height, width, 2))
27
+ bgr_image = cv2.cvtColor(yuyv, cv2.COLOR_YUV2BGR_YUY2)
28
+ return bgr_image
29
+
30
+
31
+ def uyvy_to_bgr(frame: np.ndarray, width: int, height: int) -> np.ndarray:
32
+ uyvy = frame.reshape((height, width, 2))
33
+ bgr_image = cv2.cvtColor(uyvy, cv2.COLOR_YUV2BGR_UYVY)
34
+ return bgr_image
35
+
36
+
37
+ def i420_to_bgr(frame: np.ndarray, width: int, height: int) -> np.ndarray:
38
+ y = frame[0:height, :]
39
+ u = frame[height:height + height // 4].reshape(height // 2, width // 2)
40
+ v = frame[height + height // 4:].reshape(height // 2, width // 2)
41
+ yuv_image = cv2.merge([y, u, v])
42
+ bgr_image = cv2.cvtColor(yuv_image, cv2.COLOR_YUV2BGR_I420)
43
+ return bgr_image
44
+
45
+
46
+ def nv21_to_bgr(frame: np.ndarray, width: int, height: int) -> np.ndarray:
47
+ y = frame[0:height, :]
48
+ uv = frame[height:height + height // 2].reshape(height // 2, width)
49
+ yuv_image = cv2.merge([y, uv])
50
+ bgr_image = cv2.cvtColor(yuv_image, cv2.COLOR_YUV2BGR_NV21)
51
+ return bgr_image
52
+
53
+
54
+ def nv12_to_bgr(frame: np.ndarray, width: int, height: int) -> np.ndarray:
55
+ y = frame[0:height, :]
56
+ uv = frame[height:height + height // 2].reshape(height // 2, width)
57
+ yuv_image = cv2.merge([y, uv])
58
+ bgr_image = cv2.cvtColor(yuv_image, cv2.COLOR_YUV2BGR_NV12)
59
+ return bgr_image
60
+
61
+
62
+ def determine_convert_format(frame: VideoFrame):
63
+ if frame.get_format() == OBFormat.I420:
64
+ return OBConvertFormat.I420_TO_RGB888
65
+ elif frame.get_format() == OBFormat.MJPG:
66
+ return OBConvertFormat.MJPG_TO_RGB888
67
+ elif frame.get_format() == OBFormat.YUYV:
68
+ return OBConvertFormat.YUYV_TO_RGB888
69
+ elif frame.get_format() == OBFormat.NV21:
70
+ return OBConvertFormat.NV21_TO_RGB888
71
+ elif frame.get_format() == OBFormat.NV12:
72
+ return OBConvertFormat.NV12_TO_RGB888
73
+ elif frame.get_format() == OBFormat.UYVY:
74
+ return OBConvertFormat.UYVY_TO_RGB888
75
+ else:
76
+ return None
77
+
78
+
79
+ def frame_to_rgb_frame(frame: VideoFrame) -> Union[Optional[VideoFrame], Any]:
80
+ if frame.get_format() == OBFormat.RGB:
81
+ return frame
82
+ convert_format = determine_convert_format(frame)
83
+ if convert_format is None:
84
+ print("Unsupported format")
85
+ return None
86
+ print("covert format: {}".format(convert_format))
87
+ convert_filter = FormatConvertFilter()
88
+ convert_filter.set_format_convert_format(convert_format)
89
+ rgb_frame = convert_filter.process(frame)
90
+ if rgb_frame is None:
91
+ print("Convert {} to RGB failed".format(frame.get_format()))
92
+ return rgb_frame
93
+
94
+
95
+ def frame_to_bgr_image(frame: VideoFrame) -> Union[Optional[np.array], Any]:
96
+ width = frame.get_width()
97
+ height = frame.get_height()
98
+ color_format = frame.get_format()
99
+ data = np.asanyarray(frame.get_data())
100
+ image = np.zeros((height, width, 3), dtype=np.uint8)
101
+ if color_format == OBFormat.RGB:
102
+ image = np.resize(data, (height, width, 3))
103
+ image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
104
+ elif color_format == OBFormat.BGR:
105
+ image = np.resize(data, (height, width, 3))
106
+ image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
107
+ elif color_format == OBFormat.YUYV:
108
+ image = np.resize(data, (height, width, 2))
109
+ image = cv2.cvtColor(image, cv2.COLOR_YUV2BGR_YUYV)
110
+ elif color_format == OBFormat.MJPG:
111
+ image = cv2.imdecode(data, cv2.IMREAD_COLOR)
112
+ elif color_format == OBFormat.I420:
113
+ image = i420_to_bgr(data, width, height)
114
+ return image
115
+ elif color_format == OBFormat.NV12:
116
+ image = nv12_to_bgr(data, width, height)
117
+ return image
118
+ elif color_format == OBFormat.NV21:
119
+ image = nv21_to_bgr(data, width, height)
120
+ return image
121
+ elif color_format == OBFormat.UYVY:
122
+ image = np.resize(data, (height, width, 2))
123
+ image = cv2.cvtColor(image, cv2.COLOR_YUV2BGR_UYVY)
124
+ else:
125
+ print("Unsupported color format: {}".format(color_format))
126
+ return None
127
+ return image
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,10 @@
1
+ __title__ = "pyorbbecsdk"
2
+ __description__ = "Python interface to the Orbbec SDK."
3
+ __url__ = "https://orbbec.com.cn/"
4
+ __version__ = "1.0.0"
5
+ __build__ = 0x023203
6
+ __author__ = "orbbec"
7
+ __author_email__ = "lijie@orbbec.com"
8
+ __license__ = "Apache License"
9
+ __copyright__ = "Copyright Orbbec"
10
+ __cake__ = "\u2728 \U0001f370 \u2728"
@@ -0,0 +1,222 @@
1
+ # Orbbec SDK Configuration File Introduction (OrbbecSDKConfig_v1.0.xml)
2
+
3
+ The Orbbec SDK configuration file is an XML file that defines the global configuration of the Orbbec SDK.
4
+
5
+ Upon initialization, the SDK Context will load a configuration file and apply as global configurations. If you have your own configuration file, you can specify it by entering the file path when calling the Context constructor. If you don't provide a path (or input an empty string), the SDK will look for a file named `OrbbecSDKConfig.xml` in the working directory. If neither the specified file nor the default file is found, the SDK will revert to using the built-in default configuration file.
6
+
7
+ ## Log Configuration
8
+
9
+ Log configuration mainly sets the Log level, the Log level output to the console, the Log level output to a file, configures the path for saving Log files, sets the size of each Log file, and sets the number of Log files.
10
+
11
+ ```cpp
12
+ <Log>
13
+ <!--Log output level, int type, optional values: 0-DEBUG, 1-INFO, 2-WARN, 3-ERROR, 4-FATAL, 5-OFF-->
14
+ <!--Log level configuration execution priority: 0. Application code configuration > 1. Detailed configuration of configuration file (file & console configuration) > 2. Global configuration of configuration file > 3. SDK code default configuration (file: 0, terminal: 1)-->
15
+ <!--Global log output level-->
16
+ <LogLevel>0</LogLevel>
17
+ <!--File log output level-->
18
+ <FileLogLevel>0</FileLogLevel>
19
+ <!--Console log output level-->
20
+ <ConsoleLogLevel>1</ConsoleLogLevel>
21
+ <!--Default log output file path, string type. If this item is not configured, the default path will be used: Win/Linux: "./Log"; Android: "/sdcard/Orbbec/Log"-->
22
+ <!--<OutputDir>./log</OutputDir>-->
23
+ <!--Default log output file size, int type, unit: MB-->
24
+ <MaxFileSize>100</MaxFileSize>
25
+ <!--Default log output file number (circular overwrite), int type-->
26
+ <MaxFileNum>3</MaxFileNum>
27
+ <!--Log asynchronous output, changing to asynchronous output can reduce the blocking time of printing logs, but some logs may be lost when the program exits abnormally; true-enable, false-disable (default)-->
28
+ <Async>false</Async>
29
+ </Log>
30
+ ```
31
+
32
+ ## Memory Configuration
33
+
34
+ ```cpp
35
+ <Memory>
36
+ <!--Enable memory pool to reuse frame memory, avoid frequent memory allocation and release. true-enable, false-disable)-->
37
+ <EnableMemoryPool> true </EnableMemoryPool>
38
+ <!--Maximum memory size of all data frames, int type, unit: MB, minimum 100MB-->
39
+ <MaxFrameBufferSize> 2048 </MaxFrameBufferSize>
40
+ <!--Frame buffer queue size in pipeline-->
41
+ <PipelineFrameQueueSize>10</PipelineFrameQueueSize>
42
+ <!--Frame buffer queue size in internal processing unit-->
43
+ <FrameProcessingBlockQueueSize>10</FrameProcessingBlockQueueSize>
44
+ </Memory>
45
+ ```
46
+
47
+ **Notes**
48
+
49
+ 1. The default size of the memory pool is 2GB (2048MB).
50
+ ```cpp
51
+ <MaxFrameBufferSize> 2048 </MaxFrameBufferSize>
52
+ ```
53
+ 2. The default number of frame buffere queue in the Pipeline is 10. If the host machine processes slowly, the SDK will buffer up to 10 frames internally, which may affect the delay time in retrieving frames by the user. If the delay is significant, you can reduce the number of buffers.
54
+ ```cpp
55
+ <PipelineFrameQueueSize>10</PipelineFrameQueueSize>
56
+ ```
57
+
58
+ 3. The default number of queues in the internal processing unit (Processing unit) is 10. If the host machine processes slowly, the SDK will buffer up to 10 frames internally, which may affect the delay time in retrieving frames by the user. If the delay is significant, you can reduce the number of queues.
59
+ ```cpp
60
+ <FrameProcessingBlockQueueSize>10</FrameProcessingBlockQueueSize>
61
+ ```
62
+
63
+ ## Global Timestamp
64
+
65
+ Based on the device's timestamp and considering data transmission delays, the timestamp is converted to the system timestamp dimension through linear regression. It can be used to synchronize timestamps of multiple different devices. The implementation plan is as follows:
66
+
67
+ 1. Global timestamp fitter: Regularly obtain the device timestamp and the current system timestamp, and calculate the fitting equation parameters using a linear regression method.
68
+ 2. Global timestamp converter: Convert the data frame timestamp unit to the same unit as the device timestamp, then calculate the overflow times according to the device timestamp to convert to a 64-bit timestamp, and then convert to a global timestamp according to the fitting parameters output by the global timestamp fitter.
69
+
70
+ ```cpp
71
+ <Misc>
72
+ <GlobalTimestampFitterEnable>true</GlobalTimestampFitterEnable>
73
+ <!--Global timestamp fitter refresh interval, unit: milliseconds, default value: 1000, minimum value: 100, it is recommended not to be greater than 1000 -->
74
+ <GlobalTimestampFitterInterval>1000</GlobalTimestampFitterInterval>
75
+ <!--Global timestamp fitter queue size, default value: 100, minimum value: 20 -->
76
+ <GlobalTimestampFitterQueueSize>100</GlobalTimestampFitterQueueSize>
77
+ </Misc>
78
+ ```
79
+
80
+ 1. By default, the device time is obtained every eight seconds to update the global timestamp fitter.
81
+ ```cpp
82
+ <GlobalTimestampFitterInterval>1000</GlobalTimestampFitterInterval>
83
+ ```
84
+
85
+ 2. The default queue size of the global timestamp fitter is 10.
86
+ ```cpp
87
+ <GlobalTimestampFitterQueueSize>100</GlobalTimestampFitterQueueSize>
88
+ ```
89
+
90
+ **Notes**
91
+
92
+ 1. The global timestamp mainly supports the Gemini 330 series. Gemini 2, Gemini 2L, Femto Mega, and Femto Bolt are also supported but not thoroughly tested. If there are stability issues with these devices, the global timestamp function can be turned off.
93
+ ```cpp
94
+ <GlobalTimestampFitterEnable>false</GlobalTimestampFitterEnable>
95
+ ```
96
+
97
+ ## Pipeline Configuration
98
+
99
+ ```cpp
100
+ <!--Default working configuration of pipeline-->
101
+ <Pipeline>
102
+ <Stream>
103
+ <Depth>
104
+ <!--Use default stream profile, bool type, true: use default stream profile, false: use specified stream profile in the configuration file-->
105
+ <UseDefaultStreamProfile>true</UseDefaultStreamProfile>
106
+ </Depth>
107
+ <Color>
108
+ <UseDefaultStreamProfile>true</UseDefaultStreamProfile>
109
+ </Color>
110
+ <!--If you need to open other streams, you can refer to the above format to add configuration-->
111
+ </Stream>
112
+ <!--Image alignment, int type, optional values: 0 disable, 1 hardware d2c alignment, 2 software d2c alignment-->
113
+ <AlignMode>0</AlignMode>
114
+ <!--Frame synchronization output between different data streams, bool type, true-enable frame synchronization, false-disable frame synchronization-->
115
+ <FrameSync>false</FrameSync>
116
+ </Pipeline>
117
+ ```
118
+
119
+ 1. Pipeline primarily sets which video streams to enable. By default, only Depth and Color streams are enabled. You can add to enable IR streams, left IR, and right IR as follows.
120
+ ```cpp
121
+ <!--If you need to open other streams, you can refer to the above format to add configuration-->
122
+ <IR>
123
+ <UseDefaultStreamProfile>true</UseDefaultStreamProfile>
124
+ </IR>
125
+ <LeftIR>
126
+ <UseDefaultStreamProfile>true</UseDefaultStreamProfile>
127
+ </LeftIR>
128
+ <RightIR>
129
+ <UseDefaultStreamProfile>true</UseDefaultStreamProfile>
130
+ </RightIR>
131
+ ```
132
+ 2. Pipeline can set D2C, such as hardware D2C and software D2C. Some devices do not support hardware D2C, such as Femto Bolt. If you need to use various different types of devices, it is recommended to set this in the user code based on the device type.
133
+ ```cpp
134
+ <AlignMode>0</AlignMode>
135
+ ```
136
+ 3. Pipeline can set frame synchronization. Enabling frame synchronization will match Depth, Color, and other video frames based on the timestamp and output them as FrameSet within the Pipeline.
137
+ ```cpp
138
+ <FrameSync>false</FrameSync>
139
+ ```
140
+
141
+ ## Device Configuration
142
+
143
+ ```cpp
144
+ <!--Default configuration of data streams for different types of devices-->
145
+ <Device>
146
+ <EnumerateNetDevice>false</EnumerateNetDevice>
147
+ <!--UVC Backend select on Linux; optional values: Auto, V4L2, LibUVC; Auto is the default value-->
148
+ <LinuxUVCBackend>LibUVC</LinuxUVCBackend>
149
+
150
+ <!--Gemini 335 config-->
151
+ <Gemini335>
152
+ <!--Whether to enable heartbeat by default-->
153
+ <DefaultHeartBeat>0</DefaultHeartBeat>
154
+
155
+ <Depth>
156
+ <!--Number of retries for open stream failures, 0 means no retries-->
157
+ <StreamFailedRetry>0</StreamFailedRetry>
158
+ <!--Open flow waits for the timeout period of the first frame of data, after which the open flow will fail-->
159
+ <MaxStartStreamDelayMs>5000</MaxStartStreamDelayMs>
160
+ <!--The number of data stream restarts due to abnormal interruption, 0 means no restart-->
161
+ <StreamInterruptedRestart>0</StreamInterruptedRestart>
162
+ <!--The maximum frame interval time, if this value is exceeded, it will be judged that the stream is interrupted-->
163
+ <MaxFrameIntervalMs>2000</MaxFrameIntervalMs>
164
+ <!--The resolution width is enabled by default, int type-->
165
+ <Width>848</Width>
166
+ <!--High resolution is enabled by default, int type-->
167
+ <Height>480</Height>
168
+ <!--The frame rate of the resolution enabled by default, int type-->
169
+ <FPS>30</FPS>
170
+ <Format>Y16</Format>
171
+ </Depth>
172
+ <Color>
173
+ <!--The resolution width is enabled by default, int type-->
174
+ <Width>1280</Width>
175
+ <!--High resolution is enabled by default, int type-->
176
+ <Height>720</Height>
177
+ <!--The frame rate of the resolution enabled by default, int type-->
178
+ <FPS>30</FPS>
179
+ <Format>MJPG</Format>
180
+ </Color>
181
+ <IR>
182
+ <!--The resolution width is enabled by default, int type-->
183
+ <Width>848</Width>
184
+ <!--High resolution is enabled by default, int type-->
185
+ <Height>480</Height>
186
+ <!--The frame rate of the resolution enabled by default, int type-->
187
+ <FPS>30</FPS>
188
+ <Format>Y8</Format>
189
+ </IR>
190
+ <LeftIR>
191
+ <!--The resolution width is enabled by default, int type-->
192
+ <Width>848</Width>
193
+ <!--High resolution is enabled by default, int type-->
194
+ <Height>480</Height>
195
+ <!--The frame rate of the resolution enabled by default, int type-->
196
+ <FPS>30</FPS>
197
+ <Format>Y8</Format>
198
+ </LeftIR>
199
+ <RightIR>
200
+ <!--The resolution width is enabled by default, int type-->
201
+ <Width>848</Width>
202
+ <!--High resolution is enabled by default, int type-->
203
+ <Height>480</Height>
204
+ <!--The frame rate of the resolution enabled by default, int type-->
205
+ <FPS>30</FPS>
206
+ <Format>Y8</Format>
207
+ </RightIR>
208
+ </Gemini335>
209
+ </Device>
210
+ ```
211
+
212
+ 1. Set whether to enumerate network devices. Femto Mega and Gemini 2 XL support network functions. If you need to use the network functions of these two devices, you can set this to true.
213
+ ```cpp
214
+ <EnumerateNetDevice>false</EnumerateNetDevice>
215
+ ```
216
+
217
+ 2. Set whether to use LibUVC or V4L2 to receive data on Linux or ARM. V4L2 is not supported by all devices, and we recommend using LibUVC. The Gemini 330 series devices support V4L2, but kernel patches are needed to obtain Metadata data.
218
+ ```cpp
219
+ <LinuxUVCBackend>LibUVC</LinuxUVCBackend>
220
+ ```
221
+
222
+ 3. Set the resolution, frame rate, and data format.