pyorbbec 1.0.1.33__cp311-cp311-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 (49) hide show
  1. OrbbecSDK.dll +0 -0
  2. OrbbecSDK.lib +0 -0
  3. OrbbecSDKConfig.xml +2332 -0
  4. extensions/depthengine/depthengine.dll +0 -0
  5. extensions/depthengine/depthengine.lib +0 -0
  6. extensions/filters/FilterProcessor.dll +0 -0
  7. extensions/filters/ob_priv_filter.dll +0 -0
  8. extensions/firmwareupdater/firmwareupdater.dll +0 -0
  9. extensions/frameprocessor/ob_frame_processor.dll +0 -0
  10. pyorbbec-1.0.1.33.dist-info/METADATA +11 -0
  11. pyorbbec-1.0.1.33.dist-info/RECORD +49 -0
  12. pyorbbec-1.0.1.33.dist-info/WHEEL +5 -0
  13. pyorbbec-1.0.1.33.dist-info/licenses/LICENSE +202 -0
  14. pyorbbec-1.0.1.33.dist-info/top_level.txt +1 -0
  15. pyorbbecsdk/config/OrbbecSDKConfig.md +222 -0
  16. pyorbbecsdk/config/OrbbecSDKConfig.xml +2332 -0
  17. pyorbbecsdk/config/multi_device_sync_config.json +28 -0
  18. pyorbbecsdk/examples/.gitkeep +0 -0
  19. pyorbbecsdk/examples/README.md +26 -0
  20. pyorbbecsdk/examples/callback.py +303 -0
  21. pyorbbecsdk/examples/color.py +64 -0
  22. pyorbbecsdk/examples/coordinate_transform.py +184 -0
  23. pyorbbecsdk/examples/depth.py +107 -0
  24. pyorbbecsdk/examples/depth_work_mode.py +59 -0
  25. pyorbbecsdk/examples/device_firmware_update.py +155 -0
  26. pyorbbecsdk/examples/device_optional_depth_presets_update.py +142 -0
  27. pyorbbecsdk/examples/enumerate.py +118 -0
  28. pyorbbecsdk/examples/hdr.py +216 -0
  29. pyorbbecsdk/examples/hot_plug.py +160 -0
  30. pyorbbecsdk/examples/hw_d2c_align.py +135 -0
  31. pyorbbecsdk/examples/imu.py +60 -0
  32. pyorbbecsdk/examples/infrared.py +148 -0
  33. pyorbbecsdk/examples/logger.py +55 -0
  34. pyorbbecsdk/examples/metadata.py +64 -0
  35. pyorbbecsdk/examples/multi_device.py +169 -0
  36. pyorbbecsdk/examples/multi_streams.py +219 -0
  37. pyorbbecsdk/examples/net_device.py +177 -0
  38. pyorbbecsdk/examples/playback.py +277 -0
  39. pyorbbecsdk/examples/point_cloud.py +90 -0
  40. pyorbbecsdk/examples/post_processing.py +119 -0
  41. pyorbbecsdk/examples/preset.py +67 -0
  42. pyorbbecsdk/examples/quick_start.py +90 -0
  43. pyorbbecsdk/examples/recorder.py +238 -0
  44. pyorbbecsdk/examples/requirements.txt +8 -0
  45. pyorbbecsdk/examples/save_image_to_disk.py +106 -0
  46. pyorbbecsdk/examples/sync_align.py +109 -0
  47. pyorbbecsdk/examples/two_devices_sync.py +233 -0
  48. pyorbbecsdk/examples/utils.py +127 -0
  49. pyorbbecsdk.cp311-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
Binary file