Camera Geometry
Warning
TODO doc
To inspect the results of a pinhole camera calibration, viren2d provides
the following utilities:
Overlay coordinate system axes via
draw_xyz_axes().Estimate and overlay the line of horizon via
draw_horizon_line().
Corresponding Python example code:
1def _calibrated_example():
2 """Example image (`ninja`) and its calibration (estimated via PnP)."""
3 img = viren2d.load_image_uint8(VIREN2D_DATA_PATH / 'ninja.jpg')
4 K = np.array(
5 [[523.17808219, 0.0, 341.0],
6 [ 0.0, 523.17808219, 256.0],
7 [ 0.0, 0.0, 1.0]], dtype=np.float64)
8 R = np.array(
9 [[ 0.99013141, 0.14006482, -0.00465153],
10 [ 0.05439048, -0.41465762, -0.90835056],
11 [-0.12915675, 0.89913342, -0.41818372]], dtype=np.float64)
12 t = np.array([-51.84341161, 17.32680283, 82.51435241], dtype=np.float64)
13 return img, K, R, t
14
15
16def _overlay_axes(painter, K, R, t):
17 """Draws the coordinate system axes."""
18 arrow_style = viren2d.ArrowStyle(
19 width=7, tip_length=35, tip_angle=25)
20 # Instead of (0, 0, 0), we draw the axis origin at (12, 12, 0) to avoid
21 # clipping the z-axis.
22 # The size of a checkerboard grid cell is 24x24 millimeters - the length
23 # of each axis will be 2 grid cells.
24 painter.draw_xyz_axes(
25 K=K, R=R, t=t, origin=(12, 12, 0),
26 lengths=(48, 48, 48), arrow_style=arrow_style)
27
28
29def _overlay_horizon(painter, K, R, t):
30 """Draws the approximated line of horizon."""
31 line_style = viren2d.LineStyle(
32 width=7, color=viren2d.axis_color('z'), dash_pattern=[40, 50],
33 cap='round')
34 horizon = painter.draw_horizon_line(K=K, R=R, t=t, line_style=line_style)
35 if horizon.is_valid():
36 # Add a label
37 text_style = viren2d.TextStyle(family='xkcd', size=29, color='#1a1c1d')
38 line_style.width = 3
39 line_style.dash_pattern = []
40 painter.draw_text_box(
41 ['Line of Horizon'],
42 position=horizon.point_at_offset(0.8) + (0, 10),
43 anchor='top', text_style=text_style, padding=(10, 6),
44 line_style=line_style, fill_color='#c0bab1c0')
45
46
47def demo_pinhole():
48 """Visualizations for calibrated pinhole cameras"""
49 img, K, R, t = _calibrated_example()
50 painter1 = viren2d.Painter(img)
51
52 # Visualize origin/world reference frame: #TODO WIP - needs 3d line clipping
53 _overlay_axes(painter1, K, R, t)
54
55 # Visualize line of horizon
56 _overlay_horizon(painter1, K, R, t)
57
58 # TODO Visualize ground plane
59
60 # Create the collage:
61 canvas_width = 600
62 canvas_height = 255
63 padding = 5
64 scale = (canvas_width / 2 - 2 * padding) / img.shape[1]
65 painter_comb = viren2d.Painter(
66 canvas_height, canvas_width, 'white!0')
67
68 text_style = viren2d.TextStyle(family='xkcd', size=21, color='#c0bab1')
69 line_style = viren2d.LineStyle(width=2, color=text_style.color)
70 bg_color = '#1a1c1dc8'
71
72 painter_comb.draw_image(
73 painter1.canvas, position=(padding, padding), anchor='top-left',
74 scale_x=scale, scale_y=scale, clip_factor=0.1)
75 painter_comb.draw_text_box(
76 ['Axes & Horizon (TBD)'], # TODO update text once finished
77 position=(canvas_width / 4, canvas_height - 2 * padding),
78 anchor='bottom', fill_color=bg_color, text_style=text_style,
79 line_style=line_style, padding=(10, 6))
80
81 # TODO Replace by ground plane visualization
82 dimmed = (0.2 * np.array(img)).astype(np.uint8)
83 painter_comb.draw_image(
84 dimmed, position=(canvas_width - padding, padding),
85 anchor='top-right', scale_x=scale, scale_y=scale, clip_factor=0.1)
86 painter_comb.draw_text_box(
87 ['Ground plane (TBD)'], # TODO update text once finished
88 position=(3 * canvas_width / 4, canvas_height - 2 * padding),
89 anchor='bottom', fill_color=bg_color, text_style=text_style,
90 line_style=line_style, padding=(10, 6))
91
92 return np.array(painter_comb.canvas, copy=True)