UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
perspective.hpp
1
46#ifndef UFO_VISION_CAMERA_PERSPECTIVE_HPP
47#define UFO_VISION_CAMERA_PERSPECTIVE_HPP
48
49// UFO
50#include <ufo/execution/algorithm.hpp>
51#include <ufo/execution/execution.hpp>
52#include <ufo/geometry/ray.hpp>
53#include <ufo/numeric/mat.hpp>
54#include <ufo/numeric/transform.hpp>
55#include <ufo/numeric/vec.hpp>
56#include <ufo/vision/camera/perspective_intrinsics.hpp>
57#include <ufo/vision/image.hpp>
58
59// STL
60#include <cmath>
61#include <cstddef>
62#include <format>
63#include <numbers>
64#include <ostream>
65#include <random>
66#include <utility>
67
68namespace ufo
69{
108 float far_clip;
109
116 void lookAt(Vec3f center, Vec3f const& target, Vec3f const& up)
117 {
118 pose = Transform3f{inverse(ufo::lookAt(center, target, up))};
119 }
120
121 [[nodiscard]] Mat4f projection() const
122 {
123 Mat4f m = perspective(fx(), fy(), intrinsics.cx, intrinsics.cy,
124 static_cast<float>(intrinsics.cols),
125 static_cast<float>(intrinsics.rows), near_clip, far_clip);
126 m[0][0] *= intrinsics.zoom;
127 m[1][1] *= intrinsics.zoom;
128 return m;
129 }
130
131 [[nodiscard]] Mat4f view() const { return Mat4f(pose); }
132
133 [[nodiscard]] Image<Ray3f> rays() const { return rays(ufo::execution::seq); }
134
135 template <class ExecutionPolicy>
136 [[nodiscard]] Image<Ray3f> rays(ExecutionPolicy&& policy) const
137 {
138 auto const view_inv = view();
139 Image<Ray3f> rays(intrinsics.rows, intrinsics.cols);
140
142 std::forward<ExecutionPolicy>(policy), std::size_t{}, intrinsics.rows,
143 [this, &rays, &view_inv, fx = fx(), fy = fy()](std::size_t y) {
144 if (0.0f < intrinsics.lens_radius && 0.0f < intrinsics.focus_distance) {
145 bool const deterministic = intrinsics.deterministic;
146 std::mt19937 gen_local;
147 // Use a static thread_local generator for performance in non-deterministic
148 // mode
149 static thread_local std::mt19937 gen_tl(std::random_device{}());
150
151 std::mt19937& gen = deterministic ? gen_local : gen_tl;
152 std::uniform_real_distribution<float> dist(-1.0f, 1.0f);
153
154 if (deterministic) {
155 gen.seed(static_cast<unsigned>(y * intrinsics.cols));
156 }
157
158 for (std::size_t x{}; rays.cols() > x; ++x) {
159 float const dx = (x + 0.5f - intrinsics.cx) / fx;
160 float const dy = (y + 0.5f - intrinsics.cy) / fy;
161
162 Vec3f dir_cam = normalize(Vec3f(dx, dy, 1.0f));
163
164 float const r = intrinsics.lens_radius * std::sqrt(std::abs(dist(gen)));
165 float const theta = 2.0f * std::numbers::pi_v<float> * dist(gen);
166 Vec3f const origin_cam(r * std::cos(theta), r * std::sin(theta), 0.0f);
167
168 float const ft = intrinsics.focus_distance / dir_cam.z();
169 Vec3f const p_focus = dir_cam * ft;
170 dir_cam = normalize(p_focus - origin_cam);
171
172 rays[y, x].origin = ufo::convert<Vec3f>(
173 view_inv * Vec4f(origin_cam.x(), origin_cam.y(), origin_cam.z(), 1.0f));
174 rays[y, x].direction = ufo::convert<Vec3f>(
175 view_inv * Vec4f(dir_cam.x(), dir_cam.y(), dir_cam.z(), 0.0f));
176 }
177 } else {
178 for (std::size_t x{}; rays.cols() > x; ++x) {
179 float const dx = (x + 0.5f - intrinsics.cx) / fx;
180 float const dy = (y + 0.5f - intrinsics.cy) / fy;
181
182 Vec3f const dir_cam = normalize(Vec3f(dx, dy, 1.0f));
183
184 rays[y, x].origin =
185 ufo::convert<Vec3f>(view_inv * Vec4f(0.0f, 0.0f, 0.0f, 1.0f));
186 rays[y, x].direction = ufo::convert<Vec3f>(
187 view_inv * Vec4f(dir_cam.x(), dir_cam.y(), dir_cam.z(), 0.0f));
188 }
189 }
190 });
191 return rays;
192 }
193
194 [[nodiscard]] float fx() const noexcept
195 {
196 return 0.0f < intrinsics.fx
197 ? intrinsics.fx
198 : intrinsics.rows / (2.0f * std::tan(intrinsics.vertical_fov / 2.0f));
199 }
200
201 [[nodiscard]] float fy() const noexcept
202 {
203 return 0.0f < intrinsics.fy
204 ? intrinsics.fy
205 : intrinsics.rows / (2.0f * std::tan(intrinsics.vertical_fov / 2.0f));
206 }
207
208 [[nodiscard]] friend bool operator==(PerspectiveCamera const&,
209 PerspectiveCamera const&) noexcept = default;
210};
211
215inline std::ostream& operator<<(std::ostream& os, PerspectiveCamera const& camera)
216{
217 os << "Pose: " << camera.pose << '\n'
218 << camera.intrinsics << "\nNear clip: " << camera.near_clip
219 << ", Far clip: " << camera.far_clip << '\n';
220 return os;
221}
222
226} // namespace ufo
227
228template <>
229struct std::formatter<ufo::PerspectiveCamera> {
230 constexpr auto parse(std::format_parse_context& ctx) const { return ctx.begin(); }
231
232 auto format(ufo::PerspectiveCamera const& camera, std::format_context& ctx) const
233 {
234 return std::format_to(ctx.out(), "Pose: {}\n{}\nNear clip: {}, Far clip: {}",
235 camera.pose, camera.intrinsics, camera.near_clip,
236 camera.far_clip);
237 }
238};
239
240#endif // UFO_VISION_CAMERA_PERSPECTIVE_HPP
All vision-related classes and functions.
Definition cloud.hpp:49
constexpr UnaryFunc for_each(Index first, Index last, UnaryFunc f, Proj proj={})
Applies f to each integer index in [first, last) sequentially.
Definition algorithm.hpp:80
Mat< 4, 4, T > perspective(T fovy, T aspect, T near, T far)
Builds a perspective projection matrix (OpenCV convention).
Definition mat.hpp:1412
constexpr Quat< T > normalize(Quat< T > const &q) noexcept
Returns a unit quaternion in the same direction as q.
Definition quat.hpp:679
constexpr M inverse(M const &m) noexcept
Computes the inverse of a square floating-point matrix.
Definition mat.hpp:1097
Mat< 4, 4, T > lookAt(Vec< 3, T > const &eye, Vec< 3, T > const &target, Vec< 3, T > const &up)
Builds a view matrix (OpenCV convention).
Definition mat.hpp:1471
Perspective camera model for ray-generation and projection.
void lookAt(Vec3f center, Vec3f const &target, Vec3f const &up)
Orients the camera so it looks from center toward target.
Transform3f pose
Camera-to-world pose transform.
float far_clip
Distance to the far clipping plane.
float near_clip
Distance to the near clipping plane.
PerspectiveIntrinsics intrinsics
The intrinsic parameters of the camera.
Stores the intrinsic parameters of a perspective camera.
float fy
Vertical focal length in pixels.
float focus_distance
Distance to the focal plane.
float cy
Vertical principal point in pixels.
float fx
Horizontal focal length in pixels.
float vertical_fov
Vertical field of view in radians.
bool deterministic
Whether ray generation should be deterministic.
float cx
Horizontal principal point in pixels.
std::size_t rows
Image height in pixels.
std::size_t cols
Image width in pixels.
float lens_radius
Radius of the camera lens.
Rigid-body transform: a rotation matrix plus a translation vector.
Definition transform.hpp:81