CVBpy 15.0
All Classes Namespaces Functions Variables Enumerations Enumerator Properties Modules Pages
foundation/MetricCalibration
1# @brief Example for **intrinsic and extrinsic calibration**
2# of a laser triangulation system using the AQS12 target.
3
4"""
5CVBpy Example Script for AQS12 Calibration - Use Case 1.
6
7This example shows how to calibrate range maps acquired by a modular laser
8triangulation setup (camera and laser separated), where the intrinsic calibration
9parameters are not given.
10
11See also use case 1 described in the CVB Metric documentation:
12https://help.commonvisionblox.com/NextGen/15.0/md_theory_of_operation_tools__metric.html#calibration_setup
13
14This example program estimates homography and an affine transformation.
15The affine transformation:
16- corrects errors induced by an incline laser plane
17- corrects scaling in x, y, z
18- moves the point cloud to the coordinate system given by the reference
19points of the AQS12
20"""
21
22import os
23
24import cvb
25import cvb.foundation
26
27
28def print_trafo(trafo: cvb.AffineMatrix3D) -> None:
29 print("Estimated transformation:")
30 print("Translation:")
31 print(f"[{trafo.translation.x}, {trafo.translation.y}, "
32 f"{trafo.translation.z}]")
33 print("Transformation matrix:")
34 print(f"[[{trafo.matrix.at(0, 0)}, "
35 f"{trafo.matrix.at(0, 1)}, "
36 f"{trafo.matrix.at(0, 2)}],")
37 print(f"[{trafo.matrix.at(1, 0)}, "
38 f"{trafo.matrix.at(1, 1)}, "
39 f"{trafo.matrix.at(1, 2)}],")
40 print(f"[{trafo.matrix.at(2, 0)}, "
41 f"{trafo.matrix.at(2, 1)}, "
42 f"{trafo.matrix.at(2, 2)}]]")
43
44
45def print_trafo_parameters(atp: cvb.AffineTransformationParameters) -> None:
46 print("Rotation angles about X, Y, Z axis in degrees:")
47 print(f"{atp.rotation_angles.x}, {atp.rotation_angles.y}, "
48 f"{atp.rotation_angles.z}")
49 print("Shear Syx, Syz:")
50 print(f"{atp.s_yx}, {atp.s_yz}")
51 print("Inclination of laser plane about X, Z axis in degrees:")
52 print(f"{atp.inclination_x}, {atp.inclination_z}")
53 print("Scale in X, Y, Z:")
54 print(f"{atp.scale.x}, {atp.scale.y}, {atp.scale.z}")
55
56
57def print_point_3d_list(points: list[cvb.Point3D]) -> None:
58 data_list = list()
59 for p in points:
60 data_list.append(f"[{p.x}, {p.y}, {p.z}]")
61 delimiter = ",\n"
62 print(f"[{delimiter.join(data_list)}]")
63
64
65def print_residuals(points: list[cvb.Point3D]) -> None:
66 print("Residuals:")
67 print_point_3d_list(points)
68
69
70def print_aqs12_points(points: list[cvb.Point3D]) -> None:
71 print("AQS12 points:")
72 print_point_3d_list(points)
73
74
75def create_aqs12():
76 # list of known point coordinates of the AQS12
77 points = [
78 cvb.Point3D(20.0018, 44.9941, 15.0000),
79 cvb.Point3D(24.0018, 39.9942, 14.9994),
80 cvb.Point3D(23.9994, 24.9972, 15.0001),
81 cvb.Point3D(20.0021, 20.0035, 15.0011),
82 cvb.Point3D(15.9994, 25.0079, 15.0016),
83 cvb.Point3D(16.0000, 39.9919, 15.0010),
84 cvb.Point3D(20.0095, 59.9985, 4.9902),
85 cvb.Point3D(32.0093, 44.9958, 4.9909),
86 cvb.Point3D(32.0052, 19.9925, 4.9920),
87 cvb.Point3D(20.0021, 4.9961, 4.9939),
88 cvb.Point3D(8.0024, 19.9980, 5.0009),
89 cvb.Point3D(8.0065, 45.0009, 4.9984)]
90 return cvb.foundation.AQS12Piece(points, 0)
91
92
93def check_accuracy(residuals: list[cvb.Point3D], desired_accuracy: float):
94 for point in residuals:
95 if (abs(point.x) > desired_accuracy or
96 abs(point.y) > desired_accuracy or
97 abs(point.z) > desired_accuracy):
98 return False
99 return True
100
101
102# If you like to save intermediate and final results, turn this flag on:
103save = False
104
105print("Estimation of homography and affine transformation (correcting an "
106 "inclined laser plane)")
107
108# load range map of the calibration target AQS12
109print("Loading range map.")
110range_map_file = os.path.join(cvb.install_path(),
111 "tutorial", "Metric", "Images",
112 "RangeMapCalibrationPattern.tif")
113range_map = cvb.Image(range_map_file)
114
115print(f"Range map loaded with size of {range_map.width} x {range_map.height} "
116 f"from {range_map_file}.")
117
118# create calibration configuration object
119aqs12 = create_aqs12()
121
122# create AQS12 segmentor for the range maps
123print("Estimating homography and affine matrix.")
125 cvb.foundation.SegmentationMethod.KmeansClustering)
126
127# estimate calibration parameters
129 range_map.planes[0], segmentor, config)
130
131transformation_, transformation_parameters_ = \
132 calibrator_.correction_of_laser_plane_inclination
133
134# show result
135if transformation_:
136 print_trafo(transformation_)
137
138print_residuals(residuals_)
139
140if transformation_parameters_:
141 print_trafo_parameters(transformation_parameters_)
142
143# check residuals
144desired_accuracy_ = 0.05 # mm
145if check_accuracy(residuals_, desired_accuracy_):
146 print("The calibration was successful and accuracy is < "
147 f"{desired_accuracy_} mm.")
148
149 # create calibrated cloud
150 print("Creating calibrated point cloud.")
152 range_map.planes[0], calibrator_,
153 cvb.PointCloudFlags.Float | cvb.PointCloudFlags.XYZConfidence)
154
155 # save calibrated point cloud
156 if save:
157 cloud.save("cloud.ply")
158else:
159 print("Results do not have desired accuracy. Check face segmentation and "
160 "extracted AQS12 points...")
161
162 # segment AQS12 faces
163 print("Segmenting AQ12 faces on range map.")
164 faces_aqs12 = segmentor.face_segmentation_from_piece(range_map.planes[0])
165
166 # save image with segmented faces:
167 if save:
168 faces_aqs12.save("AQS12faces.bmp")
169
170 # extract AQS12 points on range map (might take some time...)
171 print("Extracting AQ12 corner points on range map.")
172 points_aqs12 = segmentor.extract_projected_points_from_piece(
173 range_map.planes[0])
174 print_aqs12_points(points_aqs12)
The Common Vision Blox image.
Definition: __init__.py:2097
Multi-purpose 3D vector class.
Definition: __init__.py:4322
Union[cvb.PointCloud, cvb.DensePointCloud, cvb.SparsePointCloud] create(cvb.ImagePlane range_map, cvb.Calibrator3D calibrator, int flags, Union[Type[cvb.PointCloud|cvb.DensePointCloud|cvb.SparsePointCloud]] point_cloud_type=DensePointCloud)
Creates a new Cartesian 3D point cloud from the given 2.5D range map image.
Definition: __init__.py:4701
Object to collect all input parameters for the AQS12 calibration piece.
Definition: __init__.py:76
cvb.foundation.AQS12RangeMapSegmentor create(int method)
Creates an AQS12 segmentor for range maps based on given segmentation method.
Definition: __init__.py:101
cvb.foundation.CalibrationConfiguration create(cvb.foundation.AQS12Piece aqs12)
Creates a calibration configuration object.
Definition: __init__.py:272
Common Vision Blox Foundation module for Python.
Definition: __init__.py:1
Tuple[cvb.LaserPlaneHomographyCalibrator3D, List[cvb.Point3D]] create_calibrator_from_aqs12_piece(cvb.ImagePlane image_plane, cvb.foundation.AQS12RangeMapSegmentor segmentor, cvb.foundation.CalibrationConfiguration config, Optional[cvb.Rect] aoi=None)
Calculates intrinsic calibration parameters from the given range map image of an AQS12 calibration pi...
Definition: __init__.py:2939
str install_path()
Directory Common Vision Blox has been installed to.
Definition: __init__.py:8318