icp_customized.py
Go to the documentation of this file.
1 # Code example for ICP taking 2 points clouds (2D or 3D) relatively close
2 # and computing the transformation between them.
3 #
4 # Instead of using yaml file for configuration, we configure the solution
5 # directly in the code.
6 #
7 # This code replicate the solution in /evaluations/official_solutions/Besl92_pt2point.yaml
8 
9 from pypointmatcher import pointmatcher as pm, pointmatchersupport as pms
10 
11 PM = pm.PointMatcher
12 DP = PM.DataPoints
13 Parameters = pms.Parametrizable.Parameters
14 
15 # Path of output directory (default: tests/icp_customized/)
16 # The output directory must already exist
17 # Leave empty to save in the current directory
18 output_base_directory = "tests/icp_customized/"
19 
20 # Name of output files (default: test)
21 output_base_file = "test"
22 
23 # Toggle to switch between 2D and 3D clouds
24 is_3D = True
25 
26 if is_3D:
27  # Load 3D point clouds
28  ref = DP(DP.load('../data/car_cloud400.csv'))
29  data = DP(DP.load('../data/car_cloud401.csv'))
30  test_base = "3D"
31 else:
32  # Load 2D point clouds
33  ref = DP(DP.load('../data/2D_twoBoxes.csv'))
34  data = DP(DP.load('../data/2D_oneBox.csv'))
35  test_base = "2D"
36 
37 # Create the default ICP algrotithm
38 icp = PM.ICP()
39 params = Parameters()
40 
41 # Comment out to stop console outputs
42 pms.setLogger(PM.get().LoggerRegistrar.create("FileLogger"))
43 
44 # Prepare reading filters
45 name = "MinDistDataPointsFilter"
46 params["minDist"] = "1.0"
47 minDist_read = PM.get().DataPointsFilterRegistrar.create(name, params)
48 params.clear()
49 
50 name = "RandomSamplingDataPointsFilter"
51 params["prob"] = "0.05"
52 rand_read = PM.get().DataPointsFilterRegistrar.create(name, params)
53 params.clear()
54 
55 # Prepare reference filters
56 name = "MinDistDataPointsFilter"
57 params["minDist"] = "1.0"
58 minDist_ref = PM.get().DataPointsFilterRegistrar.create(name, params)
59 params.clear()
60 
61 name = "RandomSamplingDataPointsFilter"
62 params["prob"] = "0.05"
63 rand_ref = PM.get().DataPointsFilterRegistrar.create(name, params)
64 params.clear()
65 
66 # Prepare matching function
67 name = "KDTreeMatcher"
68 params["knn"] = "1"
69 params["epsilon"] = "3.16"
70 kdtree = PM.get().MatcherRegistrar.create(name, params)
71 params.clear()
72 
73 # Prepare outlier filters
74 name = "TrimmedDistOutlierFilter"
75 params["ratio"] = "0.75"
76 trim = PM.get().OutlierFilterRegistrar.create(name, params)
77 params.clear()
78 
79 # Prepare error minimization
80 name = "PointToPointErrorMinimizer"
81 pointToPoint = PM.get().ErrorMinimizerRegistrar.create(name)
82 params.clear()
83 
84 # Prepare transformation checker filters
85 name = "CounterTransformationChecker"
86 params["maxIterationCount"] = "150"
87 maxIter = PM.get().TransformationCheckerRegistrar.create(name, params)
88 params.clear()
89 
90 name = "DifferentialTransformationChecker"
91 params["minDiffRotErr"] = "0.001"
92 params["minDiffTransErr"] = "0.01"
93 params["smoothLength"] = "4"
94 diff = PM.get().TransformationCheckerRegistrar.create(name, params)
95 params.clear()
96 
97 # Prepare inspector
98 # Comment out to write vtk files per iteration
99 name = "NullInspector"
100 nullInspect = PM.get().InspectorRegistrar.create(name)
101 
102 # Uncomment to write vtk files per iteration
103 # name = "VTKFileInspector"
104 # params["dumpDataLinks"] = "1"
105 # params["dumpReading"] = "1"
106 # params["dumpReference"] = "1"
107 # vtkInspect = PM.get().InspectorRegistrar.create(name, params)
108 # params.clear()
109 
110 # Prepare transformation
111 name = "RigidTransformation"
112 rigid_trans = PM.get().TransformationRegistrar.create(name)
113 
114 # Build ICP solution
115 icp.readingDataPointsFilters.append(minDist_read)
116 icp.readingDataPointsFilters.append(rand_read)
117 
118 icp.referenceDataPointsFilters.append(minDist_ref)
119 icp.referenceDataPointsFilters.append(rand_ref)
120 
121 icp.matcher = kdtree
122 
123 icp.outlierFilters.append(trim)
124 
125 icp.errorMinimizer = pointToPoint
126 
127 icp.transformationCheckers.append(maxIter)
128 icp.transformationCheckers.append(diff)
129 
130 # Toggle to write vtk files per iteration
131 icp.inspector = nullInspect
132 # icp.inspector = vtkInspect
133 
134 icp.transformations.append(rigid_trans)
135 
136 # Compute the transformation to express data in ref
137 T = icp(data, ref)
138 
139 # Transform data to express it in ref
140 data_out = DP(data)
141 
142 icp.transformations.apply(data_out, T)
143 
144 # Save files to see the results
145 ref.save(f"{output_base_directory + test_base}_{output_base_file}_ref.vtk")
146 data.save(f"{output_base_directory + test_base}_{output_base_file}_data_in.vtk")
147 data_out.save(f"{output_base_directory + test_base}_{output_base_file}_data_out.vtk")
148 
149 print(f"{test_base} ICP transformation:\n{T}".replace("[", " ").replace("]", " "))
Definition: icp.py:1
void setLogger(std::shared_ptr< Logger > newLogger)
Set a new logger, protected by a mutex.
Definition: Logger.cpp:98


libpointmatcher
Author(s):
autogenerated on Sat May 27 2023 02:38:02