Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion area_scan_3d_camera/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ The samples marked with `(OpenCV)` require [OpenCV](https://pypi.org/project/ope
Set multiple exposure times, and then obtain and save the untextured and textured point clouds.
* [capture_point_cloud_with_normals](https://github.com/MechMindRobotics/mecheye_python_samples/tree/master/area_scan_3d_camera/basic/capture_point_cloud_with_normals.py)
Calculate normals and save the untextured and textured point clouds with normals.
* [save_virtual_device](https://github.com/MechMindRobotics/mecheye_python_samples/tree/master/area_scan_3d_camera/basic/save_virtual_device.py)
Save the data acquired by the camera as a virtual device file.
* **advanced**
* [capture_depth_source_2d_image](https://github.com/MechMindRobotics/mecheye_python_samples/tree/master/area_scan_3d_camera/advanced/capture_depth_source_2d_image.py) `(OpenCV)`
Obtain and save the 2D image from the depth source camera.
> Note: This sample is only applicable to camera models that provide the depth-source 2D image, such as Mech-Eye ULTRA M.
* [convert_depth_map_to_point_cloud](https://github.com/MechMindRobotics/mecheye_python_samples/tree/master/area_scan_3d_camera/advanced/convert_depth_map_to_point_cloud.py)
Generate a point cloud from the depth map and save the point cloud.
* [multiple_cameras_capture_sequentially](https://github.com/MechMindRobotics/mecheye_python_samples/tree/master/area_scan_3d_camera/advanced/multiple_cameras_capture_sequentially.py) `(OpenCV)`
Expand All @@ -38,11 +43,13 @@ The samples marked with `(OpenCV)` require [OpenCV](https://pypi.org/project/ope
Obtain and save 2D images, depth maps, and point clouds simultaneously from multiple cameras.
* [capture_periodically](https://github.com/MechMindRobotics/mecheye_python_samples/tree/master/area_scan_3d_camera/advanced/capture_periodically.py) `(OpenCV)`
Obtain and save 2D images, depth maps, and point clouds periodically for the specified duration from a camera.
* [warm_up](https://github.com/MechMindRobotics/mecheye_python_samples/tree/master/area_scan_3d_camera/advanced/warm_up.py) `(OpenCV)`
Warm up the device.
* [mapping_2d_image_to_depth_map](https://github.com/MechMindRobotics/mecheye_python_samples/tree/master/area_scan_3d_camera/advanced/mapping_2d_image_to_depth_map.py)
Generate untextured and textured point clouds from a masked 2D image and a depth map.
* [render_depth_map](https://github.com/MechMindRobotics/mecheye_python_samples/tree/master/area_scan_3d_camera/advanced/render_depth_map.py) `(OpenCV)`
Obtain and save the depth map rendered with the jet color scheme.
* [transform_point_cloud](https://github.com/MechMindRobotics/mecheye_python_samples/tree/master/area_scan_3d_camera/Advanced/transform_point_cloud.py)
* [transform_point_cloud](https://github.com/MechMindRobotics/mecheye_python_samples/tree/master/area_scan_3d_camera/advanced/transform_point_cloud.py)
Obtain and save the point clouds in the custom reference frame.
* [set_parameters_of_laser_cameras](https://github.com/MechMindRobotics/mecheye_python_samples/tree/master/area_scan_3d_camera/advanced/set_parameters_of_laser_cameras.py)
Set the parameters specific to laser cameras.
Expand Down
44 changes: 44 additions & 0 deletions area_scan_3d_camera/advanced/capture_depth_source_2d_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# With this sample, you can obtain and save the depth-source 2D image.

import cv2

from mecheye.shared import *
from mecheye.area_scan_3d_camera import *
from mecheye.area_scan_3d_camera_utils import find_and_connect


class CaptureDepthSource2DImage(object):
def __init__(self):
self.camera = Camera()

def capture_depth_source_2d_image(self):
frame_2d = Frame2D()
error = self.camera.capture_depth_source_2d(frame_2d)
if not error.is_ok():
show_error(error)
return

if frame_2d.color_type() == ColorTypeOf2DCamera_Monochrome:
image_2d = frame_2d.get_gray_scale_image()
file_name = "DepthSourceGrayScale2DImage.png"
print("Capture and save the depth-source gray scale 2D image: {}".format(file_name))
elif frame_2d.color_type() == ColorTypeOf2DCamera_Color:
image_2d = frame_2d.get_color_image()
file_name = "DepthSourceColor2DImage.png"
print("Capture and save the depth-source color 2D image: {}".format(file_name))
else:
print("The acquired depth-source 2D image has an unsupported color type.")
return

cv2.imwrite(file_name, image_2d.data())

def main(self):
if find_and_connect(self.camera):
self.capture_depth_source_2d_image()
self.camera.disconnect()
print("Disconnected from the camera successfully.")


if __name__ == '__main__':
a = CaptureDepthSource2DImage()
a.main()
10 changes: 10 additions & 0 deletions area_scan_3d_camera/calibration/hand_eye_calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ def input_command(self):
print("T: obtain the 2D image with feature recognition result")
print("A: enter the current robot pose")
print("C: calculate extrinsic parameters")
print("F: obtain the first corner of current image")
while True:
user_input = input()
if user_input == "P" or user_input == "p":
Expand All @@ -130,6 +131,8 @@ def input_command(self):
return "A"
elif user_input == "C" or user_input == "c":
return "C"
elif user_input == "F" or user_input == "f":
return "F"
else:
print("Unknown command, please enter correct command type")

Expand Down Expand Up @@ -289,6 +292,13 @@ def calibrate(self):
print("The extrinsic parameters are:")
print(camera_to_base.to_string())
save_extrinsic_parameters(camera_to_base.to_string())
elif command == "F":
corner = PointXYZ()
error_status = self.calibration.extract_current_image_first_corner(
self.camera, corner)
show_error(error_status)
if error_status.is_ok():
print(f"The first corner is: {corner.x:.3f}, {corner.y:.3f}, {corner.z:.3f}")

def main(self):
if not find_and_connect(self.camera):
Expand Down
48 changes: 48 additions & 0 deletions area_scan_3d_camera/util/set_point_cloud_processing_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ def set_point_cloud_processing_parameters(self):
error = current_user_set.set_enum_value(PointCloudNoiseRemoval.name,
PointCloudNoiseRemoval.Value_Normal)
show_error(error)
error = current_user_set.set_enum_value(PointCloudDepthSmooth.name,
PointCloudDepthSmooth.Value_Normal)
show_error(error)
error = current_user_set.set_enum_value(PointCloudDepthHoleFilling.name,
PointCloudDepthHoleFilling.Value_Normal)
show_error(error)
error = current_user_set.set_enum_value(PointCloudDepthSurfaceNoiseRemoval.name,
PointCloudDepthSurfaceNoiseRemoval.Value_Normal)
show_error(error)
error = current_user_set.set_enum_value(PointCloudPhaseClusterOutlierRemoval.name,
PointCloudPhaseClusterOutlierRemoval.Value_L5)
show_error(error)
error = current_user_set.set_enum_value(PointCloudSpuriousPhaseRemoval.name,
PointCloudSpuriousPhaseRemoval.Value_Normal)
show_error(error)
error = current_user_set.set_enum_value(PointCloudLargeGradNoiseRemoval.name,
PointCloudLargeGradNoiseRemoval.Value_Normal)
show_error(error)
error = current_user_set.set_enum_value(PointCloudOutlierRemoval.name,
PointCloudOutlierRemoval.Value_Normal)
show_error(error)
Expand All @@ -38,6 +56,24 @@ def set_point_cloud_processing_parameters(self):
error, noise_removal = current_user_set.get_enum_value_string(
PointCloudNoiseRemoval.name)
show_error(error)
error, depth_smooth = current_user_set.get_enum_value_string(
PointCloudDepthSmooth.name)
show_error(error)
error, depth_hole_filling = current_user_set.get_enum_value_string(
PointCloudDepthHoleFilling.name)
show_error(error)
error, depth_surface_noise_removal = current_user_set.get_enum_value_string(
PointCloudDepthSurfaceNoiseRemoval.name)
show_error(error)
error, phase_cluster_outlier_removal = current_user_set.get_enum_value_string(
PointCloudPhaseClusterOutlierRemoval.name)
show_error(error)
error, spurious_phase_removal = current_user_set.get_enum_value_string(
PointCloudSpuriousPhaseRemoval.name)
show_error(error)
error, large_grad_noise_removal = current_user_set.get_enum_value_string(
PointCloudLargeGradNoiseRemoval.name)
show_error(error)
error, outlier_removal = current_user_set.get_enum_value_string(
PointCloudOutlierRemoval.name)
show_error(error)
Expand All @@ -49,6 +85,18 @@ def set_point_cloud_processing_parameters(self):
"(0: Off, 1: Weak, 2: Normal, 3: Strong)")
print("Point Cloud Noise Removal:", noise_removal,
"(0: Off, 1: Weak, 2: Normal, 3: Strong)")
print("Depth Smooth:", depth_smooth,
"(0: Off, 1: Weak, 2: Normal, 3: Strong)")
print("Depth Hole Filling:", depth_hole_filling,
"(0: Off, 1: Weak, 2: Normal, 3: Strong)")
print("Depth Surface Noise Removal:", depth_surface_noise_removal,
"(0: Off, 1: Weak, 2: Normal, 3: Strong)")
print("Phase Cluster Outlier Removal:", phase_cluster_outlier_removal,
"(0: Off, 1: L1, 2: L2, 3: L3, 4: L4, 5: L5, 6: L6, 7: L7, 8: L8, 9: L9, 10: L10)")
print("Spurious Phase Removal:", spurious_phase_removal,
"(0: Off, 1: Weak, 2: Normal, 3: Strong)")
print("Large Gradient Noise Removal:", large_grad_noise_removal,
"(0: Off, 1: Weak, 2: Normal, 3: Strong)")
print("Point Cloud Outlier Removal:", outlier_removal,
"(0: Off, 1: Weak, 2: Normal, 3: Strong)")
print("Point Cloud Edge Preservation:", edge_preservation,
Expand Down
102 changes: 98 additions & 4 deletions area_scan_3d_camera/util/set_scanning_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,17 @@ def set_scanning_parameters(self):
error, user_set_name = current_user_set.get_name()
show_error(error)
print("\ncurrent_user_set: " + user_set_name)
error, available_params = current_user_set.get_available_parameter_names()
show_error(error)

# Set the exposure times for acquiring depth information.
if Scanning3DExposureCount.name in available_params:
error = current_user_set.set_int_value(Scanning3DExposureCount.name, 1)
show_error(error)
error, exposure_count = current_user_set.get_int_value(
Scanning3DExposureCount.name)
show_error(error)
print("\n3D scanning exposure count: {}".format(exposure_count))
error = current_user_set.set_float_array_value(
Scanning3DExposureSequence.name, [5])
# error = current_user_set.set_float_array_value(
Expand All @@ -36,6 +45,64 @@ def set_scanning_parameters(self):
for i in exposure_sequence:
print("3D scanning exposure time: {}".format(i))

# Some models provide exposure group parameters. Use "GroupExposureSelector" to select the
# target group, and then set the group exposure time, gain, and power level.
if (Scanning3DGroupExposureSelector.name in available_params and
Scanning3DGroupExposureTime.name in available_params and
Scanning3DGroupGain.name in available_params and
Scanning3DGroupDlpPowerLevel.name in available_params):
error = current_user_set.set_enum_value(
Scanning3DGroupExposureSelector.name,
Scanning3DGroupExposureSelector.Value_Exposure1)
show_error(error)
error = current_user_set.set_float_value(
Scanning3DGroupExposureTime.name, 10)
show_error(error)
error = current_user_set.set_float_value(
Scanning3DGroupGain.name, 2.0)
show_error(error)
error = current_user_set.set_int_value(
Scanning3DGroupDlpPowerLevel.name, 80)
show_error(error)

error, group_exposure_time = current_user_set.get_float_value(
Scanning3DGroupExposureTime.name)
show_error(error)
error, group_gain = current_user_set.get_float_value(
Scanning3DGroupGain.name)
show_error(error)
error, group_dlp_power_level = current_user_set.get_int_value(
Scanning3DGroupDlpPowerLevel.name)
show_error(error)
print("Group Exposure1: exposure time {}, gain {}, DLP power level {}.".format(
group_exposure_time, group_gain, group_dlp_power_level))

error = current_user_set.set_enum_value(
Scanning3DGroupExposureSelector.name,
Scanning3DGroupExposureSelector.Value_Exposure2)
show_error(error)
error = current_user_set.set_float_value(
Scanning3DGroupExposureTime.name, 5)
show_error(error)
error = current_user_set.set_float_value(
Scanning3DGroupGain.name, 0.0)
show_error(error)
error = current_user_set.set_int_value(
Scanning3DGroupDlpPowerLevel.name, 60)
show_error(error)

error, group_exposure_time = current_user_set.get_float_value(
Scanning3DGroupExposureTime.name)
show_error(error)
error, group_gain = current_user_set.get_float_value(
Scanning3DGroupGain.name)
show_error(error)
error, group_dlp_power_level = current_user_set.get_int_value(
Scanning3DGroupDlpPowerLevel.name)
show_error(error)
print("Group Exposure2: exposure time {}, gain {}, DLP power level {}.".format(
group_exposure_time, group_gain, group_dlp_power_level))

# Set the ROI for the depth map and point cloud, and then obtain the parameter values for checking.
roi = ROI(0, 0, 500, 500)
error = current_user_set.set_roi_value(Scanning3DROI.name, roi)
Expand Down Expand Up @@ -81,7 +148,7 @@ def set_scanning_parameters(self):
# show_error(error)

# The following models also provide a "FlashAcquisitionMode" when using the flash exposure
# mode: DEEP, DEEP-GL, LSR S/L/XL, LSR S-GL/L-GL/XL-GL, PRO XS/S/M, PRX XS-GL/S-GL/M-GL, NANO, NANO-GL, NANO ULTRA, NANO ULTRA-GL. Uncomment the following lines to set
# mode: DEEP, DEEP-GL, LSR S/L/XL, LSR S-GL/L-GL/XL-GL, PRO XS/S/M, PRO XS-GL/S-GL/M-GL, NANO, NANO-GL, NANO ULTRA, NANO ULTRA-GL. Uncomment the following lines to set
# the "FlashAcquisitionMode" parameter to "Responsive".
# flash_acquisition_mode_2d=Scanning2DFlashAcquisitionMode.Value_Responsive
# error = current_user_set.set_enum_value(
Expand Down Expand Up @@ -112,11 +179,38 @@ def set_scanning_parameters(self):
# setting the "Scan2DGain" parameter when the exposure mode is set to fixed exposure, auto
# exposure, HDR, or flash mode, and the flash acquisition mode is set to
# responsive.
# print("\n2D image gain: ", scan2DGain)value(Scanning2DGain.name,2.0))
# show_error(error)et_float_value(Scanning2DGain.name)
# error = current_user_set.set_float_value(Scanning2DGain.name, 2.0)
# show_error(error)
# error, scan2DGain = current_user_set.get_float_value(Scanning2DGain.name)
# show_error(current_user_set.set_float_value(Scanning2DGain.name,2.6))
# show_error(error)
# print("\n2D image gain: ", scan2DGain)


# The following parameters are only available on some models. Uncomment to set and read values.
# error = current_user_set.set_float_value(
# Scanning2DPatternRoleGain.name, 2.0)
# show_error(error)
# error, pattern_role_gain = current_user_set.get_float_value(
# Scanning2DPatternRoleGain.name)
# show_error(error)
# print("\n2D pattern role gain: {}".format(pattern_role_gain))
#
# error = current_user_set.set_float_value(
# Scanning2DFlashGain.name, 2.0)
# show_error(error)
# error, flash_gain = current_user_set.get_float_value(
# Scanning2DFlashGain.name)
# show_error(error)
# print("\n2D flash gain: {}".format(flash_gain))
#
# error = current_user_set.set_int_value(
# Scanning2DFlashPowerLevel.name, 80)
# show_error(error)
# error, flash_power_level = current_user_set.get_int_value(
# Scanning2DFlashPowerLevel.name)
# show_error(error)
# print("\n2D flash power level: {} %".format(flash_power_level))

error, exposure_mode_2d = current_user_set.get_enum_value_string(
Scanning2DExposureMode.name)
show_error(error)
Expand Down
13 changes: 12 additions & 1 deletion profiler/Advanced/transform_point_cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ def convert_batch_to_point_cloud_with_transformation(profile_batch: ProfileBatch
if not error.is_ok():
show_error(error)
return

error, scan_distance = user_set.get_float_value(ScanDistance.name)
if not error.is_ok():
show_error(error)
return
print(
f"Current Y-axis resolution: {y_resolution} um, scan distance: {scan_distance} um.")

# # Uncomment the following line for custom Y Unit
# y_resolution = get_trigger_interval_distance()

Expand Down Expand Up @@ -64,8 +72,11 @@ def set_parameters(self):
show_error(self.user_set.set_float_value(
SoftwareTriggerRate.name, 1000))

# Set the "Scan Line Count" parameter (the number of lines to be scanned) to 1600
# Set the "Scan Line Count" parameter (the number of lines to be scanned) to 1600
show_error(self.user_set.set_int_value(ScanLineCount.name, 1600))
# Set the "Travel Speed" parameter to 100 mm/s. This value is used to calculate the
# Y-axis resolution and scan distance when line scan is triggered at a fixed rate.
show_error(self.user_set.set_float_value(TravelSpeed.name, 100.0))

error, self.data_width = self.user_set.get_int_value(
DataPointsPerProfile.name)
Expand Down
Loading