Visitar URL original
Fix CTD empty conditions edge case by maximpavliv · Pull Request #3076 · DeepLabCut/DeepLabCut · GitHub
Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
eacbdaf
get_conditions_provider_for_video: load assemblies instead of full pi…
maximpavliv Jun 25, 2025
66f1da8
Fix CondProvider.load_conditions_pickle()
maximpavliv Jun 26, 2025
b5f341b
Fix FilterLowConfidencePoses
maximpavliv Jun 26, 2025
df805ec
Fix create_video_with_all_detections (bboxes generated by CTD inference)
maximpavliv Jun 26, 2025
8282f4d
PadOutputs: normalize output format
maximpavliv Jul 1, 2025
a098c63
Add CTD model to integration tests
maximpavliv Jun 25, 2025
2bd069f
Merge branch 'main' into maxim/add_ctd_integration_test
maximpavliv Jul 10, 2025
9f04c61
Formatting
maximpavliv Jul 11, 2025
2abf37c
Trim superanimal_humanbody.yaml default project config
maximpavliv Jul 21, 2025
a1a6be1
Trim superanimal_humanbody_colors
maximpavliv Jul 21, 2025
dfbce1d
Correct get_checkpoint_epoch
maximpavliv Jul 21, 2025
1432a73
Add rtmpose_x modelzoo model config
maximpavliv Jul 21, 2025
a4d74cc
Add FilteredDetector
maximpavliv Jul 21, 2025
0cbfe59
Add get_filtered_coco_detector_inference_runner() method
maximpavliv Jul 21, 2025
84b230e
Add ScaleToUnitRange transform
maximpavliv Jul 21, 2025
c4c1318
Superanimal humanbody inference: use filtered detector runner
maximpavliv Jul 21, 2025
dc511cd
ModelZoo tab: make humanbody general case
maximpavliv Jul 21, 2025
479cc66
get_super_animal_scorer(): add torchvision_detector_name arg
maximpavliv Jul 21, 2025
6a14584
Remove superanimal_humanbody_video_inference.py module
maximpavliv Jul 21, 2025
6774812
Regularize get_super_animal_model_config_path()
maximpavliv Jul 21, 2025
424ac92
Regularize load_super_animal_config()
maximpavliv Jul 21, 2025
04438f8
Regularize download_super_animal_snapshot()
maximpavliv Jul 21, 2025
256977b
update_config(): superanimal_humanbody - compatible
maximpavliv Jul 21, 2025
8d4cf20
Revert video_inference()
maximpavliv Jul 21, 2025
edf4f9d
Revert create_df_from_prediction()
maximpavliv Jul 21, 2025
cded581
Restore CTDInferenceRunner
maximpavliv Jul 21, 2025
7eaf923
Remove TorchvisionDetectorInferenceRunner
maximpavliv Jul 21, 2025
feb34d1
Revert DetectorInferenceRunner
maximpavliv Jul 21, 2025
711a47e
superanimal_analyze_images() - make humanbody compatible
maximpavliv Jul 21, 2025
28e4dd0
Revert build_predictions_dataframe()
maximpavliv Jul 21, 2025
193f935
Revert get_inference_runners()
maximpavliv Jul 21, 2025
613b2ac
Revert detectors/fasterRCNN.py
maximpavliv Jul 21, 2025
d848741
Revert detectors/torchvision.py
maximpavliv Jul 21, 2025
bba8689
Revert base Runner
maximpavliv Jul 21, 2025
25fa08d
Fix superanimal_humanbody unit test
maximpavliv Jul 31, 2025
425484b
Disable video adaptation for superanimal_humanbody
maximpavliv Jul 31, 2025
4b04013
Fix testscript_superanimal_inference.py
maximpavliv Jul 31, 2025
eea470e
Remove debug print
maximpavliv Jul 31, 2025
3d47a36
Black formatting
maximpavliv Jul 31, 2025
7b50466
Merge branch 'maxim/superanimal_humanbody_filtered_detector' into max…
maximpavliv Jul 31, 2025
0da592b
Black formatting
maximpavliv Jul 31, 2025
6c0dc12
FilterLowConfidencePoses: fix default aggregate_func
maximpavliv Aug 18, 2025
54b3b97
ConditionalKeypointsToModelInputs - empty cond kpts case
maximpavliv Aug 19, 2025
dbbd7d1
TopDownCrop: crop to required size even with empty bboxes list
maximpavliv Aug 19, 2025
62dda47
CTDInferenceRunner: shortcut predict() when empty conditions
maximpavliv Aug 19, 2025
e5ed8ee
Merge branch 'main' into maxim/cond_kpts_bug
maximpavliv Sep 4, 2025
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
Prev Previous commit
Next Next commit
Add get_filtered_coco_detector_inference_runner() method
  • Loading branch information
maximpavliv committed Jul 21, 2025
commit 0cbfe59fd5193dac13d1fb14102bb03f530345c7
123 changes: 123 additions & 0 deletions deeplabcut/pose_estimation_pytorch/apis/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@
import numpy as np
import pandas as pd

from torchvision.models import detection
from torchvision.models.detection import (
fasterrcnn_resnet50_fpn,
fasterrcnn_mobilenet_v3_large_fpn,
FasterRCNN_ResNet50_FPN_Weights,
FasterRCNN_ResNet50_FPN_V2_Weights,
FasterRCNN_MobileNet_V3_Large_FPN_Weights,
)

from deeplabcut.core.config import read_config_as_dict
from deeplabcut.core.engine import Engine
from deeplabcut.pose_estimation_pytorch.data.ctd import CondFromModel
Expand All @@ -38,6 +47,7 @@
)
from deeplabcut.pose_estimation_pytorch.data.transforms import build_transforms
from deeplabcut.pose_estimation_pytorch.models import DETECTORS, PoseModel
from deeplabcut.pose_estimation_pytorch.models.detectors.filtered_detector import FilteredDetector
from deeplabcut.pose_estimation_pytorch.runners import (
build_inference_runner,
CTDTrackingConfig,
Expand Down Expand Up @@ -713,6 +723,119 @@ def get_detector_inference_runner(
return runner


TORCHVISION_DETECTORS = {
"fasterrcnn_resnet50_fpn": {
"fn": fasterrcnn_resnet50_fpn,
"weights": FasterRCNN_ResNet50_FPN_Weights.DEFAULT,
},
"fasterrcnn_resnet50_fpn_v2": {
"fn": detection.fasterrcnn_resnet50_fpn_v2,
"weights": FasterRCNN_ResNet50_FPN_V2_Weights.DEFAULT,
},
"fasterrcnn_mobilenet_v3_large_fpn": {
"fn": fasterrcnn_mobilenet_v3_large_fpn,
"weights": FasterRCNN_MobileNet_V3_Large_FPN_Weights.DEFAULT,
},
}
def get_filtered_coco_detector_inference_runner(
model_name: str,
category_id: int,
batch_size: int = 1,
device: str | None = None,
box_score_thresh: float = 0.6,
max_individuals: int | None = None,
color_mode: str | None = None,
model_config: dict | None = None,
transform: A.BaseCompose | None = None,
) -> DetectorInferenceRunner:
"""
Builds a detector inference runner using a pretrained COCO detector from torchvision.

This function loads a pretrained object detection model from `torchvision.models.detection`,
wraps it in a `FilteredDetector` that keeps only detections for a specified COCO category,
and packages it into a `DetectorInferenceRunner` ready for inference.

You can optionally provide a model configuration dictionary to resolve `device`, `max_individuals`,
and `color_mode`. If no `model_config` is given, these must be specified explicitly.

Args:
model_name (str): Name of the torchvision detection model to load.
Supported values include:
"fasterrcnn_resnet50_fpn",
"fasterrcnn_resnet50_fpn_v2",
"fasterrcnn_mobilenet_v3_large_fpn".
category_id (int): The COCO category ID to retain in the detections.
batch_size (int, optional): Batch size for inference. Defaults to 1.
device (str or None, optional): Device to run the model on (e.g., "cuda", "cpu", or "mps").
If None, resolved from model_config or defaults to CUDA.
box_score_thresh (float, optional): Confidence threshold for filtering bounding boxes.
Defaults to 0.6.
max_individuals (int or None, optional): Maximum number of individuals to retain per image.
If None, resolved from model_config.
color_mode (str or None, optional): Color mode used for preprocessing (e.g., "RGB").
If None, resolved from model_config.
model_config (dict or None, optional): Optional configuration dictionary used to resolve
`device`, `max_individuals`, and `color_mode`.
transform (A.BaseCompose or None, optional): Optional preprocessing pipeline.
If None, uses the model's default transform.

Returns:
DetectorInferenceRunner: A configured detector inference runner.

Raises:
ValueError: If `model_config` is not provided and required fields are missing.
"""
if model_name not in TORCHVISION_DETECTORS:
raise ValueError(f"Unsupported model: {model_name}")

if model_config is not None:
if device is None:
device = resolve_device(model_config)
if max_individuals is None:
max_individuals = len(model_config["metadata"]["individuals"])
if color_mode is None:
color_mode = model_config["data"]["colormode"]
else:
missing = []
if device is None:
missing.append("device")
if max_individuals is None:
missing.append("max_individuals")
if color_mode is None:
missing.append("color_mode")
if missing:
raise ValueError(
f"If `model_config` is not provided, you must explicitly specify: {', '.join(missing)}."
)
if device == "mps":
device = "cpu"

if transform is None:
transform = build_transforms({"scale_to_unit_range": True})

entry = TORCHVISION_DETECTORS[model_name]
weights = entry["weights"]
detector = entry["fn"](weights=weights, box_score_thresh=box_score_thresh)

detector.eval().to(device)
filtered_detector = FilteredDetector(detector, class_id=category_id).to(device)
detector_runner = build_inference_runner(
task=Task.DETECT,
model=filtered_detector,
device=device,
snapshot_path=None,
batch_size=batch_size,
preprocessor=build_bottom_up_preprocessor(
color_mode=color_mode,
transform=transform,
),
postprocessor=build_detector_postprocessor(
max_individuals=max_individuals,
),
)
return detector_runner


def get_pose_inference_runner(
model_config: dict,
snapshot_path: str | Path,
Expand Down