MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
VisionInsight.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "VisionContext.hpp"
4
5/**
6 * @file VisionInsight.hpp
7 * @brief Caller-supplied context and GPU-derived output for turning a raw
8 * VisionResult into something a caller actually wants: analysis
9 * today (VisionAnalysisContext/VisionAnalysis and their per-intent
10 * pieces), extraction context to follow. Split out of
11 * VisionContext.hpp, which stays scoped to running a VisionSequence
12 * itself, not to interpreting what came out of it.
13 */
14
16
17/**
18 * @brief Caller-supplied context for VisionIntent::TrackObjects.
19 *
20 * subject_bounds narrows which tracked points count as the subject when
21 * more than one candidate is present in the raw TrackResult list, for the
22 * frame that first identifies a subject. subject_track_id continues an
23 * already-identified subject on later frames by its stable TrackResult::id
24 * instead of re-filtering by region every call, which is the case
25 * DetectFeaturesContext has no equivalent for: Keypoint carries no
26 * persistent identity at all, only TrackResult does. Not derived either
27 * way: the caller decides what the subject is, from whatever source (a
28 * previous frame's result, a UI selection, another sensor).
29 */
31 std::optional<BoundingBox> subject_bounds;
32 std::optional<uint32_t> subject_track_id;
33};
34
35/**
36 * @brief Composed context: caller-supplied data for whichever intents need
37 * it, consulted after a VisionQuery's resolved sequences have run.
38 *
39 * detect_features_bounds stands alone rather than in its own named
40 * struct like TrackObjectsContext: Keypoint has no persistent identity to
41 * grow a second field around the way TrackResult does, so a bare bounds
42 * value is the whole story.
43 *
44 * FindElements/DetectEdges/EstimateMotion/MeasureAppearance have no field
45 * here: FindElements's contours are already complete with nothing left for
46 * the caller to supply, and the other three have no concrete
47 * caller-suppliable need identified yet.
48 */
50 std::optional<TrackObjectsContext> track_objects;
51 std::optional<BoundingBox> detect_features_bounds;
52};
53
54/**
55 * @brief Track reduction, computed on GPU (Yantra's track_reduce.comp) from
56 * the (context-filtered) subject tracks: sum reduced to mean for
57 * centroid/velocity, min/max reduced to bounds. Not a CPU loop over
58 * the downloaded track list.
59 */
61 std::vector<TrackResult> tracks;
62 glm::vec2 centroid {};
63 glm::vec2 velocity {};
65
66 float mean_speed_px { 0.0F };
67 float mean_age { 0.0F };
68 uint32_t max_age { 0 };
69 uint32_t tracked_count { 0 };
70 uint32_t lost_count { 0 };
71};
72
73/**
74 * @brief Keypoint reduction, computed on GPU by the same reduction shader
75 * as TrackObjectsAnalysis (track_reduce.comp, fed previous = position
76 * so the velocity output is always zero and simply not surfaced
77 * here): centroid and bounds over every detected keypoint. Not a CPU
78 * min/max loop over the downloaded keypoint list.
79 */
81 std::vector<Keypoint> keypoints;
82 glm::vec2 centroid {};
84 float mean_response { 0.0F };
85};
86
87/**
88 * @brief Per-element shape descriptors, parallel to FindElementsAnalysis::boxes
89 * (shapes[i] describes boxes[i]).
90 *
91 * compactness is 4*pi*area/perimeter^2 in pixel units (1.0 for a perfect
92 * circle, lower for elongated or irregular shapes). aspect_ratio is the
93 * element's own bounding box width/height in pixel units.
94 */
96 float compactness { 0.0F };
97 float aspect_ratio { 0.0F };
98};
99
100/**
101 * @brief FindElements output: contours plus the per-component BoundingBoxes
102 * ConnectedComponents already computes on GPU as a matter of course.
103 *
104 * boxes is indexed by label 1..count (boxes[i] has label_id == i + 1),
105 * independent of contours' order (contours may be reordered by
106 * contour_topk_select.comp's area sort, or filtered by min_area). Join a
107 * contour to its own box via contour.label_id: boxes[contour.label_id - 1].
108 * A hole contour's label_id is 0 and has no corresponding box; a hole is
109 * not itself a component.
110 *
111 * shapes and nearest_neighbor_distance_px are both parallel to boxes (one
112 * entry per real component, holes excluded): shapes[i] is boxes[i]'s own
113 * compactness/aspect ratio, nearest_neighbor_distance_px[i] is the pixel
114 * distance from boxes[i]'s centroid to the closest other box's centroid
115 * (0 when boxes has fewer than two elements).
116 */
118 std::vector<Contour> contours;
119 std::vector<BoundingBox> boxes;
120 std::vector<ElementShape> shapes;
122};
123
124/**
125 * @brief Per-channel mean/min/max over a sampled image region, computed on
126 * GPU (Yantra's region_sample.comp) rather than downloaded and
127 * reduced on the caller's side.
128 *
129 * The channel semantics depend entirely on what image was sampled: rgb for
130 * a colour frame, r/g = flow vector with b = confidence and a = residual
131 * for VisionAnalysis::estimate_motion, and so on. VisionExtractor does not
132 * interpret the channels, only reduces them.
133 */
135 glm::vec4 mean {};
136 glm::vec4 min_val {};
137 glm::vec4 max_val {};
138};
139
140/**
141 * @brief MeasureAppearance output: whole-frame photometric characterisation,
142 * computed on GPU (region_sample.comp over VisionResult::images.sobel,
143 * and a 256-bin brightness histogram over VisionResult::gray).
144 *
145 * mean_brightness is the histogram's own weighted mean, in [0, 1].
146 */
149 std::array<uint32_t, 256> histogram {};
150 float mean_brightness { 0.0F };
151};
152
153/**
154 * @brief Composed analysis output: one populated field per active intent
155 * that produced a result this call.
156 *
157 * find_elements/detect_features are GPU-produced/GPU-reduced result types:
158 * see FindElementsAnalysis and DetectFeaturesAnalysis respectively.
159 * detect_edges/estimate_motion are exactly VisionResult::images.canny/flow.
160 *
161 * find_elements.contours arrives already sorted by area, largest first,
162 * when the caller set FindContoursParams::max_contours > 0 on the query:
163 * that cap is driven by contour_topk_select.comp, a real GPU top-K-by-area
164 * reduction already in the FindContours pipeline, so "the largest
165 * contour" is find_elements->contours.front() for a caller who asked for
166 * one, with no separate derived field needed.
167 *
168 * track_objects/detect_features carry GPU-computed centroid/bounds (see
169 * their own struct docs) rather than a bare vector: both are real reduction
170 * shader dispatches, not CPU loops.
171 *
172 * detect_edges/estimate_motion have no derived field of their own beyond
173 * motion_activity: VisionExtractor::sample() answers "what is it like here"
174 * for a region a caller supplies, on demand.
175 */
177 std::optional<FindElementsAnalysis> find_elements;
178 std::optional<TrackObjectsAnalysis> track_objects;
179 std::optional<DetectFeaturesAnalysis> detect_features;
180 std::optional<MeasureAppearanceAnalysis> measure_appearance;
181 std::shared_ptr<Core::VKImage> detect_edges;
182 std::shared_ptr<Core::VKImage> estimate_motion;
183
184 /** @brief VisionResult::motion_energy from an active EstimateMotion sequence. */
185 std::optional<float> motion_activity;
186};
187
188} // namespace MayaFlux::Kinesis::Vision
Axis-aligned bounding box in normalised image coordinates.
Definition Features.hpp:19
Keypoint reduction, computed on GPU by the same reduction shader as TrackObjectsAnalysis (track_reduc...
Per-element shape descriptors, parallel to FindElementsAnalysis::boxes (shapes[i] describes boxes[i])...
Per-channel mean/min/max over a sampled image region, computed on GPU (Yantra's region_sample....
FindElements output: contours plus the per-component BoundingBoxes ConnectedComponents already comput...
MeasureAppearance output: whole-frame photometric characterisation, computed on GPU (region_sample....
Track reduction, computed on GPU (Yantra's track_reduce.comp) from the (context-filtered) subject tra...
Caller-supplied context for VisionIntent::TrackObjects.
std::optional< TrackObjectsContext > track_objects
std::optional< BoundingBox > detect_features_bounds
Composed context: caller-supplied data for whichever intents need it, consulted after a VisionQuery's...
std::optional< FindElementsAnalysis > find_elements
std::optional< MeasureAppearanceAnalysis > measure_appearance
std::optional< DetectFeaturesAnalysis > detect_features
std::shared_ptr< Core::VKImage > estimate_motion
std::optional< TrackObjectsAnalysis > track_objects
std::shared_ptr< Core::VKImage > detect_edges
std::optional< float > motion_activity
VisionResult::motion_energy from an active EstimateMotion sequence.
Composed analysis output: one populated field per active intent that produced a result this call.