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/*!
39 * @brief Determines whether a camera distortion model is suitable for use in OpenCV as a fisheye distortion.
40 *
41 * @param model The distortion model in question.
42 */
43static inline bool
45{
46 return model == T_DISTORTION_FISHEYE_KB4;
47}
48
49/*!
50 * @brief Determines whether a camera distortion model is suitable for use in OpenCV as a non-fisheye distortion.
51 *
52 * @param model The distortion model in question.
53 */
54static inline bool
56{
57 switch (model) {
61 // @note WMR is not supported by OpenCV, but we re-interpret it into a format which is, so this is also valid.
62 case T_DISTORTION_WMR: return true;
63 default: return false;
64 }
65}
66
67/*!
68 * @brief Essential calibration data wrapped for C++.
69 *
70 * Like the cv::Mat that it holds, this object does not own all the memory
71 * it points to!
72 */
74{
76 xrt_size &image_size_pixels;
77 const cv::Size image_size_pixels_cv;
78 cv::Mat_<double> intrinsics_mat;
79 cv::Mat_<double> distortion_mat;
80 enum t_camera_distortion_model &distortion_model;
81
83 : base(calib), //
84 image_size_pixels(calib.image_size_pixels), //
85 image_size_pixels_cv(calib.image_size_pixels.w, calib.image_size_pixels.h), //
86 intrinsics_mat(3, 3, &calib.intrinsics[0][0]), //
87 distortion_mat(t_num_opencv_params_from_distortion_model(base.distortion_model),
88 1,
89 &calib.distortion_parameters_as_array[0]), //
90 distortion_model(calib.distortion_model)
91 {
93 U_LOG_W("Reinterpreting T_DISTORTION_WMR model as T_DISTORTION_OPENCV_RADTAN_8!");
94 }
95 assert(isDataStorageValid());
96 }
97
98 //! Try to verify nothing was reallocated.
99 bool
100 isDataStorageValid() const noexcept
101 {
102 return intrinsics_mat.size() == cv::Size(3, 3) &&
103 (double *)intrinsics_mat.data == &(base.intrinsics[0][0]) &&
104 (base.distortion_model != T_DISTORTION_FISHEYE_KB4 || distortion_mat.size() == cv::Size(1, 4)) &&
105 distortion_mat.size() ==
106 cv::Size(1, t_num_opencv_params_from_distortion_model(base.distortion_model)) &&
107 (double *)distortion_mat.data == &(base.distortion_parameters_as_array[0]);
108 }
109};
110
111
112/*!
113 * @brief Essential stereo calibration data wrapped for C++.
114 *
115 * Like the cv::Mat that it holds, this object does not own (all) the
116 * memory it points to!
117 */
119{
122 cv::Mat_<double> camera_translation_mat;
123 cv::Mat_<double> camera_rotation_mat;
124 cv::Mat_<double> camera_essential_mat;
125 cv::Mat_<double> camera_fundamental_mat;
126
127
129 allocData(enum t_camera_distortion_model distortion_model)
130 {
131 t_stereo_camera_calibration *data_ptr = NULL;
132 t_stereo_camera_calibration_alloc(&data_ptr, distortion_model);
133 return data_ptr;
134 }
135
137 : base(stereo), view{CameraCalibrationWrapper{stereo->view[0]}, CameraCalibrationWrapper{stereo->view[1]}},
138 camera_translation_mat(3, 1, &stereo->camera_translation[0]),
139 camera_rotation_mat(3, 3, &stereo->camera_rotation[0][0]),
140 camera_essential_mat(3, 3, &stereo->camera_essential[0][0]),
141 camera_fundamental_mat(3, 3, &stereo->camera_fundamental[0][0])
142 {
143 // Correct reference counting.
144 t_stereo_camera_calibration *temp = NULL;
145 t_stereo_camera_calibration_reference(&temp, stereo);
146
147 assert(isDataStorageValid());
148 }
149
151 : StereoCameraCalibrationWrapper(allocData(distortion_model))
152 {
153
154 // The function allocData returns with a ref count of one,
155 // the constructor increments the refcount with one,
156 // so to correct it we need to decrement the ref count with one.
158 t_stereo_camera_calibration_reference(&tmp, NULL);
159 }
160
162 {
163 t_stereo_camera_calibration_reference(&base, NULL);
164 }
165
166 bool
167 isDataStorageValid() const noexcept
168 {
169 return camera_translation_mat.size() == cv::Size(1, 3) &&
170 (double *)camera_translation_mat.data == &base->camera_translation[0] &&
171
172 camera_rotation_mat.size() == cv::Size(3, 3) &&
173 (double *)camera_rotation_mat.data == &base->camera_rotation[0][0] &&
174
175 camera_essential_mat.size() == cv::Size(3, 3) &&
176 (double *)camera_essential_mat.data == &base->camera_essential[0][0] &&
177
178 camera_fundamental_mat.size() == cv::Size(3, 3) &&
179 (double *)camera_fundamental_mat.data == &base->camera_fundamental[0][0] &&
180
181 view[0].isDataStorageValid() && view[1].isDataStorageValid();
182 }
183};
184
185
186/*!
187 * @brief An x,y pair of matrices for the remap() function.
188 *
189 * @see calibration_get_undistort_map
190 */
192{
193 cv::Mat remap_x;
194 cv::Mat remap_y;
195};
196
197/*!
198 * @brief Prepare undistortion/normalization remap structures for a rectilinear
199 * or fisheye image.
200 *
201 * @param calib A single camera calibration structure.
202 * @param rectify_transform_optional A rectification transform to apply, if
203 * desired.
204 * @param new_camera_matrix_optional Unlike OpenCV, the default/empty matrix
205 * here uses the input camera matrix as your output camera matrix.
206 */
209 cv::InputArray rectify_transform_optional = cv::noArray(),
210 cv::Mat new_camera_matrix_optional = cv::Mat());
211
212/*!
213 * @brief Rectification, rotation, projection data for a single view in a stereo
214 * pair.
215 *
216 * @see StereoRectificationMaps
217 */
219{
220 RemapPair rectify;
221 cv::Mat rotation_mat = {};
222 cv::Mat projection_mat = {};
223};
224
225/*!
226 * @brief Rectification maps as well as transforms for a stereo camera.
227 *
228 * Computed in the constructor from saved calibration data.
229 */
231{
232 ViewRectification view[2];
233
234 //! Disparity and position to camera world coordinates.
236
237 /*!
238 * @brief Constructor - produces rectification data for a stereo camera
239 * based on calibration data.
240 */
242};
243
244
245/*!
246 * @brief Provides cached, precomputed normalized image coordinates from original, distorted ones.
247 *
248 * Populates internal structures using cv::undistortPoints() and performs
249 * subpixel sampling to interpolate for each query. Essentially, this class lets
250 * you perform cv::undistortPoints() while caching the initial setup work
251 * required for that function.
252 */
254{
255public:
256 /*!
257 * @brief Set up the precomputed cache for a given camera.
258 *
259 * @param size Size of the image in pixels
260 * @param distortion_model Model used with `distortion`
261 * @param intrinsics Camera intrinsics matrix
262 * @param distortion Distortion coefficients
263 * @param rectification Rectification matrix - corresponds to parameter
264 * `R` to cv::undistortPoints().
265 * @param new_camera_or_projection_matrix A new 3x3 camera matrix or
266 * 3x4 projection matrix - corresponds to parameter `P` to
267 * cv::undistortPoints().
268 */
269 NormalizedCoordsCache(cv::Size size,
270 t_camera_distortion_model distortion_model,
271 cv::InputArray intrinsics,
272 cv::InputArray distortion,
273 cv::InputArray rectification = cv::noArray(),
274 cv::InputArray new_camera_or_projection_matrix = cv::noArray());
275
276 /*!
277 * @brief Get normalized, undistorted coordinates from a point in the
278 * original (distorted, etc.) image.
279 *
280 * @param origCoords Image coordinates in original image
281 *
282 * @return Corresponding undistorted coordinates in a "normalized" image
283 */
284 cv::Vec2f
285 getNormalizedImageCoords(cv::Point2f origCoords) const;
286
287 /*!
288 * @brief Get normalized vector in the camera-space direction
289 * corresponding to the original (distorted, etc.) image coordinates.
290 *
291 * Note that the Z component will be negative by convention.
292 */
293 cv::Vec3f
294 getNormalizedVector(cv::Point2f origCoords) const;
295
296private:
297 cv::Mat_<float> cacheX_;
298 cv::Mat_<float> cacheY_;
299};
300
301} // namespace xrt::auxiliary::tracking
Provides cached, precomputed normalized image coordinates from original, distorted ones.
Definition: t_calibration_opencv.hpp:254
cv::Vec3f getNormalizedVector(cv::Point2f origCoords) const
Get normalized vector in the camera-space direction corresponding to the original (distorted,...
Definition: t_calibration.cpp:1468
cv::Vec2f getNormalizedImageCoords(cv::Point2f origCoords) const
Get normalized, undistorted coordinates from a point in the original (distorted, etc....
Definition: t_calibration.cpp:1447
NormalizedCoordsCache(cv::Size size, t_camera_distortion_model distortion_model, cv::InputArray intrinsics, cv::InputArray distortion, cv::InputArray rectification=cv::noArray(), cv::InputArray new_camera_or_projection_matrix=cv::noArray())
Set up the precomputed cache for a given camera.
Definition: t_calibration.cpp:1421
#define U_LOG_W(...)
Log a message at U_LOGGING_WARN level, conditional on the global log level.
Definition: u_logging.h:407
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_OPENCV_RADTAN_5
OpenCV's radial-tangential distortion model.
Definition: t_tracking.h:73
@ 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
@ T_DISTORTION_OPENCV_RADTAN_14
OpenCV's radial-tangential distortion model.
Definition: t_tracking.h:101
Essential calibration data for a single camera, or single lens/sensor of a stereo camera.
Definition: t_tracking.h:236
double intrinsics[3][3]
Camera intrinsics matrix.
Definition: t_tracking.h:241
struct xrt_size image_size_pixels
Source image size.
Definition: t_tracking.h:238
enum t_camera_distortion_model distortion_model
Distortion model that this camera uses.
Definition: t_tracking.h:254
Stereo camera calibration data to be given to trackers.
Definition: t_tracking.h:261
double camera_essential[3][3]
Essential matrix.
Definition: t_tracking.h:274
double camera_translation[3]
Translation from first to second in the stereo pair.
Definition: t_tracking.h:269
struct t_camera_calibration view[2]
Calibration of individual views/sensor.
Definition: t_tracking.h:266
double camera_rotation[3][3]
Rotation matrix from first to second in the stereo pair.
Definition: t_tracking.h:271
double camera_fundamental[3][3]
Fundamental matrix.
Definition: t_tracking.h:276
Definition: comp_scratch.c:130
Essential calibration data wrapped for C++.
Definition: t_calibration_opencv.hpp:74
bool isDataStorageValid() const noexcept
Try to verify nothing was reallocated.
Definition: t_calibration_opencv.hpp:100
An x,y pair of matrices for the remap() function.
Definition: t_calibration_opencv.hpp:192
Essential stereo calibration data wrapped for C++.
Definition: t_calibration_opencv.hpp:119
Rectification maps as well as transforms for a stereo camera.
Definition: t_calibration_opencv.hpp:231
StereoRectificationMaps(t_stereo_camera_calibration *data)
Constructor - produces rectification data for a stereo camera based on calibration data.
Definition: t_file.cpp:111
cv::Mat disparity_to_depth_mat
Disparity and position to camera world coordinates.
Definition: t_calibration_opencv.hpp:235
Rectification, rotation, projection data for a single view in a stereo pair.
Definition: t_calibration_opencv.hpp:219
Image size.
Definition: xrt_defines.h:408
static bool t_camera_distortion_model_is_opencv_non_fisheye(const enum t_camera_distortion_model model)
Determines whether a camera distortion model is suitable for use in OpenCV as a non-fisheye distortio...
Definition: t_calibration_opencv.hpp:55
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:72
static bool t_camera_distortion_model_is_opencv_fisheye(const enum t_camera_distortion_model model)
Determines whether a camera distortion model is suitable for use in OpenCV as a fisheye distortion.
Definition: t_calibration_opencv.hpp:44
Tracking API interface.