Monado OpenXR Runtime
t_calibration_opencv.hpp
Go to the documentation of this file.
1// Copyright 2019-2020, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief OpenCV calibration helpers.
6 * @author Pete Black <pblack@collabora.com>
7 * @author Jakob Bornecrantz <jakob@collabora.com>
8 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
9 * @ingroup aux_tracking
10 */
11
12#pragma once
13
14#ifndef __cplusplus
15#error "This header is C++-only."
16#endif
17
18#include "tracking/t_tracking.h"
19
20#include <opencv2/opencv.hpp>
21#include <sys/stat.h>
22
23namespace xrt::auxiliary::tracking {
24
25static inline size_t
26t_num_opencv_params_from_distortion_model(const enum t_camera_distortion_model model)
27{
28 switch (model) {
30 // OpenCV doesn't know what to do with codx, cody or rpmax. We reinterpret it as
31 // T_DISTORTION_OPENCV_RADTAN_8.
33 break;
34 default: return t_num_params_from_distortion_model(model);
35 }
36}
37/*!
38 * @brief Essential calibration data wrapped for C++.
39 *
40 * Like the cv::Mat that it holds, this object does not own all the memory
41 * it points to!
42 */
44{
46 xrt_size &image_size_pixels;
47 const cv::Size image_size_pixels_cv;
48 cv::Mat_<double> intrinsics_mat;
49 cv::Mat_<double> distortion_mat;
50 enum t_camera_distortion_model &distortion_model;
51
53 : base(calib), //
54 image_size_pixels(calib.image_size_pixels), //
55 image_size_pixels_cv(calib.image_size_pixels.w, calib.image_size_pixels.h), //
56 intrinsics_mat(3, 3, &calib.intrinsics[0][0]), //
57 distortion_mat(t_num_opencv_params_from_distortion_model(base.distortion_model),
58 1,
59 &calib.distortion_parameters_as_array[0]), //
60 distortion_model(calib.distortion_model)
61 {
63 U_LOG_W("Reinterpreting T_DISTORTION_WMR model as T_DISTORTION_OPENCV_RADTAN_8!");
64 }
65 assert(isDataStorageValid());
66 }
67
68 //! Try to verify nothing was reallocated.
69 bool
70 isDataStorageValid() const noexcept
71 {
72 return intrinsics_mat.size() == cv::Size(3, 3) &&
73 (double *)intrinsics_mat.data == &(base.intrinsics[0][0]) &&
74 (base.distortion_model != T_DISTORTION_FISHEYE_KB4 || distortion_mat.size() == cv::Size(1, 4)) &&
75 distortion_mat.size() ==
76 cv::Size(1, t_num_opencv_params_from_distortion_model(base.distortion_model)) &&
77 (double *)distortion_mat.data == &(base.distortion_parameters_as_array[0]);
78 }
79};
80
81
82/*!
83 * @brief Essential stereo calibration data wrapped for C++.
84 *
85 * Like the cv::Mat that it holds, this object does not own (all) the
86 * memory it points to!
87 */
89{
92 cv::Mat_<double> camera_translation_mat;
93 cv::Mat_<double> camera_rotation_mat;
94 cv::Mat_<double> camera_essential_mat;
95 cv::Mat_<double> camera_fundamental_mat;
96
97
99 allocData(enum t_camera_distortion_model distortion_model)
100 {
101 t_stereo_camera_calibration *data_ptr = NULL;
102 t_stereo_camera_calibration_alloc(&data_ptr, distortion_model);
103 return data_ptr;
104 }
105
107 : base(stereo), view{CameraCalibrationWrapper{stereo->view[0]}, CameraCalibrationWrapper{stereo->view[1]}},
108 camera_translation_mat(3, 1, &stereo->camera_translation[0]),
109 camera_rotation_mat(3, 3, &stereo->camera_rotation[0][0]),
110 camera_essential_mat(3, 3, &stereo->camera_essential[0][0]),
111 camera_fundamental_mat(3, 3, &stereo->camera_fundamental[0][0])
112 {
113 // Correct reference counting.
114 t_stereo_camera_calibration *temp = NULL;
115 t_stereo_camera_calibration_reference(&temp, stereo);
116
117 assert(isDataStorageValid());
118 }
119
121 : StereoCameraCalibrationWrapper(allocData(distortion_model))
122 {
123
124 // The function allocData returns with a ref count of one,
125 // the constructor increments the refcount with one,
126 // so to correct it we need to decrement the ref count with one.
128 t_stereo_camera_calibration_reference(&tmp, NULL);
129 }
130
132 {
133 t_stereo_camera_calibration_reference(&base, NULL);
134 }
135
136 bool
137 isDataStorageValid() const noexcept
138 {
139 return camera_translation_mat.size() == cv::Size(1, 3) &&
140 (double *)camera_translation_mat.data == &base->camera_translation[0] &&
141
142 camera_rotation_mat.size() == cv::Size(3, 3) &&
143 (double *)camera_rotation_mat.data == &base->camera_rotation[0][0] &&
144
145 camera_essential_mat.size() == cv::Size(3, 3) &&
146 (double *)camera_essential_mat.data == &base->camera_essential[0][0] &&
147
148 camera_fundamental_mat.size() == cv::Size(3, 3) &&
149 (double *)camera_fundamental_mat.data == &base->camera_fundamental[0][0] &&
150
151 view[0].isDataStorageValid() && view[1].isDataStorageValid();
152 }
153};
154
155
156/*!
157 * @brief An x,y pair of matrices for the remap() function.
158 *
159 * @see calibration_get_undistort_map
160 */
162{
163 cv::Mat remap_x;
164 cv::Mat remap_y;
165};
166
167/*!
168 * @brief Prepare undistortion/normalization remap structures for a rectilinear
169 * or fisheye image.
170 *
171 * @param calib A single camera calibration structure.
172 * @param rectify_transform_optional A rectification transform to apply, if
173 * desired.
174 * @param new_camera_matrix_optional Unlike OpenCV, the default/empty matrix
175 * here uses the input camera matrix as your output camera matrix.
176 */
179 cv::InputArray rectify_transform_optional = cv::noArray(),
180 cv::Mat new_camera_matrix_optional = cv::Mat());
181
182/*!
183 * @brief Rectification, rotation, projection data for a single view in a stereo
184 * pair.
185 *
186 * @see StereoRectificationMaps
187 */
189{
190 RemapPair rectify;
191 cv::Mat rotation_mat = {};
192 cv::Mat projection_mat = {};
193};
194
195/*!
196 * @brief Rectification maps as well as transforms for a stereo camera.
197 *
198 * Computed in the constructor from saved calibration data.
199 */
201{
202 ViewRectification view[2];
203
204 //! Disparity and position to camera world coordinates.
206
207 /*!
208 * @brief Constructor - produces rectification data for a stereo camera
209 * based on calibration data.
210 */
212};
213
214
215/*!
216 * @brief Provides cached, precomputed normalized image coordinates from original, distorted ones.
217 *
218 * Populates internal structures using cv::undistortPoints() and performs
219 * subpixel sampling to interpolate for each query. Essentially, this class lets
220 * you perform cv::undistortPoints() while caching the initial setup work
221 * required for that function.
222 */
224{
225public:
226 /*!
227 * @brief Set up the precomputed cache for a given camera.
228 *
229 * @param size Size of the image in pixels
230 * @param intrinsics Camera intrinsics matrix
231 * @param distortion Distortion coefficients
232 *
233 * This overload applies no rectification (`R`) and uses a
234 * normalized/identity new camera matrix (`P`).
235 */
236 NormalizedCoordsCache(cv::Size size, const cv::Matx33d &intrinsics, const cv::Matx<double, 5, 1> &distortion);
237 /*!
238 * @brief Set up the precomputed cache for a given camera (overload for
239 * rectification and new camera matrix)
240 *
241 * @param size Size of the image in pixels
242 * @param intrinsics Camera intrinsics matrix
243 * @param distortion Distortion coefficients
244 * @param rectification Rectification matrix - corresponds to parameter
245 * `R` to cv::undistortPoints().
246 * @param new_camera_matrix A 3x3 new camera matrix - corresponds to
247 * parameter `P` to cv::undistortPoints().
248 */
249 NormalizedCoordsCache(cv::Size size,
250 const cv::Matx33d &intrinsics,
251 const cv::Matx<double, 5, 1> &distortion,
252 const cv::Matx33d &rectification,
253 const cv::Matx33d &new_camera_matrix);
254
255 /*!
256 * @brief Set up the precomputed cache for a given camera. (overload for
257 * rectification and new projection matrix)
258 *
259 * @param size Size of the image in pixels
260 * @param intrinsics Camera intrinsics matrix
261 * @param distortion Distortion coefficients
262 * @param rectification Rectification matrix - corresponds to parameter
263 * `R` to cv::undistortPoints().
264 * @param new_projection_matrix A 3x4 new projection matrix -
265 * corresponds to parameter `P` to cv::undistortPoints().
266 */
267 NormalizedCoordsCache(cv::Size size,
268 const cv::Matx33d &intrinsics,
269 const cv::Matx<double, 5, 1> &distortion,
270 const cv::Matx33d &rectification,
271 const cv::Matx<double, 3, 4> &new_projection_matrix);
272
273 /*!
274 * @brief Set up the precomputed cache for a given camera.
275 *
276 * Less-strongly-typed overload.
277 *
278 * @overload
279 *
280 * This overload applies no rectification (`R`) and uses a
281 * normalized/identity new camera matrix (`P`).
282 */
283 NormalizedCoordsCache(cv::Size size, const cv::Mat &intrinsics, const cv::Mat &distortion);
284
285 /*!
286 * @brief Get normalized, undistorted coordinates from a point in the
287 * original (distorted, etc.) image.
288 *
289 * @param origCoords Image coordinates in original image
290 *
291 * @return Corresponding undistorted coordinates in a "normalized" image
292 */
293 cv::Vec2f
294 getNormalizedImageCoords(cv::Point2f origCoords) const;
295
296 /*!
297 * @brief Get normalized vector in the camera-space direction
298 * corresponding to the original (distorted, etc.) image coordinates.
299 *
300 * Note that the Z component will be negative by convention.
301 */
302 cv::Vec3f
303 getNormalizedVector(cv::Point2f origCoords) const;
304
305private:
306 cv::Mat_<float> cacheX_;
307 cv::Mat_<float> cacheY_;
308};
309
310} // namespace xrt::auxiliary::tracking
Provides cached, precomputed normalized image coordinates from original, distorted ones.
Definition: t_calibration_opencv.hpp:224
cv::Vec3f getNormalizedVector(cv::Point2f origCoords) const
Get normalized vector in the camera-space direction corresponding to the original (distorted,...
Definition: t_calibration.cpp:1490
NormalizedCoordsCache(cv::Size size, const cv::Matx33d &intrinsics, const cv::Matx< double, 5, 1 > &distortion)
Set up the precomputed cache for a given camera.
Definition: t_calibration.cpp:1414
cv::Vec2f getNormalizedImageCoords(cv::Point2f origCoords) const
Get normalized, undistorted coordinates from a point in the original (distorted, etc....
Definition: t_calibration.cpp:1469
#define U_LOG_W(...)
Log a message at U_LOGGING_WARN level, conditional on the global log level.
Definition: u_logging.h:301
static size_t t_num_params_from_distortion_model(const enum t_camera_distortion_model model)
Returns the number of parameters needed for this t_camera_distortion_model to be held by an OpenCV Ma...
Definition: t_tracking.h:161
t_camera_distortion_model
The distortion model this camera calibration falls under.
Definition: t_tracking.h:63
@ T_DISTORTION_OPENCV_RADTAN_8
OpenCV's radial-tangential distortion model.
Definition: t_tracking.h:82
@ T_DISTORTION_FISHEYE_KB4
Juho Kannalla and Sami Sebastian Brandt's fisheye distortion model.
Definition: t_tracking.h:116
@ T_DISTORTION_WMR
Windows Mixed Reality headsets' camera model.
Definition: t_tracking.h:131
Essential calibration data for a single camera, or single lens/sensor of a stereo camera.
Definition: t_tracking.h:223
double intrinsics[3][3]
Camera intrinsics matrix.
Definition: t_tracking.h:228
struct xrt_size image_size_pixels
Source image size.
Definition: t_tracking.h:225
enum t_camera_distortion_model distortion_model
Distortion model that this camera uses.
Definition: t_tracking.h:241
Stereo camera calibration data to be given to trackers.
Definition: t_tracking.h:248
double camera_essential[3][3]
Essential matrix.
Definition: t_tracking.h:261
double camera_translation[3]
Translation from first to second in the stereo pair.
Definition: t_tracking.h:256
struct t_camera_calibration view[2]
Calibration of individual views/sensor.
Definition: t_tracking.h:253
double camera_rotation[3][3]
Rotation matrix from first to second in the stereo pair.
Definition: t_tracking.h:258
double camera_fundamental[3][3]
Fundamental matrix.
Definition: t_tracking.h:263
Definition: comp_scratch.c:122
Essential calibration data wrapped for C++.
Definition: t_calibration_opencv.hpp:44
bool isDataStorageValid() const noexcept
Try to verify nothing was reallocated.
Definition: t_calibration_opencv.hpp:70
An x,y pair of matrices for the remap() function.
Definition: t_calibration_opencv.hpp:162
Essential stereo calibration data wrapped for C++.
Definition: t_calibration_opencv.hpp:89
Rectification maps as well as transforms for a stereo camera.
Definition: t_calibration_opencv.hpp:201
StereoRectificationMaps(t_stereo_camera_calibration *data)
Constructor - produces rectification data for a stereo camera based on calibration data.
Definition: t_file.cpp:112
cv::Mat disparity_to_depth_mat
Disparity and position to camera world coordinates.
Definition: t_calibration_opencv.hpp:205
Rectification, rotation, projection data for a single view in a stereo pair.
Definition: t_calibration_opencv.hpp:189
Image size.
Definition: xrt_defines.h:409
RemapPair calibration_get_undistort_map(t_camera_calibration &calib, cv::InputArray rectify_transform_optional=cv::noArray(), cv::Mat new_camera_matrix_optional=cv::Mat())
Prepare undistortion/normalization remap structures for a rectilinear or fisheye image.
Definition: t_file.cpp:71
Tracking API interface.