MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
VisionExecutor.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "VisionContext.hpp"
4
6
7/**
8 * @file VisionExecutor.hpp
9 * @brief Dispatch engine for VisionSequence execution.
10 *
11 * VisionExecutor::run() is the single entry point for executing a
12 * VisionSequence. It maintains per-frame state (previous gray frame for
13 * optical flow) and returns a VisionResult carrying both the final pixel
14 * image and any structured outputs produced by the terminal step.
15 *
16 * Scratch storage is owned by the executor as DataVariant slots holding
17 * vector<float>. Steps ping-pong between slots via Eigen::Map<ArrayXf>
18 * views, accumulating zero heap allocation in steady state at a fixed
19 * resolution. Gaussian kernels are cached by sigma across frames.
20 *
21 * VisionResult::pixel_image is a DataVariant (vector<float>) moved out of
22 * a scratch slot. Callers read it via EigenAccess::view<Eigen::VectorXf>()
23 * for zero-copy Eigen access, or as_span() for raw float access.
24 */
25
27
28/**
29 * @class VisionExecutor
30 * @brief Stateful executor for a VisionSequence.
31 *
32 * Owns a pool of DataVariant scratch slots (each holding vector<float>) sized
33 * to the working resolution. Steps read via Eigen::Map<const ArrayXf> and
34 * write via Eigen::Map<ArrayXf> into the next slot, then swap indices.
35 * No heap allocation occurs in steady state after the first frame at a given
36 * resolution.
37 *
38 * Gaussian kernels are cached by sigma (keyed on bit-exact float) and reused
39 * across frames and across the three structure tensor smoothing passes in Harris.
40 *
41 * One executor instance per pipeline. Not thread-safe.
42 */
43class MAYAFLUX_API VisionExecutor {
44public:
45 VisionExecutor() = default;
46
47 /**
48 * @brief Execute a VisionSequence on one frame.
49 *
50 * @param sequence Ordered steps to execute.
51 * @param frame Normalised float input. RGBA (4 floats/pixel) for
52 * RgbaToGray/RgbaToHsv; single-channel otherwise.
53 * @param w Frame width in pixels.
54 * @param h Frame height in pixels.
55 * @return VisionResult with pixel_image (DataVariant) and/or structured output.
56 */
57 [[nodiscard]] VisionResult run(
58 const VisionSequence& sequence,
59 std::span<const float> frame,
60 uint32_t w, uint32_t h);
61
62 /**
63 * @brief Clear stored inter-frame state.
64 *
65 * Call when the pixel source changes (camera switch, video seek) so the
66 * next track_keypoints step starts clean. Does not release scratch storage.
67 */
68 void reset();
69
70private:
71 /**
72 * @brief Walk state for the current run: sequence position, geometry,
73 * working slot index, and the result under construction.
74 *
75 * Reset by begin() at the top of each run. Inter-frame state is separate,
76 * below.
77 */
79
80 // =========================================================================
81 // Scratch pool
82 //
83 // Each slot is a DataVariant holding vector<float>. Slots are accessed via
84 // slot_vec(i) for direct vector reference and slot_map(i) / slot_map_mut(i)
85 // for zero-copy Eigen views. The working resolution is tracked to detect
86 // geometry changes and resize all slots in one pass.
87 //
88 // Slot assignment (fixed):
89 // 0 current working buffer (ping)
90 // 1 next working buffer (pong)
91 // 2 filter horizontal pass tmp
92 // 3 harris: dx
93 // 4 harris: dy
94 // 5 harris: ixx
95 // 6 harris: iyy
96 // 7 harris: ixy
97 // 8 harris: sxx (smoothed)
98 // 9 harris: syy
99 // 10 harris: sxy
100 // =========================================================================
101
102 static constexpr size_t k_slot_count = 11;
103 static constexpr size_t k_slot_cur = 0;
104 static constexpr size_t k_slot_nxt = 1;
105 static constexpr size_t k_slot_tmp = 2;
106 static constexpr size_t k_slot_dx = 3;
107 static constexpr size_t k_slot_dy = 4;
108 static constexpr size_t k_slot_ixx = 5;
109 static constexpr size_t k_slot_iyy = 6;
110 static constexpr size_t k_slot_ixy = 7;
111 static constexpr size_t k_slot_sxx = 8;
112 static constexpr size_t k_slot_syy = 9;
113 static constexpr size_t k_slot_sxy = 10;
114
115 std::array<Kakshya::DataVariant, k_slot_count> m_slots;
116 uint32_t m_slot_w { 0 };
117 uint32_t m_slot_h { 0 };
118
119 /**
120 * @brief Ensure all slots are sized to n_pixels floats.
121 *
122 * No-op when geometry matches. Resizes and zero-fills all slots otherwise.
123 */
124 void ensure_slots(uint32_t w, uint32_t h);
125
126 /**
127 * @brief Mutable reference to the vector<float> inside slot i.
128 */
129 [[nodiscard]] std::vector<float>& slot_vec(size_t i) noexcept
130 {
131 return std::get<std::vector<float>>(m_slots[i]);
132 }
133
134 /**
135 * @brief Const reference to the vector<float> inside slot i.
136 */
137 [[nodiscard]] const std::vector<float>& slot_vec(size_t i) const noexcept
138 {
139 return std::get<std::vector<float>>(m_slots[i]);
140 }
141
142 /**
143 * @brief Zero-copy read-only Eigen::Map<const ArrayXf> over slot i.
144 */
145 [[nodiscard]] Eigen::Map<const Eigen::ArrayXf> slot_map(size_t i, Eigen::Index n) const noexcept
146 {
147 return { slot_vec(i).data(), n };
148 }
149
150 /**
151 * @brief Zero-copy mutable Eigen::Map<ArrayXf> over slot i.
152 */
153 [[nodiscard]] Eigen::Map<Eigen::ArrayXf> slot_map_mut(size_t i, Eigen::Index n) noexcept
154 {
155 return { slot_vec(i).data(), n };
156 }
157
158 // =========================================================================
159 // Gaussian kernel cache
160 //
161 // Keyed on the bit pattern of the float sigma value. A given sigma produces
162 // an identical kernel every time; recomputing it three times per Harris call
163 // per frame is pure waste. The 1D separable kernel is stored once and reused
164 // for all three structure tensor smoothing passes and for standalone
165 // GaussianBlur steps.
166 // =========================================================================
167
168 std::unordered_map<uint32_t, std::vector<float>> m_kernel_cache;
169
170 /**
171 * @brief Return a reference to the precomputed 1D Gaussian kernel for sigma.
172 *
173 * Computes and caches on first call for a given sigma. The kernel is
174 * normalised to unit sum and has length 2*ceil(3*sigma)+1.
175 */
176 [[nodiscard]] const std::vector<float>& gaussian_kernel(float sigma);
177
178 // =========================================================================
179 // Inter-frame state
180 // =========================================================================
181
182 Kakshya::DataVariant m_prev_gray { std::vector<float> {} };
183 std::vector<float> m_curr_gray_cache;
184 std::vector<Keypoint> m_prev_keypoints;
185};
186
187} // namespace MayaFlux::Kinesis::Vision
uint32_t h
Definition InkPress.cpp:28
float sigma
std::array< Kakshya::DataVariant, k_slot_count > m_slots
Eigen::Map< Eigen::ArrayXf > slot_map_mut(size_t i, Eigen::Index n) noexcept
Zero-copy mutable Eigen::Map<ArrayXf> over slot i.
const std::vector< float > & slot_vec(size_t i) const noexcept
Const reference to the vector<float> inside slot i.
std::vector< float > & slot_vec(size_t i) noexcept
Mutable reference to the vector<float> inside slot i.
std::unordered_map< uint32_t, std::vector< float > > m_kernel_cache
CpuVisionPass m_pass
Walk state for the current run: sequence position, geometry, working slot index, and the result under...
Eigen::Map< const Eigen::ArrayXf > slot_map(size_t i, Eigen::Index n) const noexcept
Zero-copy read-only Eigen::Map<const ArrayXf> over slot i.
Stateful executor for a VisionSequence.
void run()
Definition main.cpp:22
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
Definition NDData.hpp:102
Result of executing a VisionSequence on one frame.
Ordered sequence of VisionSteps describing a complete vision pipeline.
Definition VisionOp.hpp:169