101{
108
110 cur_vec.assign(frame.begin(), frame.end());
111
114
119
122
123 switch (step.op) {
125 uint32_t new_w = 0, new_h = 0;
127 w = new_w;
133 break;
134 }
135
140
141 if (wants_tracking && !peaks_feed_track) {
144 }
145
147 break;
148 }
149
155 break;
156 }
157
163 break;
164 }
165
167 const auto& p = get_params<ThresholdParams>(step.params, step.op);
170 break;
171 }
172
174 const auto& p = get_params<ThresholdAdaptiveParams>(step.params, step.op);
178 break;
179 }
180
185 break;
186 }
187
190 const float mn = m.minCoeff();
191 const float mx = m.maxCoeff();
192 if (mx > mn)
193 m = (m - mn) / (mx - mn);
195 break;
196 }
197
199 const auto& p = get_params<NormalizeRangeParams>(step.params, step.op);
200 if (p.hi > p.lo) {
202 m = ((m - p.lo) / (p.hi - p.lo)).
max(0.0F).min(1.0F);
203 }
205 break;
206 }
207
209 const auto& p = get_params<GaussianBlurParams>(step.params, step.op);
214 break;
215 }
216
218 const auto& p = get_params<FilterSeparableParams>(step.params, step.op);
222 break;
223 }
224
226 GradientResult grad;
229
232 slot_map_mut(nxt, en) = (dx.square() + dy.square()).sqrt();
234
237
241 grad.angle.resize(static_cast<size_t>(en));
242
243 P::transform(P::par_unseq,
246 [](float gx, float gy) { return std::atan2(gy, gx); });
247
250 break;
251 }
252
254 GradientResult grad;
257
260 slot_map_mut(nxt, en) = (dx.square() + dy.square()).sqrt();
261
265
269 grad.angle.resize(static_cast<size_t>(en));
270
271 P::transform(P::par_unseq,
274 [](float gx, float gy) { return std::atan2(gy, gx); });
275
278 break;
279 }
280
282 const auto& p = get_params<CannyParams>(step.params, step.op);
286 break;
287 }
288
290 const auto& p = get_params<MorphParams>(step.params, step.op);
294 break;
295 }
296
298 const auto& p = get_params<MorphParams>(step.params, step.op);
302 break;
303 }
304
306 const auto& p = get_params<MorphParams>(step.params, step.op);
310 break;
311 }
312
314 const auto& p = get_params<MorphParams>(step.params, step.op);
318 break;
319 }
320
322 const auto& p = get_params<MorphParams>(step.params, step.op);
326 break;
327 }
328
337 break;
338 }
339
341 const auto& p = get_params<FindContoursParams>(step.params, step.op);
345 w,
h, p.min_area, p.max_contours);
349 break;
350 }
351
353 const auto& p = get_params<HarrisParams>(step.params, step.op);
363 break;
364 }
365
367 const auto& p = get_params<ExtractPeaksParams>(step.params, step.op);
370
371 if (wants_tracking && !peaks_feed_track)
373
375 if (!peaks_feed_track) {
379 }
380 break;
381 }
382
384 const auto& p = get_params<TrackKeypointsParams>(step.params, step.op);
385
386 auto& prev_vec = std::get<std::vector<float>>(
m_prev_gray);
393 break;
394 }
395
396 std::vector<glm::vec2> prev_pos;
399 prev_pos.push_back(kp.position);
400
404 p.window_radius, p.max_iterations,
405 p.eigen_threshold, p.error_threshold);
406
412 break;
413 }
414
417 break;
419 SnapshotEntry entry;
421 entry.w = w;
425 break;
426 }
427 }
428 }
429
432
435 return out;
436}
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.
std::vector< float > m_curr_gray_cache
static constexpr size_t k_slot_iyy
static constexpr size_t k_slot_syy
static constexpr size_t k_slot_dx
std::vector< float > & slot_vec(size_t i) noexcept
Mutable reference to the vector<float> inside slot i.
static constexpr size_t k_slot_sxy
Kakshya::DataVariant m_prev_gray
CpuVisionPass m_pass
Walk state for the current run: sequence position, geometry, working slot index, and the result under...
static constexpr size_t k_slot_dy
static constexpr size_t k_slot_ixy
static constexpr size_t k_slot_ixx
static constexpr size_t k_slot_tmp
void ensure_slots(uint32_t w, uint32_t h)
Ensure all slots are sized to n_pixels floats.
static constexpr size_t k_slot_cur
const std::vector< float > & gaussian_kernel(float sigma)
Return a reference to the precomputed 1D Gaussian kernel for sigma.
static constexpr size_t k_slot_sxx
static constexpr size_t k_slot_nxt
std::vector< Keypoint > m_prev_keypoints
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.
std::vector< double > max(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Maximum value per window.
void rgba_to_gray(std::span< const float > rgba, std::span< float > dst, uint32_t w, uint32_t h)
Convert RGBA to luminance gray using BT.601 coefficients.
bool track_follows_peaks(const VisionSequence &seq)
True when an ExtractPeaks step is immediately followed by TrackKeypoints.
std::vector< float > filter_separable(std::span< const float > src, uint32_t w, uint32_t h, std::span< const float > kernel_x, std::span< const float > kernel_y)
Apply a separable 2D filter via two 1D passes.
std::vector< float > canny(std::span< const float > gray, uint32_t w, uint32_t h, float sigma, float low_threshold, float high_threshold)
Canny edge detector.
void gray_to_rgba(std::span< const float > gray, std::span< float > dst, uint32_t w, uint32_t h)
Global threshold writing into caller-supplied buffer.
std::vector< Keypoint > extract_peaks(std::span< const float > response, uint32_t w, uint32_t h, float threshold, uint32_t nms_radius)
Extract peaks from a response map via non-maximum suppression.
void erode(std::span< const float > mask, std::span< float > dst, uint32_t w, uint32_t h, uint32_t radius)
Erosion writing into dst.
std::vector< float > harris_response(std::span< const float > gray, uint32_t w, uint32_t h, float k, float sigma)
Compute the Harris corner response map.
ComponentResult connected_components(std::span< const float > mask, uint32_t w, uint32_t h)
Label connected foreground components in a binary mask.
void rgba_to_hsv(std::span< const float > rgba, std::span< float > dst, uint32_t w, uint32_t h)
Convert RGBA to HSV writing into caller-supplied buffer.
std::vector< Contour > find_contours(std::span< const float > mask, uint32_t w, uint32_t h, float min_area, uint32_t max_contours)
Extract outer contours from a binary mask.
void close(std::span< const float > mask, std::span< float > tmp, std::span< float > dst, uint32_t w, uint32_t h, uint32_t radius)
Morphological closing writing into dst.
void sobel(std::span< const float > gray, std::span< float > dx, std::span< float > dy, std::span< float > tmp, uint32_t w, uint32_t h)
Sobel gradient writing dx and dy into caller-supplied buffers.
void dilate(std::span< const float > mask, std::span< float > dst, uint32_t w, uint32_t h, uint32_t radius)
Dilation writing into dst.
bool tracks_keypoints(const VisionSequence &seq)
True when any step tracks keypoints.
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)
Track keypoints from prev_gray to curr_gray via Lucas-Kanade.
void scharr(std::span< const float > gray, std::span< float > dx, std::span< float > dy, std::span< float > tmp, uint32_t w, uint32_t h)
Scharr gradient writing dx and dy into caller-supplied buffers.
void threshold_otsu(std::span< const float > gray, std::span< float > dst)
Otsu threshold writing into caller-supplied buffer.
void threshold_adaptive(std::span< const float > gray, std::span< float > dst, uint32_t w, uint32_t h, uint32_t block_size, float offset)
Adaptive threshold writing into caller-supplied buffer.
void downsample_2x(std::span< const float > src, std::span< float > dst, uint32_t w, uint32_t h, uint32_t &new_w, uint32_t &new_h)
2x box-filter downsample writing into a caller-supplied buffer.
void morph_gradient(std::span< const float > mask, std::span< float > tmp, std::span< float > dst, uint32_t w, uint32_t h, uint32_t radius)
Morphological gradient (dilate - erode) writing into dst.
void open(std::span< const float > mask, std::span< float > tmp, std::span< float > dst, uint32_t w, uint32_t h, uint32_t radius)
Morphological opening writing into dst.
std::shared_ptr< Vruta::Routine > sequence(std::vector< std::pair< double, std::function< void()> > > sequence, Vruta::ProcessingToken token)
Creates a temporal sequence that executes callbacks at specified time offsets.
double peak(const std::vector< double > &data)
Find peak amplitude in single-channel data.
void begin(const VisionSequence &seq, uint32_t width, uint32_t height)
Reset the walk band for a fresh run.
const VisionStep & step() const noexcept
size_t plane_size() const noexcept
void set_geometry(uint32_t width, uint32_t height) noexcept
std::vector< SnapshotEntry > snapshots
Kakshya::DataVariant pixel_image
StructuredOutput structured