Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/api/detect-birds.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ BirdCallDetector(
| :--- | :--- | :--- | :--- |
| `model_path` | `str` / — | **Yes** | Path to the trained YOLO model file (`.pt`, `.onnx`, `.engine`, etc.). |
| `species_mapping` | `str` / — | **Yes** | Dataset key for class-ID-to-species mapping. Must match the mapping the model was trained with. See [allowed values](../data/audio-and-model.md#species-mapping-species-mapping). |
| `conf_threshold` | `float` / `0.001` | No | Confidence threshold (0.0–1.0). Detections below this value are discarded. Use `0.2` for direct field use. Use `0.001` to retain all raw detections for evaluation. |
| `conf_threshold` | `float` / `0.001` | No | Confidence threshold (0.0–1.0). Detections below this value are discarded. For direct field use, take `0.15` for Just-Bird and `0.2` for the other models. Use `0.001` to retain all raw detections for evaluation. |
| `nms_iou_threshold` | `float` / `0.7` | No | IoU threshold for Non-Maximum Suppression applied per-clip and across overlapping time windows. |
| `song_gap_threshold` | `float` / `0.1` | No | Maximum temporal gap in seconds between two detections of the same species that are still merged into one continuous song segment. |
| `num_workers` | `int` / `1` | No | Number of CPU processes for PCEN, spectrogram rendering, and multi-file preprocess. YOLO inference stays in the parent and runs in batches. |
Expand Down Expand Up @@ -246,7 +246,7 @@ The examples use [Just-Bird](../models-and-metrics/just-bird.md), the recommende
detector = BirdCallDetector(
model_path="models/Just-Bird.pt",
species_mapping="Just-Bird",
conf_threshold=0.2,
conf_threshold=0.15,
)

detections = detector.detect(
Expand Down
4 changes: 2 additions & 2 deletions docs/cli/detect-birds.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Detect bird calls in arbitrary-length audio files using a trained YOLO model. Pr
| `--species-mapping` | `CHOICE` / — | **Yes** | Dataset key used to map class IDs to species eBird codes. Must match the mapping the model was trained with. See [allowed values](../data/audio-and-model.md#species-mapping-species-mapping) in the Data section. |
| `--output-path` | `PATH` / `results` | No | Output directory for result files (default: `results/`, auto-versioned to `results/run_N/` when outputs already exist). See [Output Formats](#output-formats). |
| `--output-format` | `CHOICE [...]` / `json-with-algorithm-metadata` | No | One or more output formats (space-separated). Accepts `json-with-algorithm-metadata`, `simplified-csv`, `xeno-canto-annota-json`, `raven-selection-table`, or `all`. Ignored when `--no-merge` is set (only `raw_detections.json` is written). |
| `--conf` | `FLOAT` / `0.2` | No | Confidence threshold (0.0–1.0). Detections below this value are discarded. The default of `0.2` works well for direct use. For evaluation workflows, use `0.001` together with `--no-merge` to retain all raw detections. |
| `--conf` | `FLOAT` / model default | No | Confidence threshold (0.0–1.0). Detections below this value are discarded. The default is `0.15` for Just-Bird and `0.2` for the other models, for direct use. For evaluation workflows, use `0.001` together with `--no-merge` to retain all raw detections. |
| `--nms-iou` | `FLOAT` / `0.7` | No | IoU threshold for Non-Maximum Suppression applied both per-clip and across overlapping time windows. Higher values keep more overlapping detections. Lower values suppress more aggressively. |
| `--merge` | `CHOICE` / `auto` | No | How detections from the 50%-overlap windows are merged: `fusion` (window ownership + weighted box fusion, tight call-level boxes), `reconstruct` (song merge with `--song-gap` / `--freq-iou`), or `auto`: `fusion` for Just-Bird, Hawaii and Southern-Sierra-Nevada, `reconstruct` for every other species mapping. See [Window fusion](#window-fusion-just-bird-default). |
| `--phrase-gap` | `FLOAT` / `0.05` (Just-Bird), `0` (Hawaii, Southern-Sierra-Nevada) | No | Fusion only. Join boxes in the same frequency band that are closer than this many seconds into one phrase box. `0` keeps one box per call or syllable. See [phrase boxes](#window-fusion-just-bird-default). |
Expand All @@ -57,7 +57,7 @@ The confidence threshold is the single most important tuning parameter. It contr

| Use-case | Recommended value |
| :--- | :--- |
| Quick field recording scan | `0.2` (default) |
| Quick field recording scan | `0.15` for Just-Bird, `0.2` for the other models (default) |
| High-precision output (few false positives) | `0.4`–`0.6` |
| Comprehensive evaluation (feed into F-beta sweep) | `0.001` with `--no-merge` |

Expand Down
2 changes: 1 addition & 1 deletion docs/cli/filter-and-merge-detections.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Filter raw bird call detections by confidence threshold and merge them into song
| Parameter | Type / Default | Required? | Description |
| :--- | :--- | :--- | :--- |
| `--raw-detections` | `PATH` / `results` | No | Raw detections **file** or `results/` directory from [`detect_birds.py --no-merge`](detect-birds.md). Default resolves to `raw_detections.json` (follows `results/.active_run`). |
| `--conf` | `FLOAT` / `0.2` | No | Confidence threshold for filtering (0.0–1.0). All raw detections with `confidence < threshold` are discarded before merging. |
| `--conf` | `FLOAT` / model default | No | Confidence threshold for filtering (0.0–1.0). All raw detections with `confidence < threshold` are discarded before merging. Omit to use the default for `model_config.species_mapping`: `0.15` for Just-Bird, `0.2` for the other models. |
| `--song-gap` | `FLOAT` / from JSON or `0.1` | No | Maximum temporal gap in seconds between two detections of the same species that are still merged into one song segment. When omitted, the value stored in the JSON's `model_config.song_gap_threshold` is used. Falls back to `0.1` if not present. |
| `--freq-iou` | `FLOAT` / `0.6` for Just-Bird, off otherwise | No | Just-Bird only. Minimum frequency IoU required before two bird detections merge into one song. Omit to use `model_config.freq_iou_threshold` when present, otherwise `0.6`. Pass a negative value for the time-only merger. Other species mappings ignore this flag. |
| `--merge` | `CHOICE` / `auto` | No | `fusion` (window ownership + weighted box fusion) or `reconstruct` (song merge with `--song-gap` / `--freq-iou`). `auto` uses `model_config.merge_method` from the JSON, else `fusion` for Just-Bird, Hawaii and Southern-Sierra-Nevada and `reconstruct` for other species mappings. See [Window fusion](detect-birds.md#window-fusion-just-bird-default). |
Expand Down
4 changes: 2 additions & 2 deletions docs/getting-started/demo_onnx.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ Run BirdBox detection entirely in your browser. The graphs under `docs/models/`
<div>
<label for="onnx-conf">Confidence Threshold</label>
<div class="onnx-demo__slider-row">
<input id="onnx-conf" type="range" min="0.01" max="0.80" step="0.01" value="0.18" />
<output id="onnx-conf-value" for="onnx-conf">0.18</output>
<input id="onnx-conf" type="range" min="0.01" max="0.80" step="0.01" value="0.15" />
<output id="onnx-conf-value" for="onnx-conf">0.15</output>
</div>
</div>
<div>
Expand Down
2 changes: 1 addition & 1 deletion docs/models-and-metrics/just-bird.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ The graph shows precision, recall and F1 at IoU 0.5 for every confidence thresho

<img src="../../img/metrics/just_bird_F1.png" width="1000" alt="Precision, recall and F1 at IoU 0.5 on the Southern Sierra Nevada hold-out, current recipe against previous recipe">

- **Confidence threshold:** around **0.15**. The best threshold on the Hawai'i validation recordings is 0.13 to 0.15, and it carries over to the unseen site with almost no loss (0.384 against the best 0.385).
- **Confidence threshold:** **0.15**, the default in `detect_birds.py`, the Streamlit app and the ONNX demo. The best threshold on the Hawai'i validation recordings is 0.13 to 0.15, and it carries over to the unseen site with almost no loss (0.384 against the best 0.385).
- **Phrase gap:** some Southern Sierra Nevada labels box a whole phrase where the model boxes single syllables, which lowers the scores at IoU 0.5 and above. The default phrase gap of 0.05 s raises F1 at IoU 0.5 there from 0.385 to 0.396, and on song-labelled Western-US validation minutes from 0.170 to 0.197. On call-level labels it costs about 0.05 (Hawai'i val: 0.581 to 0.531). If your annotations box single calls, pass `--phrase-gap 0`. [Phrase boxes](../cli/detect-birds.md#window-fusion-just-bird-default) has the numbers for other gaps.
- **In-domain:** on the full Hawai'i validation recordings, the released model reaches F1 0.590 at IoU 0.5 (threshold 0.14, phrase gap off).

Expand Down
Binary file modified docs/models/Just-Bird_fp16.onnx
Binary file not shown.
6 changes: 3 additions & 3 deletions run_pipeline.bat
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,13 @@ python src\evaluation\f_beta_score_analysis.py ^
if errorlevel 1 goto :fail


REM Step 3: From raw detections, filter at conf=0.25 and merge.
echo Filtering raw detections at conf=0.25 and merging for confusion matrix...
REM Step 3: From raw detections, filter at the model's default confidence
REM (0.15 for Just-Bird, 0.2 for the other models; add --conf to change it) and merge.
echo Filtering raw detections at the model's default confidence and merging for confusion matrix...
python src\evaluation\filter_and_merge_detections.py ^
--raw-detections "%OUTPUT_PATH%" ^
--output-path "%OUTPUT_PATH%" ^
--output-format all ^
--conf 0.2 ^
%MERGE_FLAGS%
if errorlevel 1 goto :fail

Expand Down
6 changes: 3 additions & 3 deletions run_pipeline.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,13 @@ python src\evaluation\f_beta_score_analysis.py `
@SINGLE_CLS_FLAG


# Step 3: From raw detections, filter at conf=0.25 and merge.
Write-Host "Filtering raw detections at conf=0.25 and merging for confusion matrix..."
# Step 3: From raw detections, filter at the model's default confidence
# (0.15 for Just-Bird, 0.2 for the other models; add --conf to change it) and merge.
Write-Host "Filtering raw detections at the model's default confidence and merging for confusion matrix..."
python src\evaluation\filter_and_merge_detections.py `
--raw-detections "$OUTPUT_PATH" `
--output-path "$OUTPUT_PATH" `
--output-format all `
--conf 0.2 `
@MERGE_FLAGS


Expand Down
6 changes: 3 additions & 3 deletions run_pipeline.sh
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,13 @@ python src/evaluation/f_beta_score_analysis.py \
"${SINGLE_CLS_FLAG[@]}"


# Step 3: From raw detections, filter at conf=0.25 and merge.
echo "Filtering raw detections at conf=0.25 and merging for confusion matrix..."
# Step 3: From raw detections, filter at the model's default confidence
# (0.15 for Just-Bird, 0.2 for the other models; add --conf to change it) and merge.
echo "Filtering raw detections at the model's default confidence and merging for confusion matrix..."
python src/evaluation/filter_and_merge_detections.py \
--raw-detections "${OUTPUT_PATH}" \
--output-path "${OUTPUT_PATH}" \
--output-format all \
--conf 0.2 \
"${MERGE_FLAGS[@]}"


Expand Down
11 changes: 8 additions & 3 deletions src/evaluation/filter_and_merge_detections.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
describe_merge_settings,
file_ends_from_raw,
merge_detections,
resolve_conf,
resolve_merge_settings,
)
from inference.utils.output_paths import (
Expand Down Expand Up @@ -323,8 +324,11 @@ def main():
parser.add_argument(
'--conf',
type=float,
default=0.2,
help='Confidence threshold for filtering (0.0-1.0, default: 0.2)'
default=None,
help=(
'Confidence threshold for filtering (0.0-1.0). Default: 0.15 for Just-Bird, '
'0.2 for the other models (species_mapping in the JSON model_config)'
)
)

parser.add_argument(
Expand Down Expand Up @@ -393,7 +397,7 @@ def main():
if not Path(args.raw_detections).exists():
print(f"Error: Raw detections file not found: {args.raw_detections}", file=sys.stderr)
sys.exit(1)
if not (0.0 <= args.conf <= 1.0):
if args.conf is not None and not (0.0 <= args.conf <= 1.0):
print(f"Error: Confidence threshold must be between 0.0 and 1.0, got: {args.conf}", file=sys.stderr)
sys.exit(1)
if not ensure_output_directory(args.output_path):
Expand All @@ -403,6 +407,7 @@ def main():
data = filter_obj.load_detections(args.raw_detections)
raw_list = data.get('detections', [])
model_config = data.get('model_config', {})
args.conf = resolve_conf(model_config.get('species_mapping'), args.conf)
settings = resolve_merge_settings(model_config, args.song_gap, args.freq_iou, args.merge, args.phrase_gap)
song_gap = settings['song_gap_threshold']

Expand Down
20 changes: 17 additions & 3 deletions src/inference/detect_birds.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,12 @@ def reconstruct_songs(
# (call labels) 0.581 -> 0.531. The Hawaii and Southern-Sierra-Nevada models
# are trained on and used for call labels, so they keep call-level boxes.
FUSION_DEFAULT_PHRASE_GAP = {JUST_BIRD_SPECIES_MAPPING: 0.05}
# Default confidence threshold per mapping for direct use. Just-Bird: the best
# IoU 0.5 micro F1 is at 0.13 to 0.14 on Hawaii val and 0.16 on Western-US val;
# 0.15 is within 0.005 of the best there and on the Southern Sierra Nevada
# hold-out (best at 0.08 to 0.09, not used for tuning).
DEFAULT_CONF = 0.2
MAPPING_DEFAULT_CONF = {JUST_BIRD_SPECIES_MAPPING: 0.15}


def resolve_merge_method(species_mapping: Optional[str], requested: Optional[str]) -> str:
Expand All @@ -368,6 +374,14 @@ def resolve_merge_method(species_mapping: Optional[str], requested: Optional[str
return requested


def resolve_conf(species_mapping: Optional[str], requested: Optional[float] = None) -> float:
"""Confidence threshold: the requested value, else the mapping's default
(MAPPING_DEFAULT_CONF, DEFAULT_CONF for other mappings)."""
if requested is None:
requested = MAPPING_DEFAULT_CONF.get(species_mapping, DEFAULT_CONF)
return float(requested)


def resolve_phrase_gap(
species_mapping: Optional[str],
merge_method: str,
Expand Down Expand Up @@ -1934,12 +1948,11 @@ def main():
)
)

# the default value should work perfectly
parser.add_argument(
'--conf',
type=float,
default=0.2,
help='Confidence threshold for detections'
default=None,
help='Confidence threshold for detections (default: 0.15 for Just-Bird, 0.2 for the other models)'
)

# this value can be further explored
Expand Down Expand Up @@ -2029,6 +2042,7 @@ def main():
)

args = parser.parse_args()
args.conf = resolve_conf(args.species_mapping, args.conf)

if args.no_merge and args.output_format != ['json-with-algorithm-metadata']:
print(
Expand Down
22 changes: 14 additions & 8 deletions src/inference/onnx_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@
1.5 s grid is complete. Detections that fall only in
that silence are removed.
Input ``conf`` float32, shape ``(1,)``
Confidence threshold. Required. Suggested default 0.18
(also stored in ONNX metadata as ``default_conf``).
Confidence threshold. Required. Suggested default 0.15
for Just-Bird, 0.2 for the other models (also stored in
ONNX metadata as ``default_conf``).
Input ``song_gap`` float32, shape ``(1,)``
Required. Song-merge graphs: max gap in seconds between
detections to merge into the same song, suggested 0.1.
Expand Down Expand Up @@ -151,7 +152,8 @@
MAX_FREQ = 15000
MIN_FREQ = 50

DEFAULT_CONF = 0.18
# The suggested conf comes from detect_birds.resolve_conf (0.15 for Just-Bird,
# 0.2 otherwise).
DEFAULT_NMS_IOU = 0.7
DEFAULT_SONG_GAP = 0.1
# Fusion graphs: the song_gap input is the phrase gap (0 = off); its default
Expand Down Expand Up @@ -1942,11 +1944,11 @@ def main():
parser.add_argument(
"--conf",
type=float,
default=DEFAULT_CONF,
default=None,
help=(
"Suggested confidence threshold stored in ONNX metadata "
f"(default: {DEFAULT_CONF}). Hosts must pass a conf tensor on "
"every run. This value is the usual starting point."
"(default: 0.15 for Just-Bird, 0.2 for the other models). Hosts must "
"pass a conf tensor on every run. This value is the usual starting point."
),
)
parser.add_argument(
Expand Down Expand Up @@ -2028,10 +2030,14 @@ def main():

try:
from inference.detect_birds import (
resolve_freq_iou_threshold, resolve_merge_method, resolve_phrase_gap,
resolve_conf, resolve_freq_iou_threshold, resolve_merge_method, resolve_phrase_gap,
)
except ImportError:
from detect_birds import resolve_freq_iou_threshold, resolve_merge_method, resolve_phrase_gap
from detect_birds import (
resolve_conf, resolve_freq_iou_threshold, resolve_merge_method, resolve_phrase_gap,
)

args.conf = resolve_conf(mapping_name, args.conf)

resolved_freq_iou = resolve_freq_iou_threshold(mapping_name, None)
merge_method = resolve_merge_method(mapping_name, args.merge)
Expand Down
6 changes: 3 additions & 3 deletions src/streamlit/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
sys.path.insert(0, str(Path(__file__).parent))

import config
from inference.detect_birds import BirdCallDetector, resolve_merge_method, resolve_phrase_gap
from inference.detect_birds import BirdCallDetector, resolve_conf, resolve_merge_method, resolve_phrase_gap
from inference.utils import pcen_inference
from inference.utils.raven_export import build_raven_rows
from inference.utils.xeno_canto_export import build_xeno_canto_json
Expand Down Expand Up @@ -849,14 +849,14 @@ def main():
"Confidence Threshold",
min_value=0.01,
max_value=0.8,
value=0.18,
value=resolve_conf(species_mapping_name),
step=0.01,
format="%.2f",
help="""
Minimum confidence score for individual detections.\\
Decrease to retrieve more detections and therefore emphasize Recall.\\
Increase to retrieve less detections and therefore emphasize Precision.\\
Recommended: 0.25
Default: 0.15 for Just-Bird, 0.2 for the other models.
"""
)

Expand Down
4 changes: 2 additions & 2 deletions tests/java/test_model.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
* java -cp tests/java:tests/java/onnxruntime.jar test_model
* java -cp tests/java:tests/java/onnxruntime.jar test_model tests/test.wav
* java -cp tests/java:tests/java/onnxruntime.jar test_model audio.wav model.onnx out.txt
* java -cp tests/java:tests/java/onnxruntime.jar test_model audio.wav model.onnx out.txt 0.18 0.1
* java -cp tests/java:tests/java/onnxruntime.jar test_model audio.wav model.onnx out.txt 0.15 0.05
*
* Args: [wav] [onnx] [out.txt] [conf] [song_gap]
* Defaults: tests/test.wav, docs/models/Just-Bird_fp32.onnx,
Expand All @@ -69,7 +69,7 @@ public static void main(String[] args) throws Exception {
OrtEnvironment env = OrtEnvironment.getEnvironment();
try (OrtSession session = env.createSession(onnx.toString())) {
Map<String, String> meta = session.getMetadata().getCustomMetadata();
float conf = floatArg(args, 3, meta, "default_conf", 0.18f);
float conf = floatArg(args, 3, meta, "default_conf", 0.15f);
float gap = floatArg(args, 4, meta, "default_song_gap", 0.1f);
Map<Integer, String> names = parseNames(meta.get("names"));

Expand Down
Loading