add example CameraResectioning.py
							parent
							
								
									3aca281caf
								
							
						
					
					
						commit
						25a5f81070
					
				|  | @ -0,0 +1,85 @@ | |||
| # pylint: disable=consider-using-from-import,invalid-name,no-name-in-module,no-member,missing-function-docstring | ||||
| """ | ||||
| This is a 1:1 transcription of CameraResectioning.cpp. | ||||
| """ | ||||
| import numpy as np | ||||
| from gtsam import Cal3_S2, CustomFactor, LevenbergMarquardtOptimizer, KeyVector | ||||
| from gtsam import NonlinearFactor, NonlinearFactorGraph | ||||
| from gtsam import PinholeCameraCal3_S2, Point2, Point3, Pose3, Rot3, Values | ||||
| from gtsam.noiseModel import Base as SharedNoiseModel, Diagonal | ||||
| from gtsam.symbol_shorthand import X | ||||
| 
 | ||||
| 
 | ||||
| def resectioning_factor( | ||||
|     model: SharedNoiseModel, | ||||
|     key: int, | ||||
|     calib: Cal3_S2, | ||||
|     p: Point2, | ||||
|     P: Point3, | ||||
| ) -> NonlinearFactor: | ||||
| 
 | ||||
|     def error_func(this: CustomFactor, v: Values, H: list[np.ndarray]) -> np.ndarray: | ||||
|         pose = v.atPose3(this.keys()[0]) | ||||
|         camera = PinholeCameraCal3_S2(pose, calib) | ||||
|         if H is None: | ||||
|             return camera.project(P) - p | ||||
|         Dpose = np.zeros((2, 6), order="F") | ||||
|         Dpoint = np.zeros((2, 3), order="F") | ||||
|         Dcal = np.zeros((2, 5), order="F") | ||||
|         result = camera.project(P, Dpose, Dpoint, Dcal) - p | ||||
|         H[0] = Dpose | ||||
|         return result | ||||
| 
 | ||||
|     return CustomFactor(model, KeyVector([key]), error_func) | ||||
| 
 | ||||
| 
 | ||||
| def main() -> None: | ||||
|     """ | ||||
|     Camera: f = 1, Image: 100x100, center: 50, 50.0 | ||||
|     Pose (ground truth): (Xw, -Yw, -Zw, [0,0,2.0]') | ||||
|     Known landmarks: | ||||
|        3D Points: (10,10,0) (-10,10,0) (-10,-10,0) (10,-10,0) | ||||
|     Perfect measurements: | ||||
|        2D Point:  (55,45)   (45,45)    (45,55)     (55,55) | ||||
|     """ | ||||
| 
 | ||||
|     # read camera intrinsic parameters | ||||
|     calib = Cal3_S2(1, 1, 0, 50, 50) | ||||
| 
 | ||||
|     # 1. create graph | ||||
|     graph = NonlinearFactorGraph() | ||||
| 
 | ||||
|     # 2. add factors to the graph | ||||
|     measurement_noise = Diagonal.Sigmas(np.array([0.5, 0.5])) | ||||
|     graph.add( | ||||
|         resectioning_factor( | ||||
|             measurement_noise, X(1), calib, Point2(55, 45), Point3(10, 10, 0) | ||||
|         ) | ||||
|     ) | ||||
|     graph.add( | ||||
|         resectioning_factor( | ||||
|             measurement_noise, X(1), calib, Point2(45, 45), Point3(-10, 10, 0) | ||||
|         ) | ||||
|     ) | ||||
|     graph.add( | ||||
|         resectioning_factor( | ||||
|             measurement_noise, X(1), calib, Point2(45, 55), Point3(-10, -10, 0) | ||||
|         ) | ||||
|     ) | ||||
|     graph.add( | ||||
|         resectioning_factor( | ||||
|             measurement_noise, X(1), calib, Point2(55, 55), Point3(10, -10, 0) | ||||
|         ) | ||||
|     ) | ||||
| 
 | ||||
|     # 3. Create an initial estimate for the camera pose | ||||
|     initial: Values = Values() | ||||
|     initial.insert(X(1), Pose3(Rot3(1, 0, 0, 0, -1, 0, 0, 0, -1), Point3(0, 0, 1))) | ||||
| 
 | ||||
|     # 4. Optimize the graph using Levenberg-Marquardt | ||||
|     result: Values = LevenbergMarquardtOptimizer(graph, initial).optimize() | ||||
|     result.print("Final result:\n") | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     main() | ||||
		Loading…
	
		Reference in New Issue