MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
VisionMatrix.cpp
Go to the documentation of this file.
1#include "VisionMatrix.hpp"
2
4
5namespace {
6
8
9 template <typename Params>
10 void complete(std::optional<Params>& params, VisionIntent intents, VisionIntent intent)
11 {
12 if (Kinesis::Vision::has_flag(intents, intent) && !params)
13 params.emplace();
14 }
15
16 /**
17 * @brief @p query with default parameters for every intent it sets but
18 * does not configure, which resolve() would otherwise skip.
19 */
20 Kinesis::Vision::VisionQuery completed(Kinesis::Vision::VisionQuery query)
21 {
22 const auto intents = query.intents;
23 complete(query.find_elements, intents, VisionIntent::FindElements);
24 complete(query.track_objects, intents, VisionIntent::TrackObjects);
25 complete(query.detect_features, intents, VisionIntent::DetectFeatures);
26 complete(query.detect_edges, intents, VisionIntent::DetectEdges);
27 complete(query.estimate_motion, intents, VisionIntent::EstimateMotion);
28 complete(query.measure_appearance, intents, VisionIntent::MeasureAppearance);
29 return query;
30 }
31
32} // namespace
33
34std::shared_ptr<VisionMatrix> VisionMatrix::create(
36 std::optional<VisionExtractMode> extract,
38{
39 return std::make_shared<VisionMatrix>(query, extract, context);
40}
41
44 std::optional<VisionExtractMode> extract,
46{
47 create_operation<VisionAnalyzer>("analyze", completed(query), context);
48 if (extract)
49 create_operation<VisionExtractor>("extract", *extract);
50}
51
53{
54 const auto now = std::chrono::steady_clock::now();
55 if (m_last_call) {
56 const double seconds = std::chrono::duration<double>(now - *m_last_call).count();
57 if (seconds > 0.0) {
58 const double rate = 1.0 / seconds;
59 m_rate = m_rate > 0.0 ? m_rate + 0.1 * (rate - m_rate) : rate;
60 }
61 }
62 m_last_call = now;
63}
64
65void VisionMatrix::execute(const std::shared_ptr<Core::VKImage>& image)
66{
67 if (image)
68 count_call();
69 m_frame = image;
70 m_extraction.reset();
72}
73
74void VisionMatrix::execute(const std::shared_ptr<Kakshya::SignalSourceContainer>& source, size_t index)
75{
76 execute(source ? analyzer()->resolve_image(source, index) : nullptr);
77}
78
79void VisionMatrix::extract(const Kinesis::Vision::VisionAnalysis& analysis, const std::shared_ptr<Core::VKImage>& image)
80{
81 count_call();
83 m_frame = image;
84 m_extraction.reset();
85
86 if (!image || !extractor())
87 return;
88
90 input.metadata["vision_analysis"] = analysis;
91 input.metadata["vision_image"] = image;
92
93 const auto output = with(std::move(input)).then<VisionExtractor>("extract").to_io();
94 if (const auto extracted = Kakshya::get_metadata_value<std::shared_ptr<Core::VKImage>>(output.metadata, "vision_extraction"))
95 m_extraction = *extracted;
96}
97
98std::shared_ptr<const Kinesis::Vision::VisionResult> VisionMatrix::result(VisionIntent intent)
99{
101
102 const auto analyzer_op = analyzer();
103 const auto results = analyzer_op->get_shared_results();
104 const auto resolved = Kinesis::Vision::resolve(analyzer_op->get_query());
105 const size_t lanes = std::min(results->size(), resolved.size());
106
107 for (size_t lane = 0; lane < lanes; ++lane) {
108 const auto& steps = resolved[lane].sequence.steps;
109 const auto has = [&steps](VisionOp op) {
110 return std::ranges::any_of(steps, [op](const auto& step) { return step.op == op; });
111 };
112
113 bool serves = false;
114 switch (intent) {
115 case VisionIntent::FindElements:
116 serves = has(VisionOp::ConnectedComponents);
117 break;
118 case VisionIntent::TrackObjects:
119 serves = has(VisionOp::TrackKeypoints);
120 break;
121 case VisionIntent::DetectFeatures:
122 serves = has(VisionOp::HarrisResponse) && !has(VisionOp::TrackKeypoints);
123 break;
124 case VisionIntent::DetectEdges:
125 serves = has(VisionOp::Canny);
126 break;
127 case VisionIntent::EstimateMotion:
128 serves = has(VisionOp::OpticalFlowDense);
129 break;
130 case VisionIntent::MeasureAppearance:
131 serves = has(VisionOp::Sobel);
132 break;
133 default:
134 break;
135 }
136
137 if (serves)
138 return { results, &(*results)[lane] };
139 }
140
141 return nullptr;
142}
143
144Kinesis::Vision::VisionAnalysis VisionMatrix::analyze(const std::shared_ptr<Core::VKImage>& image)
145{
146 return analyzer()->analyze_vision(image);
147}
148
150 const std::shared_ptr<Kakshya::SignalSourceContainer>& source, size_t index)
151{
152 return analyzer()->analyze_vision(source, index);
153}
154
155} // namespace MayaFlux::Yantra::Vision
Core::GlobalInputConfig input
Definition Config.cpp:42
IO::ImageData image
Definition Decoder.cpp:47
float rate
uint32_t index
Definition VKDevice.cpp:122
FluentExecutor< ComputeMatrix, StartType > with(const Datum< StartType > &input)
Create a fluent executor for chaining operations.
static std::shared_ptr< ComputeMatrix > create()
Create a new ComputeMatrix instance.
Extraction from each VisionAnalysis field.
std::shared_ptr< VisionExtractor > extractor()
The matrix's "extract" operation, or null when the matrix was built without a mode.
const std::vector< Kinesis::Vision::VisionResult > & results()
The VisionResult of every sequence the analyzer's last completed analysis ran, with each step's image...
void execute(const std::shared_ptr< Core::VKImage > &image)
Analyze image and keep it with its analysis until the next call.
std::optional< std::chrono::steady_clock::time_point > m_last_call
VisionMatrix(Kinesis::Vision::VisionQuery query, std::optional< VisionExtractMode > extract={}, Kinesis::Vision::VisionAnalysisContext context={})
Kinesis::Vision::VisionAnalysis analyze(const std::shared_ptr< Core::VKImage > &image)
Analyze image with the matrix's query.
Kinesis::Vision::VisionAnalysis m_analysis
std::shared_ptr< Core::VKImage > m_extraction
std::shared_ptr< const Kinesis::Vision::VisionResult > result(Kinesis::Vision::VisionIntent intent)
The VisionResult of the sequence that served intent in the last completed analysis,...
void extract(const Kinesis::Vision::VisionAnalysis &analysis, const std::shared_ptr< Core::VKImage > &image)
Extract from image with analysis and keep all three until the next call.
std::shared_ptr< VisionAnalyzer > analyzer()
The matrix's "analyze" operation.
std::shared_ptr< Core::VKImage > m_frame
const Kinesis::Vision::VisionAnalysis & analysis() const
The analysis of the last execute() or extract(), empty before the first.
std::optional< T > get_metadata_value(const std::unordered_map< std::string, std::any > &metadata, const std::string &key)
Get a value from a metadata map by key.
VisionIntent
Composable flags naming what a vision analysis should produce.
VisionOp
Named operations available in a VisionSequence.
Definition VisionOp.hpp:30
std::vector< ResolvedSequence > resolve(const VisionQuery &query)
Resolve a VisionQuery into the ResolvedSequences needed to satisfy every active intent.
Composed context: caller-supplied data for whichever intents need it, consulted after a VisionQuery's...
Composed analysis output: one populated field per active intent that produced a result this call.
Composed query: which VisionIntents are active, and each active one's parameters.
std::unordered_map< std::string, std::any > metadata
Associated metadata.
Definition DataIO.hpp:30
Input/Output container for computation pipeline data flow with structure preservation.
Definition DataIO.hpp:26