-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
267 lines (260 loc) · 20.6 KB
/
index.html
File metadata and controls
267 lines (260 loc) · 20.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
<!DOCTYPE html>
<html lang="en">
<head>
<title>CamLab: Interactive Camera Intrinsics Analysis Tool</title>
<meta name="description" content="CamLab lets you explore camera intrinsics, distortion, extrinsics, and chessboard designs in real time." />
<meta name="google-site-verification" content="GW-YKJveTf8AuwYxDb-nZdcywpYg1ez5yTVXkY_H7fo" />
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="column">
<!-- <h1 style="text-align: center;">Camera Intrinsic & Distortion Visualization</h1> -->
<div class="repo-link-row">
<a href="https://github.com/Roxign/CamLab" target="_blank" rel="noopener noreferrer">CamLab on GitHub</a>
</div>
<div class="view-tab-row" role="tablist" aria-label="Visualization view tabs">
<button id="viewChessboard" type="button" role="tab" aria-selected="true" aria-controls="canvas" title="Show the chessboard view for calibration.">Chessboard</button>
<button id="viewCurve" type="button" role="tab" aria-selected="false" aria-controls="curveCanvas" title="Show the distortion curve view for lens analysis.">Distortion Curve</button>
</div>
<div class="canvas-stack">
<canvas id="canvas" width="640" height="360"></canvas>
<canvas id="curveCanvas" class="hidden" width="640" height="480"></canvas>
</div>
<div class="curve-axis-options" id="curveAxisOptions">
<div class="axis-group">
<span>X type:</span>
<label><input type="radio" id="curveXTypeAngle" name="curveXType" value="angle" checked data-curve-axis="x" data-curve-role="type" data-axis-label="incoming ray" title="X axis: Use incoming ray angle as variable."> incoming ray</label>
<label><input type="radio" id="curveXTypeHeight" name="curveXType" value="height" data-curve-axis="x" data-curve-role="type" data-axis-label="reference image height" title="X axis: Use reference image height as variable."> reference height</label>
</div>
<div class="axis-group" id="curveXUnitGroup" data-curve-axis="x" data-curve-role="unit-group">
<span>X unit:</span>
<label><input type="radio" id="curveXUnitDeg" name="curveXUnit" value="deg" checked data-curve-axis="x" data-curve-role="unit" data-unit-kind="angle" title="Degrees (°)"> deg</label>
<label><input type="radio" id="curveXUnitRad" name="curveXUnit" value="rad" data-curve-axis="x" data-curve-role="unit" data-unit-kind="angle" title="Radians (rad)"> rad</label>
<label><input type="radio" id="curveXUnitSlope" name="curveXUnit" value="slope" data-curve-axis="x" data-curve-role="unit" data-unit-kind="angle" title="Slope (tanθ)"> slope (tanθ)</label>
<label><input type="radio" id="curveXUnitPixel" name="curveXUnit" value="pixel" data-curve-axis="x" data-curve-role="unit" data-unit-kind="height" title="Pixels (image units)"> pixel</label>
<label><input type="radio" id="curveXUnitUm" name="curveXUnit" value="um" data-curve-axis="x" data-curve-role="unit" data-unit-kind="height" title="Micrometers (μm)"> um</label>
<label><input type="radio" id="curveXUnitMm" name="curveXUnit" value="mm" data-curve-axis="x" data-curve-role="unit" data-unit-kind="height" title="Millimeters (mm)"> mm</label>
<label><input type="radio" id="curveXUnitCm" name="curveXUnit" value="cm" data-curve-axis="x" data-curve-role="unit" data-unit-kind="height" title="Centimeters (cm)"> cm</label>
<label><input type="radio" id="curveXUnitM" name="curveXUnit" value="m" data-curve-axis="x" data-curve-role="unit" data-unit-kind="height" title="Meters (m)"> m</label>
</div>
<div class="axis-group">
<span>Y type:</span>
<label><input type="radio" id="curveYTypeAngle" name="curveYType" value="angle" checked data-curve-axis="y" data-curve-role="type" data-axis-label="reflected ray" title="Y axis: Use reflected ray angle as variable."> reflected ray</label>
<label><input type="radio" id="curveYTypeHeight" name="curveYType" value="height" data-curve-axis="y" data-curve-role="type" data-axis-label="measured image height" title="Y axis: Use measured image height as variable."> measured height</label>
</div>
<div class="axis-group" id="curveYUnitGroup" data-curve-axis="y" data-curve-role="unit-group">
<span>Y unit:</span>
<label><input type="radio" id="curveYUnitDeg" name="curveYUnit" value="deg" checked data-curve-axis="y" data-curve-role="unit" data-unit-kind="angle" title="Degrees (°)"> deg</label>
<label><input type="radio" id="curveYUnitRad" name="curveYUnit" value="rad" data-curve-axis="y" data-curve-role="unit" data-unit-kind="angle" title="Radians (rad)"> rad</label>
<label><input type="radio" id="curveYUnitSlope" name="curveYUnit" value="slope" data-curve-axis="y" data-curve-role="unit" data-unit-kind="angle" title="Slope (tanθ)"> slope (tanθ)</label>
<label><input type="radio" id="curveYUnitPixel" name="curveYUnit" value="pixel" data-curve-axis="y" data-curve-role="unit" data-unit-kind="height" title="Pixels (image units)"> pixel</label>
<label><input type="radio" id="curveYUnitUm" name="curveYUnit" value="um" data-curve-axis="y" data-curve-role="unit" data-unit-kind="height" title="Micrometers (μm)"> um</label>
<label><input type="radio" id="curveYUnitMm" name="curveYUnit" value="mm" data-curve-axis="y" data-curve-role="unit" data-unit-kind="height" title="Millimeters (mm)"> mm</label>
<label><input type="radio" id="curveYUnitCm" name="curveYUnit" value="cm" data-curve-axis="y" data-curve-role="unit" data-unit-kind="height" title="Centimeters (cm)"> cm</label>
<label><input type="radio" id="curveYUnitM" name="curveYUnit" value="m" data-curve-axis="y" data-curve-role="unit" data-unit-kind="height" title="Meters (m)"> m</label>
</div>
<div class="curve-direction-row" id="curveDirectionControls">
<div class="curve-direction-inputs">
<div class="curve-direction-angle-col">
<div class="curve-direction-angle-row">
<label for="curveDirectionAngleText">image-plane angle (deg)</label>
<input type="text" id="curveDirectionAngleText" value="45">
</div>
<input type="range" id="curveDirectionAngle" min="-180" max="180" value="45" step="1">
<div class="curve-direction-pad" aria-label="Direction presets">
<button type="button" data-curve-direction-target="TL" aria-label="Top-left" title="Set direction to Top-Left">TL</button>
<button type="button" data-curve-direction-target="T" aria-label="Top" title="Set direction to Top">T</button>
<button type="button" data-curve-direction-target="TR" aria-label="Top-right" title="Set direction to Top-Right">TR</button>
<button type="button" data-curve-direction-target="L" aria-label="Left" title="Set direction to Left">L</button>
<span class="curve-direction-pad-hole" aria-hidden="true"></span>
<button type="button" data-curve-direction-target="R" aria-label="Right" title="Set direction to Right">R</button>
<button type="button" data-curve-direction-target="BL" aria-label="Bottom-left" title="Set direction to Bottom-Left">BL</button>
<button type="button" data-curve-direction-target="B" aria-label="Bottom" title="Set direction to Bottom">B</button>
<button type="button" data-curve-direction-target="BR" aria-label="Bottom-right" title="Set direction to Bottom-Right">BR</button>
</div>
</div>
</div>
<div class="curve-direction-preview-wrap">
<canvas id="directionCanvas" width="220" height="124"></canvas>
</div>
</div>
</div>
</div>
<div class="controls">
<div class="column">
<!-- Intrinsic -->
<div>
<label style="font-family: 'sans-serif'; font-weight: bold; font-size: 20px;">Intrinsic:</label>
</div>
<div class="pixel-size-row">
<label for="psText" title="Pixel size in micrometers per pixel (μm/px)">um/px</label>
<input type="text" id="psText" value="1.0" title="Set the pixel size (μm/px)">
</div>
<div>
<label for="iw" title="Image width in pixels">iw</label>
<input type="text" id="iwText" value="1920" title="Set image width (pixels)">
<input type="range" id="iw" name="iw" min="100" max="10000" value="1920" title="Adjust image width (pixels)">
</div>
<div>
<label for="ih" title="Image height in pixels">ih</label>
<input type="text" id="ihText" value="1080" title="Set image height (pixels)">
<input type="range" id="ih" name="ih" min="100" max="10000" value="1080" title="Adjust image height (pixels)">
</div>
<div>
<label for="fx" title="Focal length in x (pixels)">f<sub>x</sub></label>
<input type="text" id="fxText" value="1000" title="Set focal length in x (pixels)">
<input type="range" id="fx" name="fx" min="100" max="10000" value="1000" title="Adjust focal length in x (pixels)">
</div>
<div>
<label for="fy" title="Focal length in y (pixels)">f<sub>y</sub></label>
<input type="text" id="fyText" value="1000" title="Set focal length in y (pixels)">
<input type="range" id="fy" name="fy" min="100" max="10000" value="1000" title="Adjust focal length in y (pixels)">
</div>
<div>
<label for="cx" title="Principal point x-coordinate (pixels)">c<sub>x</sub></label>
<input type="text" id="cxText" value="960" title="Set principal point x (pixels)">
<input type="range" id="cx" name="cx" min="0" max="1920" value="960" title="Adjust principal point x (pixels)">
</div>
<div>
<label for="cy" title="Principal point y-coordinate (pixels)">c<sub>y</sub></label>
<input type="text" id="cyText" value="540" title="Set principal point y (pixels)">
<input type="range" id="cy" name="cy" min="0" max="1080" value="540" title="Adjust principal point y (pixels)">
</div>
<!-- Distortion -->
<div>
<label style="font-family: 'sans-serif'; font-weight: bold; font-size: 20px;">Distortion:</label>
</div>
<div>
<label for="k1" title="Radial distortion coefficient k₁">k<sub>1</sub></label>
<input type="text" id="k1Text" value="0" title="Set k₁ (radial distortion)">
<input type="range" id="k1" name="k1" min="-1" max="1" value="0" step="0.01" title="Adjust k₁ (radial distortion)">
</div>
<div>
<label for="k2" title="Radial distortion coefficient k₂">k<sub>2</sub></label>
<input type="text" id="k2Text" value="0" title="Set k₂ (radial distortion)">
<input type="range" id="k2" name="k2" min="-1" max="1" value="0" step="0.01" title="Adjust k₂ (radial distortion)">
</div>
<div>
<label for="p1" title="Tangential distortion coefficient p₁">p<sub>1</sub></label>
<input type="text" id="p1Text" value="0" title="Set p₁ (tangential distortion)">
<input type="range" id="p1" name="p1" min="-1" max="1" value="0" step="0.01" title="Adjust p₁ (tangential distortion)">
</div>
<div>
<label for="p2" title="Tangential distortion coefficient p₂">p<sub>2</sub></label>
<input type="text" id="p2Text" value="0" title="Set p₂ (tangential distortion)">
<input type="range" id="p2" name="p2" min="-1" max="1" value="0" step="0.01" title="Adjust p₂ (tangential distortion)">
</div>
<div>
<label for="k3" title="Radial distortion coefficient k₃">k<sub>3</sub></label>
<input type="text" id="k3Text" value="0" title="Set k₃ (radial distortion)">
<input type="range" id="k3" name="k3" min="-1" max="1" value="0" step="0.01" title="Adjust k₃ (radial distortion)">
</div>
<div>
<label for="k4" title="Radial distortion coefficient k₄">k<sub>4</sub></label>
<input type="text" id="k4Text" value="0" title="Set k₄ (radial distortion)">
<input type="range" id="k4" name="k4" min="-1" max="1" value="0" step="0.01" title="Adjust k₄ (radial distortion)">
</div>
<div>
<label for="k5" title="Radial distortion coefficient k₅">k<sub>5</sub></label>
<input type="text" id="k5Text" value="0" title="Set k₅ (radial distortion)">
<input type="range" id="k5" name="k5" min="-1" max="1" value="0" step="0.01" title="Adjust k₅ (radial distortion)">
</div>
<div>
<label for="k6" title="Radial distortion coefficient k₆">k<sub>6</sub></label>
<input type="text" id="k6Text" value="0" title="Set k₆ (radial distortion)">
<input type="range" id="k6" name="k6" min="-1" max="1" value="0" step="0.01" title="Adjust k₆ (radial distortion)">
</div>
<div>
<label for="fisheye" title="Enable Kannala-Brandt (KB) fisheye distortion model">KB</label>
<input type="checkbox" id="fisheye" name="fisheye" title="Toggle KB fisheye distortion model">
<span id="fovResultsRow" style="display: flex; gap: 0.4em;">
<span class="axis-fov">hFOV: <span id="hFOVResult">-</span>°</span>
<span class="axis-fov">vFOV: <span id="vFOVResult">-</span>°</span>
<span class="axis-fov">dFOV: <span id="dFOVResult">-</span>°</span>
</span>
</div>
</div>
<div class="column">
<!-- Extrinsic -->
<div class="extrinsic-header-row">
<label style="font-family: 'sans-serif'; font-weight: bold; font-size: 20px;">Extrinsic:</label>
<div class="extrinsic-mode-row" role="tablist" aria-label="Extrinsic transform mode tabs">
<button id="world2cam" type="button" role="tab" aria-selected="true" class="active" title="Transform world coordinates to camera coordinates">world2cam</button>
<button id="cam2world" type="button" role="tab" aria-selected="false" title="Transform camera coordinates to world coordinates">cam2world</button>
</div>
</div>
<div>
<label for="rx" title="Rotation around x-axis (degrees)">r<sub>x</sub></label>
<input type="text" id="rxText" value="0" title="Set rotation x (degrees)">
<input type="range" id="rx" name="rx" min="-180" max="180" value="0" title="Adjust rotation x (degrees)">
</div>
<div>
<label for="ry" title="Rotation around y-axis (degrees)">r<sub>y</sub></label>
<input type="text" id="ryText" value="0" title="Set rotation y (degrees)">
<input type="range" id="ry" name="ry" min="-180" max="180" value="0" title="Adjust rotation y (degrees)">
</div>
<div>
<label for="rz" title="Rotation around z-axis (degrees)">r<sub>z</sub></label>
<input type="text" id="rzText" value="0" title="Set rotation z (degrees)">
<input type="range" id="rz" name="rz" min="-180" max="180" value="0" title="Adjust rotation z (degrees)">
</div>
<div>
<label for="tx" title="Translation along x-axis (mm)">t<sub>x</sub></label>
<input type="text" id="txText" value="0" title="Set translation x (mm)">
<input type="range" id="tx" name="tx" min="-1000" max="1000" value="0" title="Adjust translation x (mm)">
</div>
<div>
<label for="ty" title="Translation along y-axis (mm)">t<sub>y</sub></label>
<input type="text" id="tyText" value="0" title="Set translation y (mm)">
<input type="range" id="ty" name="ty" min="-1000" max="1000" value="0" title="Adjust translation y (mm)">
</div>
<div>
<label for="tz" title="Translation along z-axis (mm)">t<sub>z</sub></label>
<input type="text" id="tzText" value="1000" title="Set translation z (mm)">
<input type="range" id="tz" name="tz" min="-10000" max="10000" value="1000" title="Adjust translation z (mm)">
</div>
<!-- Chessboard -->
<div class="chessboard-header-row">
<label style="font-family: 'sans-serif'; font-weight: bold; font-size: 20px;">Chessboard:</label>
<div class="center-mode-row" role="tablist" aria-label="Chessboard coordinate origin tabs">
<button id="centerAtTL" type="button" role="tab" aria-selected="false" title="TL-CS: Set the chessboard coordinate system origin to the Top-Left corner. Use this if you want (0,0) at the top-left square, matching most image coordinate systems.">TL-CS</button>
<button id="centerAtCenter" type="button" role="tab" aria-selected="true" class="active" title="CT-CS: Set the chessboard coordinate system origin to the Center of the board. Use this if you want (0,0) at the center square, which is common in some calibration workflows.">CT-CS</button>
</div>
</div>
<div>
<!-- number of inner corners along width (bc) and height (br) -->
<label for="bc" title="Number of inner corners along chessboard width">bc</label>
<input type="text" id="bcText" value="12" title="Set number of inner corners (width)">
<input type="range" id="bc" name="bc" min="3" max="100" value="12" title="Adjust number of inner corners (width)">
</div>
<div>
<label for="br" title="Number of inner corners along chessboard height">br</label>
<input type="text" id="brText" value="9" title="Set number of inner corners (height)">
<input type="range" id="br" name="br" min="3" max="100" value="9" title="Adjust number of inner corners (height)">
</div>
<div>
<label for="bw" title="Chessboard square width (mm)">bw</label>
<input type="text" id="bwText" value="100" title="Set chessboard square width (mm)">
<input type="range" id="bw" name="bw" min="1" max="1000" value="100" title="Adjust chessboard square width (mm)">
</div>
<div>
<label for="bh" title="Chessboard square height (mm)">bh</label>
<input type="text" id="bhText" value="100" title="Set chessboard square height (mm)">
<input type="range" id="bh" name="bh" min="1" max="1000" value="100" title="Adjust chessboard square height (mm)">
</div>
<div>
<label for="showSquares" title="Show or hide chessboard squares">■□</label>
<input type="checkbox" id="showSquares" name="showSquares" title="Toggle chessboard squares">
</div>
<div>
<!-- when enabled draw filled circles at each corner after the board is rendered -->
<label for="showCircles" title="Show or hide chessboard circles">●●</label>
<input type="checkbox" id="showCircles" name="showCircles" checked="true" title="Toggle chessboard circles">
</div>
<button id="reset" title="Reset all parameters to default values">Reset</button>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="script.js"></script>
</body>
</html>