// firmware/lib/cv/cv.h #pragma once #include #include static const int CV_W = 96; static const int CV_H = 96; static const int CV_PIXELS = CV_W * CV_H; struct CVTrack { int id; float x, y; bool above_line; int missed; }; struct CVTuning { uint8_t diff_thresh; // per-pixel motion threshold int min_blob_px; // min foreground pixels for a blob float max_move; // max inter-frame track jump (px) int max_missed; // frames before drop uint8_t line_offset; // 0-100, percent of frame height for virtual line uint32_t cfg_version; // monotonic; server increments on push }; struct CVState { uint8_t background[CV_PIXELS]; bool bg_valid; uint32_t last_motion_frame; uint32_t frame_index; int next_id; std::vector tracks; int entries; int exits; CVTuning tuning; }; struct CVResult { int entries_delta; int exits_delta; }; void cv_init(CVState& state); CVResult cv_process(CVState& state, const uint8_t* frame); void cv_reset_counts(CVState& state); // Pure validator: returns true iff all tunable fields are in range and // cfg_version is non-zero. No Arduino deps — safe for native tests. bool cv_tuning_validate(const CVTuning& t);