M
muq
93ae08bc91
The OSS threshold_qualifier was last synced from utils on Feb 23 2026, before the major robustness improvements landed in utils on Mar 19 2026. This commit brings it fully up to date. Changes ported from utils: - Multi-pass detection (Pass 1 strong burst, Pass 2 weak residual, Pass 3 sustained faint burst via macro-window averaging) - Noise floor estimation via percentile instead of simple max*threshold - Dynamic range ratio guard (early exit on low-contrast captures) - Improved _find_ranges, _expand_and_filter_ranges, _merge_ranges helpers - Spectral smoothing in _estimate_spectral_bounds for wideband bursts - Minimum duration filter expressed in absolute time (5ms) not sample count Also includes the Pass 2 hysteresis spillover fix: - Pass 2 expansion now runs against residual_power (masked) instead of smoothed_power, preventing it from walking into Pass 1 territory - Pass 2 mask now has a window_size guard band around Pass 1 ranges, matching the guard already used in Pass 3 Only change from utils: import swapped to ria_toolkit_oss.datatypes.
56 lines
1.7 KiB
Python
56 lines
1.7 KiB
Python
from ria_toolkit_oss.datatypes.annotation import Annotation
|
|
|
|
# TODO figure out how to transfer labels in the merge case
|
|
|
|
|
|
def remove_contained_boxes(annotations: list[Annotation]):
|
|
"""
|
|
Remove all annotations (bounding boxes) that are entirely contained within other boxes in the list.
|
|
|
|
:param annotations: A list of Annotation objects.
|
|
:type annotations: list[Annotation]
|
|
|
|
:returns: A new list of Annotation objects.
|
|
:rtype: list[Annotation]"""
|
|
|
|
output_boxes = []
|
|
|
|
for i in range(len(annotations)):
|
|
contained = False
|
|
for j in range(len(annotations)):
|
|
if i != j and is_annotation_contained(annotations[i], annotations[j]):
|
|
contained = True
|
|
break
|
|
|
|
if not contained:
|
|
output_boxes.append(annotations[i])
|
|
|
|
return output_boxes
|
|
|
|
|
|
def is_annotation_contained(inner: Annotation, outer: Annotation) -> bool:
|
|
"""
|
|
Check if an annotation box is entirely contained within another annotation bounding box.
|
|
|
|
:param inner: The inner box.
|
|
:type inner: Annotation.
|
|
:param outer: The outer box.
|
|
:type outer: Annotation.
|
|
|
|
:returns: True if inner is within outer, false otherwise.
|
|
:rtype: bool
|
|
"""
|
|
|
|
inner_sample_stop = inner.sample_start + inner.sample_count
|
|
outer_sample_stop = outer.sample_start + outer.sample_count
|
|
|
|
if inner.sample_start > outer.sample_start and inner_sample_stop < outer_sample_stop:
|
|
if inner.freq_lower_edge > outer.freq_lower_edge and inner.freq_upper_edge < outer.freq_upper_edge:
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def merge_annotations(annotations: list[Annotation], overlap_threshold) -> list[Annotation]:
|
|
raise NotImplementedError
|