MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
OpticalFlow.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Features.hpp"
4
5/**
6 * @file OpticalFlow.hpp
7 * @brief Sparse optical flow via Lucas-Kanade tracker.
8 *
9 * Pure functions. No MayaFlux type dependencies.
10 *
11 * ## Conventions
12 * - All inputs are single-channel normalised float in [0, 1]
13 * - w and h are pixel dimensions; caller ensures span size == w * h
14 * - Keypoint positions are normalised to [0, 1]
15 * - window_radius is the half-size of the tracking window in pixels
16 * - Points that fail to track are returned at their previous position
17 * with tracked = false
18 * - Parallelism handled internally via std::execution::par_unseq
19 */
20
22
23/**
24 * @brief Result for a single tracked point.
25 */
27 glm::vec2 position; ///< Tracked position in normalised [0, 1] coordinates.
28 float error; ///< Residual photometric error after convergence.
29 bool tracked; ///< False if tracking failed or diverged.
30 glm::vec2 previous { 0.0F }; ///< Position of the point in the previous frame, normalised [0, 1].
31 uint32_t id { 0 }; ///< Stable identifier of a persistent track. Zero for stateless trackers.
32 uint32_t age { 0 }; ///< Frames the track was successfully followed before this one.
33};
34
35/**
36 * @brief Track keypoints from prev_gray to curr_gray via Lucas-Kanade.
37 *
38 * For each input point, solves the Lucas-Kanade optical flow equation
39 * within a window_radius x window_radius patch using iterative
40 * Newton-Raphson refinement. Iteration stops when the displacement
41 * update falls below 0.03 pixels or max_iterations is reached.
42 *
43 * A point is marked tracked=false if:
44 * - The structure tensor within its window is near-singular
45 * (min eigenvalue below eigen_threshold)
46 * - The tracked position moves outside the image boundary
47 * - The residual error after convergence exceeds error_threshold
48 * - An enabled backward check misses the source by more than
49 * forward_backward_threshold pixels
50 *
51 * prev_points and the returned vector have the same length and order.
52 * Callers should discard points where tracked == false before passing
53 * to subsequent frames.
54 *
55 * @param prev_gray Previous frame, single-channel float, size w * h.
56 * @param curr_gray Current frame, single-channel float, size w * h.
57 * @param w Image width in pixels.
58 * @param h Image height in pixels.
59 * @param prev_points Points to track in normalised [0, 1] coordinates.
60 * @param window_radius Half-size of the tracking patch in pixels.
61 * @param max_iterations Maximum Newton-Raphson iterations per point.
62 * @param eigen_threshold Minimum eigenvalue for structure tensor validity.
63 * @param error_threshold Maximum residual error to accept a track.
64 * @param forward_backward_threshold Maximum return error in pixels; zero disables the check.
65 * @return TrackResult per input point, same order.
66 */
67[[nodiscard]] MAYAFLUX_API std::vector<TrackResult> track_keypoints(
68 std::span<const float> prev_gray,
69 std::span<const float> curr_gray,
70 uint32_t w, uint32_t h,
71 std::span<const glm::vec2> prev_points,
72 uint32_t window_radius = 7,
73 uint32_t max_iterations = 20,
74 float eigen_threshold = 1e-4F,
75 float error_threshold = 0.3F,
76 float forward_backward_threshold = 0.0F);
77
78/**
79 * @brief Track keypoints using a pre-computed Sobel gradient of prev_gray.
80 *
81 * Identical to the four-parameter overload but accepts caller-supplied dx
82 * and dy of the previous frame, avoiding recomputation when the gradient
83 * is already cached. dx and dy must be the Sobel gradient of prev_gray
84 * at the same w x h resolution.
85 *
86 * @param prev_gray Previous frame, single-channel float, size w * h.
87 * @param curr_gray Current frame, single-channel float, size w * h.
88 * @param grad_dx Horizontal Sobel gradient of prev_gray, size w * h.
89 * @param grad_dy Vertical Sobel gradient of prev_gray, size w * h.
90 * @param w Image width in pixels.
91 * @param h Image height in pixels.
92 * @param prev_points Points to track in normalised [0, 1] coordinates.
93 * @param window_radius Half-size of the tracking patch in pixels.
94 * @param max_iterations Maximum Newton-Raphson iterations per point.
95 * @param eigen_threshold Minimum eigenvalue for structure tensor validity.
96 * @param error_threshold Maximum residual error to accept a track.
97 * @param forward_backward_threshold Maximum return error in pixels; zero disables the check.
98 * @return TrackResult per input point, same order.
99 */
100[[nodiscard]] MAYAFLUX_API std::vector<TrackResult> track_keypoints(
101 std::span<const float> prev_gray,
102 std::span<const float> curr_gray,
103 std::span<const float> grad_dx,
104 std::span<const float> grad_dy,
105 uint32_t w, uint32_t h,
106 std::span<const glm::vec2> prev_points,
107 uint32_t window_radius = 7,
108 uint32_t max_iterations = 20,
109 float eigen_threshold = 1e-4F,
110 float error_threshold = 0.3F,
111 float forward_backward_threshold = 0.0F);
112
113} // namespace MayaFlux::Kinesis::Vision
uint32_t h
Definition InkPress.cpp:29
std::vector< TrackResult > track_keypoints(std::span< const float > prev_gray, std::span< const float > curr_gray, uint32_t w, uint32_t h, std::span< const glm::vec2 > prev_points, uint32_t window_radius, uint32_t max_iterations, float eigen_threshold, float error_threshold, float forward_backward_threshold)
Track keypoints from prev_gray to curr_gray via Lucas-Kanade.
uint32_t age
Frames the track was successfully followed before this one.
glm::vec2 previous
Position of the point in the previous frame, normalised [0, 1].
float error
Residual photometric error after convergence.
bool tracked
False if tracking failed or diverged.
glm::vec2 position
Tracked position in normalised [0, 1] coordinates.
Result for a single tracked point.