feat: CV blob detection and centroid tracking

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>
This commit is contained in:
2026-04-13 14:39:23 -07:00
parent 136b22bc1b
commit b664753596
2 changed files with 115 additions and 1 deletions

View File

@@ -60,11 +60,34 @@ void test_cv_reset_counts() {
TEST_ASSERT_EQUAL_INT(0, state.exits);
}
void test_tracking_spawns_track_for_new_blob() {
CVState state;
cv_init(state);
uint8_t bg[CV_PIXELS];
fill_frame(bg, 100);
cv_process(state, bg, 50); // init background
// Frame with a bright 30x30 blob in top-left quadrant
uint8_t blob_frame[CV_PIXELS];
fill_frame(blob_frame, 100);
for (int y = 5; y < 35; y++)
for (int x = 5; x < 35; x++)
blob_frame[y * CV_W + x] = 200;
cv_process(state, blob_frame, 50);
TEST_ASSERT_EQUAL_INT(1, (int)state.tracks.size());
TEST_ASSERT_FLOAT_WITHIN(5.0f, 20.0f, state.tracks[0].x);
TEST_ASSERT_FLOAT_WITHIN(5.0f, 20.0f, state.tracks[0].y);
}
int main() {
UNITY_BEGIN();
RUN_TEST(test_frame_diff_no_change_gives_no_fg);
RUN_TEST(test_frame_diff_large_change_detected_no_crash);
RUN_TEST(test_cv_init_clears_state);
RUN_TEST(test_cv_reset_counts);
RUN_TEST(test_tracking_spawns_track_for_new_blob);
return UNITY_END();
}