Skip to content

Commit ed90121

Browse files
authored
Merge pull request #1816 from truher/team100_camera_resectioning
add example CameraResectioning.py
2 parents 017044e + 25a5f81 commit ed90121

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# pylint: disable=consider-using-from-import,invalid-name,no-name-in-module,no-member,missing-function-docstring
2+
"""
3+
This is a 1:1 transcription of CameraResectioning.cpp.
4+
"""
5+
import numpy as np
6+
from gtsam import Cal3_S2, CustomFactor, LevenbergMarquardtOptimizer, KeyVector
7+
from gtsam import NonlinearFactor, NonlinearFactorGraph
8+
from gtsam import PinholeCameraCal3_S2, Point2, Point3, Pose3, Rot3, Values
9+
from gtsam.noiseModel import Base as SharedNoiseModel, Diagonal
10+
from gtsam.symbol_shorthand import X
11+
12+
13+
def resectioning_factor(
14+
model: SharedNoiseModel,
15+
key: int,
16+
calib: Cal3_S2,
17+
p: Point2,
18+
P: Point3,
19+
) -> NonlinearFactor:
20+
21+
def error_func(this: CustomFactor, v: Values, H: list[np.ndarray]) -> np.ndarray:
22+
pose = v.atPose3(this.keys()[0])
23+
camera = PinholeCameraCal3_S2(pose, calib)
24+
if H is None:
25+
return camera.project(P) - p
26+
Dpose = np.zeros((2, 6), order="F")
27+
Dpoint = np.zeros((2, 3), order="F")
28+
Dcal = np.zeros((2, 5), order="F")
29+
result = camera.project(P, Dpose, Dpoint, Dcal) - p
30+
H[0] = Dpose
31+
return result
32+
33+
return CustomFactor(model, KeyVector([key]), error_func)
34+
35+
36+
def main() -> None:
37+
"""
38+
Camera: f = 1, Image: 100x100, center: 50, 50.0
39+
Pose (ground truth): (Xw, -Yw, -Zw, [0,0,2.0]')
40+
Known landmarks:
41+
3D Points: (10,10,0) (-10,10,0) (-10,-10,0) (10,-10,0)
42+
Perfect measurements:
43+
2D Point: (55,45) (45,45) (45,55) (55,55)
44+
"""
45+
46+
# read camera intrinsic parameters
47+
calib = Cal3_S2(1, 1, 0, 50, 50)
48+
49+
# 1. create graph
50+
graph = NonlinearFactorGraph()
51+
52+
# 2. add factors to the graph
53+
measurement_noise = Diagonal.Sigmas(np.array([0.5, 0.5]))
54+
graph.add(
55+
resectioning_factor(
56+
measurement_noise, X(1), calib, Point2(55, 45), Point3(10, 10, 0)
57+
)
58+
)
59+
graph.add(
60+
resectioning_factor(
61+
measurement_noise, X(1), calib, Point2(45, 45), Point3(-10, 10, 0)
62+
)
63+
)
64+
graph.add(
65+
resectioning_factor(
66+
measurement_noise, X(1), calib, Point2(45, 55), Point3(-10, -10, 0)
67+
)
68+
)
69+
graph.add(
70+
resectioning_factor(
71+
measurement_noise, X(1), calib, Point2(55, 55), Point3(10, -10, 0)
72+
)
73+
)
74+
75+
# 3. Create an initial estimate for the camera pose
76+
initial: Values = Values()
77+
initial.insert(X(1), Pose3(Rot3(1, 0, 0, 0, -1, 0, 0, 0, -1), Point3(0, 0, 1)))
78+
79+
# 4. Optimize the graph using Levenberg-Marquardt
80+
result: Values = LevenbergMarquardtOptimizer(graph, initial).optimize()
81+
result.print("Final result:\n")
82+
83+
84+
if __name__ == "__main__":
85+
main()

0 commit comments

Comments
 (0)