diff --git a/docs/user-guide/inference.md b/docs/user-guide/inference.md index ac92779..9e46d39 100644 --- a/docs/user-guide/inference.md +++ b/docs/user-guide/inference.md @@ -7,35 +7,39 @@ This guide covers running inference with trained models. Run inference on a single image: ```python -from mmdet.apis import init_detector, inference_detector +from visdet.apis import inference_detector, init_detector -config_file = 'configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py' -checkpoint_file = 'checkpoints/faster_rcnn_r50_fpn_1x_coco.pth' +config_file = "configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py" +checkpoint_file = "checkpoints/faster_rcnn_r50_fpn_1x_coco.pth" # Build the model from config and checkpoint -model = init_detector(config_file, checkpoint_file, device='cuda:0') +model = init_detector(config_file, checkpoint_file, device="cuda:0") # Run inference on an image -result = inference_detector(model, 'demo/demo.jpg') +result = inference_detector(model, "demo/demo.jpg") ``` ## Visualization -Display results: - -```python -from mmdet.apis import show_result_pyplot - -# Show the results -show_result_pyplot(model, 'demo/demo.jpg', result, score_thr=0.3) -``` - Save results to file: ```python -from mmdet.apis import show_result_pyplot - -model.show_result('demo/demo.jpg', result, out_file='result.jpg', score_thr=0.3) +from visdet.cv import imread +from visdet.visualization import DetLocalVisualizer + +# DetLocalVisualizer expects RGB images +image = imread("demo/demo.jpg", channel_order="rgb") + +visualizer = DetLocalVisualizer() +visualizer.dataset_meta = model.dataset_meta +visualizer.add_datasample( + "result", + image, + data_sample=result, + draw_gt=False, + out_file="result.jpg", + pred_score_thr=0.3, +) ``` ## Batch Inference @@ -44,16 +48,18 @@ Process multiple images: ```python import glob -from mmdet.apis import inference_detector + +from visdet.apis import inference_detector # Get all images in a directory -image_files = glob.glob('path/to/images/*.jpg') +image_files = glob.glob("path/to/images/*.jpg") -for image_file in image_files: - result = inference_detector(model, image_file) - # Process result... +# Run as a batch for better performance +results = inference_detector(model, image_files) ``` +`results` is a list of `DetDataSample` objects (one per input image). + ### Multi-GPU Inference To run inference on multiple GPUs in a single process, pass multiple CUDA devices to `init_detector` and then infer a batch (a list) of images: @@ -92,40 +98,51 @@ dataset.compute_metadata() # populates sample.metadata.width/height classes = model.dataset_meta.get("classes", []) score_thr = 0.3 -# 3) Run inference and attach detections -for sample in dataset.iter_samples(progress=True): - data_sample = inference_detector(model, sample.filepath) - - pred = data_sample.pred_instances - pred = pred[pred.scores > score_thr] - - width = sample.metadata.width - height = sample.metadata.height - - dets = [] - for bbox, label_id, score in zip( - pred.bboxes.cpu().numpy(), - pred.labels.cpu().numpy(), - pred.scores.cpu().numpy(), - strict=False, - ): - x1, y1, x2, y2 = bbox.tolist() - - dets.append( - { - "label": classes[int(label_id)] if classes else str(int(label_id)), - "bounding_box": [ - x1 / width, - y1 / height, - (x2 - x1) / width, - (y2 - y1) / height, - ], - "confidence": float(score), - } - ) - - sample["predictions"] = detections_to_fiftyone(dets) - sample.save() +# 3) Run streaming batched inference and attach detections +# (Batching is important for performance, and required for multi-GPU inference) +import itertools + +batch_size = 8 +sample_iter = dataset.iter_samples(progress=True) + +while True: + sample_batch = list(itertools.islice(sample_iter, batch_size)) + if not sample_batch: + break + + data_samples = inference_detector(model, [s.filepath for s in sample_batch]) + + for sample, data_sample in zip(sample_batch, data_samples, strict=True): + pred = data_sample.pred_instances + pred = pred[pred.scores > score_thr] + + width = sample.metadata.width + height = sample.metadata.height + + dets = [] + for bbox, label_id, score in zip( + pred.bboxes.cpu().numpy(), + pred.labels.cpu().numpy(), + pred.scores.cpu().numpy(), + strict=True, + ): + x1, y1, x2, y2 = bbox.tolist() + + dets.append( + { + "label": classes[int(label_id)] if classes else str(int(label_id)), + "bounding_box": [ + x1 / width, + y1 / height, + (x2 - x1) / width, + (y2 - y1) / height, + ], + "confidence": float(score), + } + ) + + sample["predictions"] = detections_to_fiftyone(dets) + sample.save() # 4) Visualize in the FiftyOne App session = fo.launch_app(dataset) @@ -153,20 +170,20 @@ bash tools/dist_test.sh ${CONFIG_FILE} ${CHECKPOINT_FILE} ${GPU_NUM} --eval bbox Create a custom inference pipeline: ```python -from mmdet.apis import init_detector -from mmcv import Config +from visdet.apis import inference_detector, init_detector +from visdet.engine.config import Config # Load config -cfg = Config.fromfile('config.py') +cfg = Config.fromfile("config.py") # Modify config if needed cfg.model.test_cfg.score_thr = 0.5 # Initialize model -model = init_detector(cfg, 'checkpoint.pth', device='cuda:0') +model = init_detector(cfg, "checkpoint.pth", device="cuda:0") # Run inference -result = inference_detector(model, 'image.jpg') +result = inference_detector(model, "image.jpg") ``` ### Async Inference @@ -175,10 +192,12 @@ For high-throughput scenarios: ```python import asyncio -from mmdet.apis import init_detector, async_inference_detector + +from visdet.apis import init_detector +from visdet.apis.inference import async_inference_detector async def async_process(): - model = init_detector(config_file, checkpoint_file, device='cuda:0') + model = init_detector(config_file, checkpoint_file, device="cuda:0") tasks = [async_inference_detector(model, img) for img in images] results = await asyncio.gather(*tasks) return results diff --git a/visdet/apis/__init__.py b/visdet/apis/__init__.py index 5b68195..dcffb8b 100644 --- a/visdet/apis/__init__.py +++ b/visdet/apis/__init__.py @@ -4,10 +4,11 @@ from visdet import models as _ # noqa: F401 from visdet.apis.det_inferencer import DetInferencer -from visdet.apis.inference import inference_detector, init_detector +from visdet.apis.inference import async_inference_detector, inference_detector, init_detector __all__ = [ "DetInferencer", + "async_inference_detector", "inference_detector", "init_detector", ]