MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
VisionContext.hpp
Go to the documentation of this file.
1#pragma once
2
4#include "Features.hpp"
5#include "Gradient.hpp"
6#include "OpticalFlow.hpp"
7#include "VisionOp.hpp"
8
10
11namespace MayaFlux::Core {
12class VKImage;
13}
14
16
17using StructuredOutput = std::variant<
18 std::monostate,
21 std::vector<Contour>,
22 std::vector<Keypoint>,
23 std::vector<TrackResult>>;
24
25/**
26 * @brief Whether a run carried the sequence to its end.
27 *
28 * SUSPENDED means a deferred step has work outstanding. The result carries
29 * nothing and must not be consumed. Call run again with the same arguments
30 * to poll; the executor resumes where it left off and ignores the image
31 * argument until the sequence completes.
32 */
33enum class VisionStatus : uint8_t {
36};
37
38/**
39 * @brief Result of executing a VisionSequence on one frame.
40 *
41 * pixel_image holds the final normalised float pixel buffer as a DataVariant
42 * (active alternative: vector<float>). Empty when the terminal step produces
43 * only structured output.
44 *
45 * Callers access pixel data via:
46 * EigenAccess(result.pixel_image).view<Eigen::VectorXf>() -- zero-copy Eigen map
47 * std::get<std::vector<float>>(result.pixel_image) -- direct vector access
48 *
49 * w and h are the dimensions of pixel_image. Both are 0 when pixel_image is empty.
50 */
52 Kakshya::DataVariant pixel_image { std::vector<float> {} };
53 StructuredOutput structured { std::monostate {} };
54 std::vector<SnapshotEntry> snapshots;
55 std::shared_ptr<Core::VKImage> debug_labels;
56 std::shared_ptr<Core::VKImage> debug_contours;
57 uint32_t w { 0 };
58 uint32_t h { 0 };
60 size_t suspended_at { 0 };
61
62 /**
63 * @brief True when the sequence reached its end and this result may be
64 * consumed, cached, or broadcast.
65 */
66 [[nodiscard]] bool is_ready() const noexcept
67 {
69 }
70
71 /**
72 * @brief Zero-copy float span into pixel_image storage.
73 * @return Empty span if pixel_image is not vector<float> or is empty.
74 */
75 [[nodiscard]] std::span<const float> as_span() const noexcept
76 {
77 const auto* v = std::get_if<std::vector<float>>(&pixel_image);
78 if (!v || v->empty())
79 return {};
80 return { v->data(), v->size() };
81 }
82};
83
84/**
85 * @brief State threaded through one execution of a VisionSequence.
86 *
87 * Shared by the CPU and GPU executors so op functions have one signature on
88 * both paths. Three bands: the walk, working storage, and redundancy caches.
89 *
90 * Cross-run retained state is not here. It is owned vectors on the CPU path
91 * and owned images on the GPU path, neither of which is a working storage
92 * handle, so each executor holds its own in its own types.
93 *
94 * @tparam Handle Working storage handle. Slot index on the CPU path,
95 * shared_ptr<VKImage> on the GPU path.
96 *
97 * sequence is non-owning and valid only for the run that constructed the
98 * pass. Storage and caches outlive a single run once the pass is held by
99 * the executor; the walk band is reset per run by begin().
100 */
101template <typename Handle>
103 // -------------------------------------------------------------------------
104 // Walk
105 // -------------------------------------------------------------------------
106
107 const VisionSequence* sequence { nullptr };
108 size_t index { 0 };
109 uint32_t w { 0 };
110 uint32_t h { 0 };
111 uint32_t channels { 4 };
113
114 // -------------------------------------------------------------------------
115 // Working storage
116 // -------------------------------------------------------------------------
117
118 Handle current {};
119 uint32_t storage_w { 0 };
120 uint32_t storage_h { 0 };
121
122 // -------------------------------------------------------------------------
123 // Retained across runs
124 // -------------------------------------------------------------------------
125
126 Handle prev {};
127 Handle prev_cache {};
128 std::vector<Keypoint> prev_keypoints;
129
130 // -------------------------------------------------------------------------
131 // Redundancy caches
132 // -------------------------------------------------------------------------
133
134 struct Completed {
135 Handle output {};
136 Handle input {};
137 };
138
139 std::unordered_map<size_t, Completed> completed;
140
141 /**
142 * @brief Reset the walk band for a fresh run.
143 *
144 * Clears the memo unconditionally: its keys compare image handles, which
145 * proxy for content only within one walk. Across runs the caller's input
146 * and the contexts' output images are reused in place, so an equal handle
147 * does not mean equal pixels.
148 *
149 * Retained cross-run state is dropped only when the geometry changes,
150 * since surviving between runs is what it is for.
151 */
152 void begin(const VisionSequence& seq, uint32_t width, uint32_t height)
153 {
154 completed.clear();
155
156 if (width != w || height != h)
157 forget();
158
159 sequence = &seq;
160 index = 0;
161 channels = 4;
162 result = VisionResult {};
164 }
165
166 /**
167 * @brief Discard retained cross-run state. Storage and caches are kept.
168 */
169 void forget()
170 {
171 prev = Handle {};
172 prev_cache = Handle {};
173 prev_keypoints.clear();
174 }
175
176 [[nodiscard]] const VisionStep& step() const noexcept
177 {
178 return sequence->steps[index];
179 }
180
181 [[nodiscard]] size_t plane_size() const noexcept
182 {
183 return static_cast<size_t>(w) * h;
184 }
185
186 /**
187 * @brief Op at @p offset steps ahead, or nullptr past the end.
188 *
189 * Replaces the adjacency booleans derived by VisionSequence::Builder.
190 * Correct under any mutation of steps because it is evaluated at the
191 * point of use.
192 */
193 [[nodiscard]] const VisionStep* ahead(size_t offset = 1) const noexcept
194 {
195 const auto& steps = sequence->steps;
196 const size_t at = index + offset;
197 return at < steps.size() ? &steps[at] : nullptr;
198 }
199
200 /**
201 * @brief Op at @p offset steps back, or nullptr before the start.
202 *
203 * Counterpart to ahead(), for ops validating what produced their input.
204 */
205 [[nodiscard]] const VisionStep* behind(size_t offset = 1) const noexcept
206 {
207 if (offset > index)
208 return nullptr;
209 return &sequence->steps[index - offset];
210 }
211
212 void set_geometry(uint32_t width, uint32_t height) noexcept
213 {
214 w = width;
215 h = height;
216 result.w = width;
217 result.h = height;
218 }
219
220 /**
221 * @brief Memoised output for @p key when it was produced from @p input.
222 */
223 [[nodiscard]] const Handle* memo(size_t key, const Handle& input) const
224 {
225 auto it = completed.find(key);
226 if (it == completed.end() || !(it->second.input == input))
227 return nullptr;
228 return &it->second.output;
229 }
230};
231
234
235} // namespace MayaFlux::Kinesis::Vision
Core::GlobalInputConfig input
Definition Config.cpp:38
Connected component labelling on normalised float masks.
Gradient and edge detection on normalised float image spans.
Sparse optical flow via Lucas-Kanade tracker.
float offset
Declarative description of a Kinesis::Vision processing sequence.
uint32_t width
uint32_t height
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
std::variant< std::monostate, GradientResult, ComponentResult, std::vector< Contour >, std::vector< Keypoint >, std::vector< TrackResult > > StructuredOutput
VisionStatus
Whether a run carried the sequence to its end.
Result of connected component labelling.
Gradient maps produced by Sobel and Scharr operators.
Definition Gradient.hpp:22
void begin(const VisionSequence &seq, uint32_t width, uint32_t height)
Reset the walk band for a fresh run.
const VisionStep & step() const noexcept
const VisionStep * behind(size_t offset=1) const noexcept
Op at offset steps back, or nullptr before the start.
const VisionStep * ahead(size_t offset=1) const noexcept
Op at offset steps ahead, or nullptr past the end.
const Handle * memo(size_t key, const Handle &input) const
Memoised output for key when it was produced from input.
std::unordered_map< size_t, Completed > completed
void set_geometry(uint32_t width, uint32_t height) noexcept
void forget()
Discard retained cross-run state.
State threaded through one execution of a VisionSequence.
std::shared_ptr< Core::VKImage > debug_labels
std::vector< SnapshotEntry > snapshots
bool is_ready() const noexcept
True when the sequence reached its end and this result may be consumed, cached, or broadcast.
std::shared_ptr< Core::VKImage > debug_contours
std::span< const float > as_span() const noexcept
Zero-copy float span into pixel_image storage.
Result of executing a VisionSequence on one frame.
Ordered sequence of VisionSteps describing a complete vision pipeline.
Definition VisionOp.hpp:169
One step in a VisionSequence: an op and its parameters.
Definition VisionOp.hpp:158