Adds CVTuning to CVState, populates defaults from existing file-scope
constants in cv_init, and introduces config_load_tuning/config_save_tuning
backed by the doorcounter NVS namespace. No runtime behavior change yet;
CV code still reads the existing constants (Task 2 will migrate reads).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
loopTask: cv_init() created a CVState{} temporary (9KB background
array) on the stack — fixed by initializing members directly.
cam task: cv_process() had uint8_t fg[CV_PIXELS] (9KB) as a local
variable — made static, matching the existing fg_copy fix.
cam task stack bumped from 4096 to 8192 for headroom.
Also: switch to 4MB OTA partition table (TimerCamera-F has 4MB flash,
not 8MB), add CONFIG_ARDUINO_LOOP_STACK_SIZE=16384 build flag,
upload_speed=115200 and --no-stub for reliable CH340 flashing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add BFS flood-fill blob extraction, centroid finding, and nearest-neighbour track matching/spawning inside cv_process. Add test verifying a new blob spawns a track.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>