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,67 @@
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
+
17
+ import pyorbbecsdk as ob
18
+
19
+ def main():
20
+ # Create a pipeline with default device
21
+ pipe = ob.Pipeline()
22
+
23
+ # Get the device from the pipeline
24
+ device = pipe.get_device()
25
+
26
+ try:
27
+ while True:
28
+ # Get preset list from device
29
+ preset_list = device.get_available_preset_list()
30
+ if len(preset_list) == 0:
31
+ print("The current device does not support preset mode")
32
+ break
33
+
34
+ print("\nAvailable Presets:")
35
+ for index in range(len(preset_list)):
36
+ print(f" - {index}. {preset_list[index]}")
37
+
38
+ # Print current preset name
39
+ print(f"\nCurrent PresetName: {device.get_current_preset_name()}")
40
+
41
+ # Select preset to load
42
+ try:
43
+ input_option = int(input("\nEnter index of preset to load (or -1 to exit): "))
44
+ if input_option == -1:
45
+ break
46
+ if input_option < 0 or input_option >= len(preset_list):
47
+ raise ValueError("Invalid index")
48
+ except ValueError:
49
+ print("Invalid input. Please enter a valid index.")
50
+ continue
51
+
52
+ preset_name = preset_list[input_option]
53
+
54
+ # Load preset
55
+ device.load_preset(preset_name)
56
+
57
+ # Print current preset name
58
+ print(f"\nPreset loaded. Current PresetName: {device.get_current_preset_name()}")
59
+
60
+ except ob.OBError as e:
61
+ print(f"Error: {str(e)}")
62
+ finally:
63
+ # Stop Pipeline
64
+ pipe.stop()
65
+
66
+ if __name__ == "__main__":
67
+ main()
@@ -0,0 +1,90 @@
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
+
17
+ import cv2
18
+ import numpy as np
19
+ import time
20
+
21
+ from pyorbbecsdk import *
22
+ from utils import frame_to_bgr_image
23
+
24
+ ESC_KEY = 27
25
+ MIN_DEPTH = 20 # 20mm
26
+ MAX_DEPTH = 10000 # 10000mm
27
+
28
+ def main():
29
+ pipeline = Pipeline()
30
+
31
+ pipeline.start()
32
+ print("Pipeline started successfully. Press 'q' or ESC to exit.")
33
+
34
+ # Set window size
35
+ window_width = 1280
36
+ window_height = 720
37
+ cv2.namedWindow("QuickStart Viewer", cv2.WINDOW_NORMAL)
38
+ cv2.resizeWindow("QuickStart Viewer", window_width, window_height)
39
+
40
+ while True:
41
+ try:
42
+ frames = pipeline.wait_for_frames(100)
43
+ if frames is None:
44
+ continue
45
+
46
+ # Get color frame
47
+ color_frame = frames.get_color_frame()
48
+ if color_frame is None:
49
+ continue
50
+ color_image = frame_to_bgr_image(color_frame)
51
+
52
+ # Get depth frame
53
+ depth_frame = frames.get_depth_frame()
54
+ if depth_frame is None:
55
+ continue
56
+ if depth_frame.get_format() != OBFormat.Y16:
57
+ print("Depth format is not Y16")
58
+ continue
59
+
60
+ # Process depth data
61
+ width = depth_frame.get_width()
62
+ height = depth_frame.get_height()
63
+ scale = depth_frame.get_depth_scale()
64
+
65
+ depth_data = np.frombuffer(depth_frame.get_data(), dtype=np.uint16).reshape((height, width))
66
+ depth_data = depth_data.astype(np.float32) * scale
67
+ depth_data = np.where((depth_data > MIN_DEPTH) & (depth_data < MAX_DEPTH), depth_data, 0).astype(np.uint16)
68
+
69
+ # Create depth visualization
70
+ depth_image = cv2.normalize(depth_data, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)
71
+ depth_image = cv2.applyColorMap(depth_image, cv2.COLORMAP_JET)
72
+
73
+ # Resize and combine images
74
+ color_image_resized = cv2.resize(color_image, (window_width // 2, window_height))
75
+ depth_image_resized = cv2.resize(depth_image, (window_width // 2, window_height))
76
+ combined_image = np.hstack((color_image_resized, depth_image_resized))
77
+
78
+ cv2.imshow("QuickStart Viewer", combined_image)
79
+
80
+ if cv2.waitKey(1) in [ord('q'), ESC_KEY]:
81
+ break
82
+ except KeyboardInterrupt:
83
+ break
84
+
85
+ cv2.destroyAllWindows()
86
+ pipeline.stop()
87
+ print("Pipeline stopped and all windows closed.")
88
+
89
+ if __name__ == "__main__":
90
+ main()
@@ -0,0 +1,238 @@
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
+
17
+ import cv2
18
+ import numpy as np
19
+ from pyorbbecsdk import *
20
+ from utils import frame_to_bgr_image
21
+
22
+ is_paused = False
23
+ # cached frames for better visualization
24
+ cached_frames = {
25
+ 'color': None,
26
+ 'depth': None,
27
+ 'left_ir': None,
28
+ 'right_ir': None,
29
+ 'ir': None
30
+ }
31
+
32
+ def setup_camera():
33
+ """Setup camera and stream configuration"""
34
+ pipeline = Pipeline()
35
+ config = Config()
36
+ device = pipeline.get_device()
37
+
38
+ # Try to enable all possible sensors
39
+ video_sensors = [
40
+ OBSensorType.COLOR_SENSOR,
41
+ OBSensorType.DEPTH_SENSOR,
42
+ OBSensorType.IR_SENSOR,
43
+ OBSensorType.LEFT_IR_SENSOR,
44
+ OBSensorType.RIGHT_IR_SENSOR
45
+ ]
46
+ sensor_list = device.get_sensor_list()
47
+ for sensor in range(len(sensor_list)):
48
+ try:
49
+ sensor_type = sensor_list[sensor].get_type()
50
+ if sensor_type in video_sensors:
51
+ config.enable_stream(sensor_type)
52
+ except:
53
+ continue
54
+
55
+ pipeline.start(config)
56
+ return pipeline
57
+
58
+ def setup_imu():
59
+ """Setup IMU configuration"""
60
+ pipeline = Pipeline()
61
+ config = Config()
62
+ config.enable_accel_stream()
63
+ config.enable_gyro_stream()
64
+ pipeline.start(config)
65
+ return pipeline
66
+
67
+ def process_color(frame):
68
+ """Process color image"""
69
+ frame = frame if frame else cached_frames['color']
70
+ cached_frames['color'] = frame
71
+ return frame_to_bgr_image(frame) if frame else None
72
+
73
+
74
+ def process_depth(frame):
75
+ """Process depth image"""
76
+ frame = frame if frame else cached_frames['depth']
77
+ cached_frames['depth'] = frame
78
+ if not frame:
79
+ return None
80
+ try:
81
+ depth_data = np.frombuffer(frame.get_data(), dtype=np.uint16)
82
+ depth_data = depth_data.reshape(frame.get_height(), frame.get_width())
83
+ depth_image = cv2.normalize(depth_data, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)
84
+ return cv2.applyColorMap(depth_image, cv2.COLORMAP_JET)
85
+ except ValueError:
86
+ return None
87
+
88
+
89
+ def process_ir(ir_frame):
90
+ """Process IR frame (left or right) to RGB image"""
91
+ if ir_frame is None:
92
+ return None
93
+ ir_frame = ir_frame.as_video_frame()
94
+ ir_data = np.asanyarray(ir_frame.get_data())
95
+ width = ir_frame.get_width()
96
+ height = ir_frame.get_height()
97
+ ir_format = ir_frame.get_format()
98
+
99
+ if ir_format == OBFormat.Y8:
100
+ ir_data = np.resize(ir_data, (height, width, 1))
101
+ data_type = np.uint8
102
+ image_dtype = cv2.CV_8UC1
103
+ max_data = 255
104
+ elif ir_format == OBFormat.MJPG:
105
+ ir_data = cv2.imdecode(ir_data, cv2.IMREAD_UNCHANGED)
106
+ data_type = np.uint8
107
+ image_dtype = cv2.CV_8UC1
108
+ max_data = 255
109
+ if ir_data is None:
110
+ print("decode mjpeg failed")
111
+ return None
112
+ ir_data = np.resize(ir_data, (height, width, 1))
113
+ else:
114
+ ir_data = np.frombuffer(ir_data, dtype=np.uint16)
115
+ data_type = np.uint16
116
+ image_dtype = cv2.CV_16UC1
117
+ max_data = 255
118
+ ir_data = np.resize(ir_data, (height, width, 1))
119
+
120
+ cv2.normalize(ir_data, ir_data, 0, max_data, cv2.NORM_MINMAX, dtype=image_dtype)
121
+ ir_data = ir_data.astype(data_type)
122
+ return cv2.cvtColor(ir_data, cv2.COLOR_GRAY2RGB)
123
+
124
+ def get_imu_text(frame, name):
125
+ """Format IMU data"""
126
+ if not frame:
127
+ return []
128
+ return [
129
+ f"{name} x: {frame.get_x():.2f}",
130
+ f"{name} y: {frame.get_y():.2f}",
131
+ f"{name} z: {frame.get_z():.2f}"
132
+ ]
133
+
134
+
135
+ def create_display(frames, width=1280, height=720):
136
+ """Create display window"""
137
+ display = np.zeros((height, width, 3), dtype=np.uint8)
138
+ h, w = height // 2, width // 2
139
+
140
+ # Process video frames
141
+ if 'color' in frames and frames['color'] is not None:
142
+ display[0:h, 0:w] = cv2.resize(frames['color'], (w, h))
143
+
144
+ if 'depth' in frames and frames['depth'] is not None:
145
+ display[0:h, w:] = cv2.resize(frames['depth'], (w, h))
146
+
147
+ if 'ir' in frames and frames['ir'] is not None:
148
+ display[h:, 0:w] = cv2.resize(frames['ir'], (w, h))
149
+
150
+ # Display IMU data
151
+ if 'imu' in frames:
152
+ y_offset = h + 20
153
+ for data_type in ['accel', 'gyro']:
154
+ text_lines = get_imu_text(frames['imu'].get(data_type), data_type.title())
155
+ for i, line in enumerate(text_lines):
156
+ cv2.putText(display, line, (w + 10, y_offset + i * 20),
157
+ cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
158
+ y_offset += 80
159
+
160
+ return display
161
+
162
+
163
+ def main():
164
+ # Window settings
165
+ WINDOW_NAME = "MultiStream Record Viewer"
166
+ file_path = input("Enter output filename (.bag) and press Enter to start recording: ")
167
+
168
+ DISPLAY_WIDTH = 1280
169
+ DISPLAY_HEIGHT = 720
170
+
171
+ # Initialize camera
172
+ pipeline = setup_camera()
173
+ device = pipeline.get_device()
174
+ #synchronize the timer of the device with the host
175
+ device.timer_sync_with_host();
176
+ # initialize recording
177
+ recorder = RecordDevice(device, file_path)
178
+ imu_pipeline = setup_imu()
179
+ cv2.namedWindow(WINDOW_NAME, cv2.WINDOW_NORMAL)
180
+ cv2.resizeWindow(WINDOW_NAME, DISPLAY_WIDTH, DISPLAY_HEIGHT)
181
+ while True:
182
+ # Get all frames
183
+ frames = pipeline.wait_for_frames(100)
184
+ if not frames:
185
+ continue
186
+ # Process different frame types
187
+ processed_frames = {'color': process_color(frames.get_color_frame()),
188
+ 'depth': process_depth(frames.get_depth_frame())}
189
+
190
+ # Process IR image: try stereo IR first, fallback to mono if unavailable
191
+ try:
192
+ left = process_ir(frames.get_frame(OBFrameType.LEFT_IR_FRAME).as_video_frame())
193
+ right = process_ir(frames.get_frame(OBFrameType.RIGHT_IR_FRAME).as_video_frame())
194
+ if left is not None and right is not None:
195
+ processed_frames['ir'] = np.hstack((left, right))
196
+ except:
197
+ ir_frame = frames.get_ir_frame()
198
+ if ir_frame:
199
+ processed_frames['ir'] = process_ir(ir_frame.as_video_frame())
200
+
201
+ # Process IMU data
202
+ imu_frames = imu_pipeline.wait_for_frames(100)
203
+ if not imu_frames:
204
+ continue
205
+ accel = imu_frames.get_frame(OBFrameType.ACCEL_FRAME)
206
+ gyro = imu_frames.get_frame(OBFrameType.GYRO_FRAME)
207
+ if accel and gyro:
208
+ processed_frames['imu'] = {
209
+ 'accel': accel.as_accel_frame(),
210
+ 'gyro': gyro.as_gyro_frame()
211
+ }
212
+
213
+ # create display
214
+ display = create_display(processed_frames, DISPLAY_WIDTH, DISPLAY_HEIGHT)
215
+ cv2.imshow(WINDOW_NAME, display)
216
+
217
+ # check exit key
218
+ key = cv2.waitKey(1) & 0xFF
219
+ if key == ord('s'):
220
+ global is_paused
221
+ if not is_paused:
222
+ recorder.pause()
223
+ is_paused = True
224
+ print("[PAUSED] Recording paused")
225
+ else:
226
+ recorder.resume()
227
+ is_paused = False
228
+ print("[RESUMED] Recording resumed")
229
+ if key in (ord('q'), 27):
230
+ break
231
+
232
+ pipeline.stop()
233
+ recorder = None
234
+ cv2.destroyAllWindows()
235
+
236
+
237
+ if __name__ == "__main__":
238
+ main()
@@ -0,0 +1,9 @@
1
+ pybind11==2.11.0
2
+ pybind11-global==2.11.0
3
+ opencv-python
4
+ wheel
5
+ numpy<2.0 # see https://github.com/orbbec/pyorbbecsdk/issues/47
6
+ open3d # for visualization point cloud
7
+ av # for h264 decoding
8
+ pygame # for visualization
9
+ pynput # for keyboard input
@@ -0,0 +1,106 @@
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 os
17
+
18
+ import cv2
19
+ import numpy as np
20
+
21
+ from pyorbbecsdk import *
22
+ from utils import frame_to_bgr_image
23
+
24
+
25
+ def save_depth_frame(frame: DepthFrame, index):
26
+ if frame is None:
27
+ return
28
+ width = frame.get_width()
29
+ height = frame.get_height()
30
+ timestamp = frame.get_timestamp()
31
+ scale = frame.get_depth_scale()
32
+ depth_format = frame.get_format()
33
+ if depth_format != OBFormat.Y16:
34
+ print("depth format is not Y16")
35
+ return
36
+ data = np.frombuffer(frame.get_data(), dtype=np.uint16)
37
+ data = data.reshape((height, width))
38
+ data = data.astype(np.float32) * scale
39
+ data = data.astype(np.uint16)
40
+ save_image_dir = os.path.join(os.getcwd(), "depth_images")
41
+ if not os.path.exists(save_image_dir):
42
+ os.mkdir(save_image_dir)
43
+ raw_filename = save_image_dir + "/depth_{}x{}_{}_{}.raw".format(width, height, index, timestamp)
44
+ data.tofile(raw_filename)
45
+
46
+
47
+ def save_color_frame(frame: ColorFrame, index):
48
+ if frame is None:
49
+ return
50
+ width = frame.get_width()
51
+ height = frame.get_height()
52
+ timestamp = frame.get_timestamp()
53
+ save_image_dir = os.path.join(os.getcwd(), "color_images")
54
+ if not os.path.exists(save_image_dir):
55
+ os.mkdir(save_image_dir)
56
+ filename = save_image_dir + "/color_{}x{}_{}_{}.png".format(width, height, index, timestamp)
57
+ image = frame_to_bgr_image(frame)
58
+ if image is None:
59
+ print("failed to convert frame to image")
60
+ return
61
+ cv2.imwrite(filename, image)
62
+
63
+
64
+ def main():
65
+ pipeline = Pipeline()
66
+ config = Config()
67
+ saved_color_cnt: int = 0
68
+ saved_depth_cnt: int = 0
69
+ has_color_sensor = False
70
+ try:
71
+ profile_list = pipeline.get_stream_profile_list(OBSensorType.COLOR_SENSOR)
72
+ if profile_list is not None:
73
+ color_profile: VideoStreamProfile = profile_list.get_default_video_stream_profile()
74
+ config.enable_stream(color_profile)
75
+ has_color_sensor = True
76
+ except OBError as e:
77
+ print(e)
78
+ depth_profile_list = pipeline.get_stream_profile_list(OBSensorType.DEPTH_SENSOR)
79
+ if depth_profile_list is not None:
80
+ depth_profile = depth_profile_list.get_default_video_stream_profile()
81
+ config.enable_stream(depth_profile)
82
+ pipeline.start(config)
83
+ while True:
84
+ try:
85
+ frames = pipeline.wait_for_frames(100)
86
+ if frames is None:
87
+ continue
88
+ if has_color_sensor:
89
+ if saved_color_cnt >= 5 and saved_depth_cnt >= 5:
90
+ break
91
+ elif saved_depth_cnt >= 5:
92
+ break
93
+ color_frame = frames.get_color_frame()
94
+ if color_frame is not None and saved_color_cnt < 5:
95
+ save_color_frame(color_frame, saved_color_cnt)
96
+ saved_color_cnt += 1
97
+ depth_frame = frames.get_depth_frame()
98
+ if depth_frame is not None and saved_depth_cnt < 5:
99
+ save_depth_frame(depth_frame, saved_depth_cnt)
100
+ saved_depth_cnt += 1
101
+ except KeyboardInterrupt:
102
+ break
103
+
104
+
105
+ if __name__ == "__main__":
106
+ main()
@@ -0,0 +1,109 @@
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 argparse
17
+ import sys
18
+
19
+ import cv2
20
+ import numpy as np
21
+
22
+ from pyorbbecsdk import *
23
+ from utils import frame_to_bgr_image
24
+
25
+ ESC_KEY = 27
26
+
27
+ MIN_DEPTH = 20 # 20mm
28
+ MAX_DEPTH = 10000 # 10000mm
29
+ # Temporal filter for smoothing depth data over time
30
+
31
+ def main(argv):
32
+ pipeline = Pipeline()
33
+ config = Config()
34
+ parser = argparse.ArgumentParser()
35
+ parser.add_argument("-s", "--enable_sync", help="enable sync", type=bool, default=True)
36
+ args = parser.parse_args(argv)
37
+
38
+ enable_sync = args.enable_sync
39
+ try:
40
+ profile_list = pipeline.get_stream_profile_list(OBSensorType.COLOR_SENSOR)
41
+ color_profile = profile_list.get_default_video_stream_profile()
42
+ config.enable_stream(color_profile)
43
+ profile_list = pipeline.get_stream_profile_list(OBSensorType.DEPTH_SENSOR)
44
+ depth_profile = profile_list.get_default_video_stream_profile()
45
+ config.enable_stream(depth_profile)
46
+ except Exception as e:
47
+ print(e)
48
+ return
49
+
50
+ if enable_sync:
51
+ try:
52
+ pipeline.enable_frame_sync()
53
+ except Exception as e:
54
+ print(e)
55
+
56
+ try:
57
+ pipeline.start(config)
58
+ except Exception as e:
59
+ print(e)
60
+ return
61
+
62
+ align_filter = AlignFilter(align_to_stream=OBStreamType.COLOR_STREAM)
63
+
64
+ while True:
65
+ try:
66
+ frames = pipeline.wait_for_frames(100)
67
+ if not frames:
68
+ continue
69
+ color_frame = frames.get_color_frame()
70
+ depth_frame = frames.get_depth_frame()
71
+ if not color_frame or not depth_frame:
72
+ continue
73
+ frames = align_filter.process(frames)
74
+ if not frames:
75
+ continue
76
+ frames = frames.as_frame_set()
77
+ color_frame = frames.get_color_frame()
78
+ depth_frame = frames.get_depth_frame()
79
+ if not color_frame or not depth_frame:
80
+ continue
81
+
82
+ color_image = frame_to_bgr_image(color_frame)
83
+ if color_image is None:
84
+ print("Failed to convert frame to image")
85
+ continue
86
+ try:
87
+ depth_data = np.frombuffer(depth_frame.get_data(), dtype=np.uint16).reshape(
88
+ (depth_frame.get_height(), depth_frame.get_width()))
89
+ except ValueError:
90
+ print("Failed to reshape depth data")
91
+ continue
92
+ depth_data = depth_data.astype(np.float32) * depth_frame.get_depth_scale()
93
+ depth_data = np.where((depth_data > MIN_DEPTH) & (depth_data < MAX_DEPTH), depth_data, 0)
94
+ depth_data = depth_data.astype(np.uint16)
95
+ depth_image = cv2.normalize(depth_data, None, 0, 255, cv2.NORM_MINMAX)
96
+ depth_image = cv2.applyColorMap(depth_image.astype(np.uint8), cv2.COLORMAP_JET)
97
+ depth_image = cv2.addWeighted(color_image, 0.5, depth_image, 0.5, 0)
98
+
99
+ cv2.imshow("SyncAlignViewer", depth_image)
100
+ if cv2.waitKey(1) in [ord('q'), ESC_KEY]:
101
+ break
102
+ except KeyboardInterrupt:
103
+ break
104
+ cv2.destroyAllWindows()
105
+ pipeline.stop()
106
+
107
+
108
+ if __name__ == "__main__":
109
+ main(sys.argv[1:])