Skip to content

Commit 371e15d

Browse files
committed
v2.0.5: Streamlined inference API and full config-driven detection
Major improvements: - Streamlined inference: species_list now auto-loaded from checkpoint - Full JPEG support in prepare function (.jpeg files) - All detection parameters moved to detection_config.yaml (24 total) - Standardized frame-based tracking (max_lost_frames vs lost_track_seconds) Changed: - inference() API: hierarchical_model_path is first param, species_list optional - Tracker uses max_lost_frames (45) instead of lost_track_seconds (1.5s) - All hardcoded detection values now configurable via YAML Added: - GMM parameters: gmm_history, gmm_var_threshold - Morphological: morph_kernel_size - Cohesiveness: min_motion_ratio - Track consistency: max_area_change_ratio - Path topology: revisit_radius Fixed: - Indentation error in prepare.py corruption detection Files changed: CHANGELOG.md, README.md, detection_config.yaml, notebooks/full_pipeline.ipynb, pyproject.toml, detector.py, inference.py, prepare.py, tracker.py
1 parent a9ce371 commit 371e15d

File tree

9 files changed

+806
-532
lines changed

9 files changed

+806
-532
lines changed

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [2.0.5] - 2025-02-04
8+
9+
### Added
10+
- **JPEG support**: `prepare()` now fully supports `.jpeg` files in addition to `.jpg` and `.png`
11+
- **Full detection configuration**: All 24 detection parameters now exposed in `detection_config.yaml` with comprehensive documentation
12+
13+
### Changed
14+
- **Streamlined inference API**: `species_list` is now optional and automatically loaded from model checkpoint (still can be overridden if needed)
15+
- **Frame-based tracking**: Standardized on `max_lost_frames` (frame-based) instead of `lost_track_seconds` for consistent behavior across different FPS
16+
- **Refactored detection modules**: Moved all hardcoded values to `detection_config.yaml` for better configurability
17+
- GMM parameters (`gmm_history`, `gmm_var_threshold`)
18+
- Morphological filtering (`morph_kernel_size`)
19+
- Cohesiveness filters (`min_motion_ratio`)
20+
- Track consistency (`max_area_change_ratio`)
21+
- Path topology (`revisit_radius`)
22+
23+
### Fixed
24+
- **Indentation error** in `prepare.py` file corruption detection loop
25+
726
## [2.0.4] - 2025-02-02
827

928
### Added

README.md

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ results = bplusplus.validate(
134134
#### Step 5: Run Inference on Video
135135
Process a video file to detect, classify, and track insects using motion-based detection. The pipeline uses background subtraction (GMM) to detect moving insects, tracks them across frames, and classifies confirmed tracks.
136136
137+
**Note:** The species list and taxonomy are automatically loaded from the model checkpoint, so you don't need to provide them again.
138+
137139
**Output files generated in `output_dir`:**
138140
- `{video}_annotated.mp4` - Video showing confirmed tracks with classifications
139141
- `{video}_debug.mp4` - Debug video with motion mask and all detections
@@ -146,10 +148,10 @@ OUTPUT_DIR = Path("./output")
146148
HIERARCHICAL_MODEL_PATH = TRAINED_MODEL_DIR / "best_multitask.pt"
147149
148150
results = bplusplus.inference(
149-
species_list=names,
150151
hierarchical_model_path=HIERARCHICAL_MODEL_PATH,
151152
video_path=VIDEO_INPUT_PATH,
152153
output_dir=OUTPUT_DIR,
154+
# species_list=names, # Optional: override species from checkpoint
153155
fps=None, # None = process all frames
154156
backbone="resnet50", # Must match training
155157
save_video=True, # Set to False to skip video rendering (only CSV output)
@@ -172,7 +174,44 @@ results = bplusplus.inference(
172174
)
173175
```
174176

175-
Download a template config from the [releases page](https://github.com/Tvenver/Bplusplus/releases). Parameters control cohesiveness filtering, shape filtering, tracking behavior, and path topology analysis for confirming insect-like movement.
177+
Download a template config from the [releases page](https://github.com/Tvenver/Bplusplus/releases).
178+
179+
<details>
180+
<summary><b>Full Configuration Parameters</b> (click to expand)</summary>
181+
182+
| Parameter | Default | Description |
183+
|-----------|---------|-------------|
184+
| **GMM Background Subtractor** | | *Motion detection model* |
185+
| `gmm_history` | 500 | Frames to build background model |
186+
| `gmm_var_threshold` | 16 | Variance threshold for foreground detection |
187+
| **Morphological Filtering** | | *Noise removal* |
188+
| `morph_kernel_size` | 3 | Morphological kernel size (NxN) |
189+
| **Cohesiveness** | | *Filters scattered motion (plants) vs compact motion (insects)* |
190+
| `min_largest_blob_ratio` | 0.80 | Min ratio of largest blob to total motion |
191+
| `max_num_blobs` | 5 | Max separate blobs allowed in detection |
192+
| `min_motion_ratio` | 0.15 | Min ratio of motion pixels to bbox area |
193+
| **Shape** | | *Filters by contour properties* |
194+
| `min_area` | 200 | Min detection area (px²) |
195+
| `max_area` | 40000 | Max detection area (px²) |
196+
| `min_density` | 3.0 | Min area/perimeter ratio |
197+
| `min_solidity` | 0.55 | Min convex hull fill ratio |
198+
| **Tracking** | | *Controls track behavior* |
199+
| `min_displacement` | 50 | Min net movement for confirmation (px) |
200+
| `min_path_points` | 10 | Min points before path analysis |
201+
| `max_frame_jump` | 100 | Max jump between frames (px) |
202+
| `max_lost_frames` | 45 | Frames before lost track deleted (e.g., 45 @ 30fps = 1.5s) |
203+
| `max_area_change_ratio` | 3.0 | Max area change ratio between frames |
204+
| **Tracker Matching** | | *Hungarian algorithm cost function* |
205+
| `tracker_w_dist` | 0.6 | Weight for distance cost (0-1) |
206+
| `tracker_w_area` | 0.4 | Weight for area cost (0-1) |
207+
| `tracker_cost_threshold` | 0.3 | Max cost for valid match (0-1) |
208+
| **Path Topology** | | *Confirms insect-like movement patterns* |
209+
| `max_revisit_ratio` | 0.30 | Max ratio of revisited positions |
210+
| `min_progression_ratio` | 0.70 | Min forward progression |
211+
| `max_directional_variance` | 0.90 | Max heading variance |
212+
| `revisit_radius` | 50 | Radius (px) for revisit detection |
213+
214+
</details>
176215

177216
### Customization
178217

detection_config.yaml

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,28 @@
88
# results = inference(..., config="detection_config.yaml")
99
# =============================================================================
1010

11+
# -----------------------------------------------------------------------------
12+
# GMM BACKGROUND SUBTRACTOR PARAMETERS
13+
# -----------------------------------------------------------------------------
14+
# Controls the Gaussian Mixture Model for motion detection
15+
16+
# Number of frames to build background model
17+
# Higher = more stable background, slower adaptation to lighting changes
18+
gmm_history: 500
19+
20+
# Variance threshold for foreground detection
21+
# Higher = less sensitive, fewer false positives from noise
22+
gmm_var_threshold: 16
23+
24+
# -----------------------------------------------------------------------------
25+
# MORPHOLOGICAL FILTERING
26+
# -----------------------------------------------------------------------------
27+
# Noise removal after motion detection
28+
29+
# Size of the morphological kernel (NxN ellipse)
30+
# Larger = removes more noise but may lose small detections
31+
morph_kernel_size: 3
32+
1133
# -----------------------------------------------------------------------------
1234
# COHESIVENESS PARAMETERS
1335
# -----------------------------------------------------------------------------
@@ -21,6 +43,10 @@ min_largest_blob_ratio: 0.80
2143
# Lower = stricter, rejects scattered motion
2244
max_num_blobs: 5
2345

46+
# Min ratio of motion pixels to bounding box area
47+
# Higher = requires more filled bounding box
48+
min_motion_ratio: 0.15
49+
2450
# -----------------------------------------------------------------------------
2551
# SHAPE PARAMETERS
2652
# -----------------------------------------------------------------------------
@@ -55,9 +81,30 @@ min_path_points: 10
5581
# Larger = more tolerant of fast movement, but may link separate objects
5682
max_frame_jump: 100
5783

58-
# How long to remember a lost track (seconds)
59-
# Helps re-link tracks after brief occlusions
60-
lost_track_seconds: 1.5
84+
# How many frames to remember a lost track before deleting
85+
# Helps re-link tracks after brief occlusions (e.g., 45 frames @ 30fps = 1.5s)
86+
max_lost_frames: 45
87+
88+
# Max allowed area change ratio between frames
89+
# Prevents linking very different sized detections
90+
max_area_change_ratio: 3.0
91+
92+
# -----------------------------------------------------------------------------
93+
# TRACKER MATCHING PARAMETERS
94+
# -----------------------------------------------------------------------------
95+
# Hungarian algorithm cost function weights
96+
97+
# Weight for distance cost (0-1)
98+
# Higher = position matters more for matching
99+
tracker_w_dist: 0.6
100+
101+
# Weight for area cost (0-1)
102+
# Higher = size similarity matters more for matching
103+
tracker_w_area: 0.4
104+
105+
# Maximum cost for valid track-detection match (0-1)
106+
# Lower = stricter matching, more new tracks created
107+
tracker_cost_threshold: 0.3
61108

62109
# -----------------------------------------------------------------------------
63110
# PATH TOPOLOGY PARAMETERS
@@ -74,4 +121,8 @@ min_progression_ratio: 0.70
74121

75122
# Max directional variance (insects maintain relatively consistent heading)
76123
# Lower = stricter, requires more consistent direction
77-
max_directional_variance: 0.90
124+
max_directional_variance: 0.90
125+
126+
# Radius in pixels for determining if a position is "revisited"
127+
# Smaller = stricter definition of revisiting
128+
revisit_radius: 50

notebooks/full_pipeline.ipynb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@
281281
"\n",
282282
"Runs motion-based insect detection and hierarchical classification on video files. Detects moving insects using background subtraction (GMM), tracks them across frames, classifies each detection, and aggregates predictions per track.\n",
283283
"\n",
284+
"**Note:** The species list and taxonomy are automatically loaded from the model checkpoint, so you don't need to provide them again.\n",
285+
"\n",
284286
"**Output files generated:**\n",
285287
"- `{video}_annotated.mp4` - Video with detection boxes and track paths (if `save_video=True`)\n",
286288
"- `{video}_debug.mp4` - Side-by-side view with GMM motion mask (if `save_video=True`)\n",
@@ -297,10 +299,10 @@
297299
"outputs": [],
298300
"source": [
299301
"results = bplusplus.inference(\n",
300-
" species_list=names,\n",
301302
" hierarchical_model_path=RESNET_MULTITASK_WEIGHTS,\n",
302303
" video_path=\"./10.mp4\",\n",
303304
" output_dir=\"./output\",\n",
305+
" # species_list=names, # Optional: override species from checkpoint\n",
304306
" fps=None, # None = all frames\n",
305307
" backbone=\"resnet50\", # Must match training\n",
306308
" save_video=True, # Set to False to skip video rendering (only CSV output)\n",
@@ -327,11 +329,19 @@
327329
")\n",
328330
"```\n",
329331
"\n",
332+
"#### Full Configuration Parameters\n",
333+
"\n",
330334
"| Parameter | Default | Description |\n",
331335
"|-----------|---------|-------------|\n",
336+
"| **GMM Background Subtractor** | | *Motion detection model* |\n",
337+
"| `gmm_history` | 500 | Frames to build background model |\n",
338+
"| `gmm_var_threshold` | 16 | Variance threshold for foreground detection |\n",
339+
"| **Morphological Filtering** | | *Noise removal* |\n",
340+
"| `morph_kernel_size` | 3 | Morphological kernel size (NxN) |\n",
332341
"| **Cohesiveness** | | *Filters scattered motion (plants) vs compact motion (insects)* |\n",
333342
"| `min_largest_blob_ratio` | 0.80 | Min ratio of largest blob to total motion |\n",
334343
"| `max_num_blobs` | 5 | Max separate blobs allowed in detection |\n",
344+
"| `min_motion_ratio` | 0.15 | Min ratio of motion pixels to bbox area |\n",
335345
"| **Shape** | | *Filters by contour properties* |\n",
336346
"| `min_area` | 200 | Min detection area (px²) |\n",
337347
"| `max_area` | 40000 | Max detection area (px²) |\n",
@@ -341,11 +351,17 @@
341351
"| `min_displacement` | 50 | Min net movement for confirmation (px) |\n",
342352
"| `min_path_points` | 10 | Min points before path analysis |\n",
343353
"| `max_frame_jump` | 100 | Max jump between frames (px) |\n",
344-
"| `lost_track_seconds` | 1.5 | How long to remember lost tracks (s) |\n",
354+
"| `max_lost_frames` | 45 | Frames before lost track deleted (e.g., 45 @ 30fps = 1.5s) |\n",
355+
"| `max_area_change_ratio` | 3.0 | Max area change ratio between frames |\n",
356+
"| **Tracker Matching** | | *Hungarian algorithm cost function* |\n",
357+
"| `tracker_w_dist` | 0.6 | Weight for distance cost (0-1) |\n",
358+
"| `tracker_w_area` | 0.4 | Weight for area cost (0-1) |\n",
359+
"| `tracker_cost_threshold` | 0.3 | Max cost for valid match (0-1) |\n",
345360
"| **Path Topology** | | *Confirms insect-like movement patterns* |\n",
346361
"| `max_revisit_ratio` | 0.30 | Max ratio of revisited positions |\n",
347362
"| `min_progression_ratio` | 0.70 | Min forward progression |\n",
348363
"| `max_directional_variance` | 0.90 | Max heading variance |\n",
364+
"| `revisit_radius` | 50 | Radius (px) for revisit detection |\n",
349365
"\n"
350366
]
351367
}

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "bplusplus"
3-
version = "2.0.4"
3+
version = "2.0.5"
44
description = "A simple method to create AI models for biodiversity, with collect and prepare pipeline"
55
authors = ["Titus Venverloo <tvenver@mit.edu>", "Deniz Aydemir <deniz@aydemir.us>", "Orlando Closs <orlandocloss@pm.me>", "Ase Hatveit <aase@mit.edu>"]
66
license = "MIT"

0 commit comments

Comments
 (0)