Skip to content

Object Detection

Use create_detector with any registered object detection model. The model registry selects the inference backend, class labels, and default confidence threshold.

Set batch_size above one to batch list inputs when the selected ONNX model has a dynamic batch dimension. Models exported with a fixed batch size of one automatically retain serial inference.

Local ONNX models require their backend and class labels:

from open_image_models import create_detector

detector = create_detector(
    "/path/to/model.onnx",
    backend="rf_detr",
    class_labels=["vehicle", "License Plate"],
)

Creates an object detector from a registered model or local ONNX file.

Parameters:

Name Type Description Default
model DetectionModelName | str | PathLike[str]

Registered model name or path to a local ONNX model.

required
backend DetectorBackend | None

Inference backend. Required only for local models.

None
class_labels ClassLabels | None

Contiguous labels or a class-ID mapping. Required only for local models.

None
conf_thresh float | None

Confidence threshold. Uses the model default when omitted.

None
batch_size int

Maximum inference batch size for models with a dynamic batch dimension.

1
providers Sequence[str | tuple[str, dict]] | None

ONNX Runtime providers in order of decreasing precedence.

None
sess_options SessionOptions | None

Advanced ONNX Runtime session options.

None

Returns:

Type Description
ObjectDetector

A detector configured for the selected model or local file.

Raises:

Type Description
ValueError

If local model metadata is missing or registered model metadata is overridden.

FileNotFoundError

If a local model file does not exist.

Source code in open_image_models/detection/factory.py
def create_detector(
    model: DetectionModelName | str | os.PathLike[str],
    *,
    backend: DetectorBackend | None = None,
    class_labels: ClassLabels | None = None,
    conf_thresh: float | None = None,
    batch_size: int = 1,
    providers: Sequence[str | tuple[str, dict]] | None = None,
    sess_options: ort.SessionOptions | None = None,
) -> ObjectDetector:
    """
    Creates an object detector from a registered model or local ONNX file.

    Args:
        model: Registered model name or path to a local ONNX model.
        backend: Inference backend. Required only for local models.
        class_labels: Contiguous labels or a class-ID mapping. Required only for local models.
        conf_thresh: Confidence threshold. Uses the model default when omitted.
        batch_size: Maximum inference batch size for models with a dynamic batch dimension.
        providers: ONNX Runtime providers in order of decreasing precedence.
        sess_options: Advanced ONNX Runtime session options.

    Returns:
        A detector configured for the selected model or local file.

    Raises:
        ValueError: If local model metadata is missing or registered model metadata is overridden.
        FileNotFoundError: If a local model file does not exist.
    """
    threshold = conf_thresh
    if not isinstance(model, str) or model not in DETECTION_MODELS:
        model_path = Path(model)
        if not model_path.is_file():
            raise FileNotFoundError(f"ONNX model not found at '{model_path}'")
        if backend is None or class_labels is None:
            raise ValueError("backend and class_labels are required for a local model")
        labels = class_labels
    else:
        if backend is not None or class_labels is not None:
            raise ValueError("backend and class_labels cannot override a registered model")
        spec = DETECTION_MODELS[model]
        model_path = download_model(model)
        backend = spec.backend
        labels = spec.class_labels
        if threshold is None:
            threshold = spec.default_conf_thresh

    if backend == "yolo_v9":
        return YoloV9Detector(
            model_path=model_path,
            class_labels=labels,
            conf_thresh=threshold,
            batch_size=batch_size,
            providers=providers,
            sess_options=sess_options,
        )
    if backend == "rf_detr":
        return RFDETRDetector(
            model_path=model_path,
            class_labels=labels,
            conf_thresh=threshold,
            batch_size=batch_size,
            providers=providers,
            sess_options=sess_options,
        )

    raise ValueError(f"Unsupported detector backend: {backend}")

Core API

The core module provides base classes and protocols for object detection models, including essential data structures like BoundingBox and DetectionResult.

🔧 Core Components

The following components are shared by all detection backends:

  • BoundingBox: Represents a bounding box for detected objects.
  • DetectionResult: Stores label, confidence, and bounding box for a detection.
  • ObjectDetector: Protocol defining predict and display_predictions.

ClassLabels module-attribute

ClassLabels = Sequence[str] | Mapping[int, str]

Class labels as a contiguous sequence or explicit class-ID mapping.

BoundingBox dataclass

BoundingBox(x1: int, y1: int, x2: int, y2: int)

Represents an axis-aligned 2D bounding box defined by two corner points.

x1 instance-attribute

x1: int

X-coordinate of the top-left corner

y1 instance-attribute

y1: int

Y-coordinate of the top-left corner

x2 instance-attribute

x2: int

X-coordinate of the bottom-right corner

y2 instance-attribute

y2: int

Y-coordinate of the bottom-right corner

width property

width: int

Returns:

Type Description
int

The horizontal distance from x1 to x2.

height property

height: int

Returns:

Type Description
int

The vertical distance from y1 to y2.

area property

area: int

Returns:

Type Description
int

The bounding box area, or zero if the box is empty.

aspect_ratio property

aspect_ratio: float

Returns:

Type Description
float

The width-to-height ratio, or zero if the box is empty.

is_empty property

is_empty: bool

Returns:

Type Description
bool

True if either dimension is zero or negative, otherwise False.

xyxy property

xyxy: tuple[int, int, int, int]

Returns:

Type Description
tuple[int, int, int, int]

The coordinates as (x1, y1, x2, y2).

center property

center: tuple[float, float]

Returns:

Type Description
tuple[float, float]

The center coordinates as (center_x, center_y).

from_xywh classmethod

from_xywh(
    x: int, y: int, width: int, height: int
) -> BoundingBox

Creates a bounding box from top-left coordinates, width, and height.

Parameters:

Name Type Description Default
x int

X-coordinate of the left edge.

required
y int

Y-coordinate of the top edge.

required
width int

Width of the bounding box.

required
height int

Height of the bounding box.

required

Returns:

Type Description
BoundingBox

A bounding box in (x1, y1, x2, y2) format.

Source code in open_image_models/detection/core/base.py
@classmethod
def from_xywh(cls, x: int, y: int, width: int, height: int) -> "BoundingBox":
    """
    Creates a bounding box from top-left coordinates, width, and height.

    Args:
        x: X-coordinate of the left edge.
        y: Y-coordinate of the top edge.
        width: Width of the bounding box.
        height: Height of the bounding box.

    Returns:
        A bounding box in `(x1, y1, x2, y2)` format.
    """
    return cls(x, y, x + width, y + height)

from_cxcywh classmethod

from_cxcywh(
    center_x: float,
    center_y: float,
    width: float,
    height: float,
) -> BoundingBox

Creates a bounding box from center coordinates, width, and height.

Coordinates are rounded outward so the integer box contains the full floating-point region.

Parameters:

Name Type Description Default
center_x float

X-coordinate of the center.

required
center_y float

Y-coordinate of the center.

required
width float

Width of the bounding box.

required
height float

Height of the bounding box.

required

Returns:

Type Description
BoundingBox

A bounding box with integer coordinates.

Source code in open_image_models/detection/core/base.py
@classmethod
def from_cxcywh(cls, center_x: float, center_y: float, width: float, height: float) -> "BoundingBox":
    """
    Creates a bounding box from center coordinates, width, and height.

    Coordinates are rounded outward so the integer box contains the full floating-point region.

    Args:
        center_x: X-coordinate of the center.
        center_y: Y-coordinate of the center.
        width: Width of the bounding box.
        height: Height of the bounding box.

    Returns:
        A bounding box with integer coordinates.
    """
    half_width = width / 2
    half_height = height / 2
    return cls(
        floor(center_x - half_width),
        floor(center_y - half_height),
        ceil(center_x + half_width),
        ceil(center_y + half_height),
    )

intersection

intersection(other: BoundingBox) -> Optional[BoundingBox]

Computes the intersection with another bounding box.

Parameters:

Name Type Description Default
other BoundingBox

The bounding box to intersect with this box.

required

Returns:

Type Description
Optional[BoundingBox]

The positive-area intersection, or None if the boxes do not overlap.

Source code in open_image_models/detection/core/base.py
def intersection(self, other: "BoundingBox") -> Optional["BoundingBox"]:
    """
    Computes the intersection with another bounding box.

    Args:
        other: The bounding box to intersect with this box.

    Returns:
        The positive-area intersection, or `None` if the boxes do not overlap.
    """
    x1 = max(self.x1, other.x1)
    y1 = max(self.y1, other.y1)
    x2 = min(self.x2, other.x2)
    y2 = min(self.y2, other.y2)

    if x2 > x1 and y2 > y1:
        return BoundingBox(x1, y1, x2, y2)

    return None

intersects

intersects(other: BoundingBox) -> bool

Checks whether this bounding box intersects another.

Parameters:

Name Type Description Default
other BoundingBox

The bounding box to test.

required

Returns:

Type Description
bool

True if the boxes have a positive-area intersection, otherwise False.

Source code in open_image_models/detection/core/base.py
def intersects(self, other: "BoundingBox") -> bool:
    """
    Checks whether this bounding box intersects another.

    Args:
        other: The bounding box to test.

    Returns:
        `True` if the boxes have a positive-area intersection, otherwise `False`.
    """
    return self.intersection(other) is not None

contains_point

contains_point(x: float, y: float) -> bool

Checks whether a point lies within this bounding box.

Parameters:

Name Type Description Default
x float

X-coordinate of the point.

required
y float

Y-coordinate of the point.

required

Returns:

Type Description
bool

True if the point is inside the box or on its boundary, otherwise False.

Source code in open_image_models/detection/core/base.py
def contains_point(self, x: float, y: float) -> bool:
    """
    Checks whether a point lies within this bounding box.

    Args:
        x: X-coordinate of the point.
        y: Y-coordinate of the point.

    Returns:
        `True` if the point is inside the box or on its boundary, otherwise `False`.
    """
    return not self.is_empty and self.x1 <= x <= self.x2 and self.y1 <= y <= self.y2

contains

contains(other: BoundingBox) -> bool

Checks whether this bounding box fully contains another.

Parameters:

Name Type Description Default
other BoundingBox

The bounding box to test.

required

Returns:

Type Description
bool

True if both boxes are non-empty and this box contains all of other, otherwise False.

Source code in open_image_models/detection/core/base.py
def contains(self, other: "BoundingBox") -> bool:
    """
    Checks whether this bounding box fully contains another.

    Args:
        other: The bounding box to test.

    Returns:
        `True` if both boxes are non-empty and this box contains all of `other`, otherwise `False`.
    """
    return (
        not self.is_empty
        and not other.is_empty
        and self.x1 <= other.x1
        and self.y1 <= other.y1
        and other.x2 <= self.x2
        and other.y2 <= self.y2
    )

iou

iou(other: BoundingBox) -> float

Computes the Intersection-over-Union (IoU) with another bounding box.

Parameters:

Name Type Description Default
other BoundingBox

The bounding box to compare with this box.

required

Returns:

Type Description
float

The IoU in the range [0.0, 1.0], or zero if the union has no positive area.

Source code in open_image_models/detection/core/base.py
def iou(self, other: "BoundingBox") -> float:
    """
    Computes the Intersection-over-Union (IoU) with another bounding box.

    Args:
        other: The bounding box to compare with this box.

    Returns:
        The IoU in the range `[0.0, 1.0]`, or zero if the union has no positive area.
    """
    inter = self.intersection(other)

    if inter is None:
        return 0.0

    inter_area = inter.area
    union_area = self.area + other.area - inter_area
    return inter_area / union_area if union_area > 0 else 0.0

intersection_over_area

intersection_over_area(other: BoundingBox) -> float

Computes the intersection divided by this bounding box's area.

Parameters:

Name Type Description Default
other BoundingBox

The bounding box to compare with this box.

required

Returns:

Type Description
float

The fraction of this box covered by other, or zero if this box is empty or the boxes do not intersect.

Source code in open_image_models/detection/core/base.py
def intersection_over_area(self, other: "BoundingBox") -> float:
    """
    Computes the intersection divided by this bounding box's area.

    Args:
        other: The bounding box to compare with this box.

    Returns:
        The fraction of this box covered by `other`, or zero if this box is empty or the boxes do not intersect.
    """
    inter = self.intersection(other)
    return inter.area / self.area if inter is not None and self.area > 0 else 0.0

enclosing

enclosing(other: BoundingBox) -> BoundingBox

Computes the smallest bounding box containing both boxes.

Parameters:

Name Type Description Default
other BoundingBox

The bounding box to enclose with this box.

required

Returns:

Type Description
BoundingBox

A bounding box spanning this box and other.

Source code in open_image_models/detection/core/base.py
def enclosing(self, other: "BoundingBox") -> "BoundingBox":
    """
    Computes the smallest bounding box containing both boxes.

    Args:
        other: The bounding box to enclose with this box.

    Returns:
        A bounding box spanning this box and `other`.
    """
    return BoundingBox(
        min(self.x1, other.x1),
        min(self.y1, other.y1),
        max(self.x2, other.x2),
        max(self.y2, other.y2),
    )

to_xywh

to_xywh() -> tuple[int, int, int, int]

Converts the bounding box to top-left, width, and height format.

Returns:

Type Description
tuple[int, int, int, int]

The bounding box as (x, y, width, height).

Source code in open_image_models/detection/core/base.py
def to_xywh(self) -> tuple[int, int, int, int]:
    """
    Converts the bounding box to top-left, width, and height format.

    Returns:
        The bounding box as `(x, y, width, height)`.
    """
    return self.x1, self.y1, self.width, self.height

to_cxcywh

to_cxcywh() -> tuple[float, float, float, float]

Converts the bounding box to center, width, and height format.

Returns:

Type Description
tuple[float, float, float, float]

The bounding box as (center_x, center_y, width, height).

Source code in open_image_models/detection/core/base.py
def to_cxcywh(self) -> tuple[float, float, float, float]:
    """
    Converts the bounding box to center, width, and height format.

    Returns:
        The bounding box as `(center_x, center_y, width, height)`.
    """
    return *self.center, float(self.width), float(self.height)

as_slices

as_slices() -> tuple[slice, slice]

Converts the bounding box to NumPy-compatible image slices.

NumPy excludes the stop coordinate, so pixels at x2 and y2 are not included.

Returns:

Type Description
tuple[slice, slice]

A (rows, columns) tuple equivalent to (slice(y1, y2), slice(x1, x2)).

Source code in open_image_models/detection/core/base.py
def as_slices(self) -> tuple[slice, slice]:
    """
    Converts the bounding box to NumPy-compatible image slices.

    NumPy excludes the stop coordinate, so pixels at `x2` and `y2` are not included.

    Returns:
        A `(rows, columns)` tuple equivalent to `(slice(y1, y2), slice(x1, x2))`.
    """
    return slice(self.y1, self.y2), slice(self.x1, self.x2)

clamp

clamp(max_width: int, max_height: int) -> BoundingBox

Clamps the bounding box coordinates to frame boundaries.

Parameters:

Name Type Description Default
max_width int

Maximum x-coordinate, normally the frame width.

required
max_height int

Maximum y-coordinate, normally the frame height.

required

Returns:

Type Description
BoundingBox

A bounding box whose coordinates lie within [0, max_width] and [0, max_height].

Source code in open_image_models/detection/core/base.py
def clamp(self, max_width: int, max_height: int) -> "BoundingBox":
    """
    Clamps the bounding box coordinates to frame boundaries.

    Args:
        max_width: Maximum x-coordinate, normally the frame width.
        max_height: Maximum y-coordinate, normally the frame height.

    Returns:
        A bounding box whose coordinates lie within `[0, max_width]` and `[0, max_height]`.
    """
    return BoundingBox(
        x1=max(0, min(self.x1, max_width)),
        y1=max(0, min(self.y1, max_height)),
        x2=max(0, min(self.x2, max_width)),
        y2=max(0, min(self.y2, max_height)),
    )

is_inside

is_inside(frame_width: int, frame_height: int) -> bool

Checks whether all coordinates lie within frame boundaries.

This method only checks coordinate bounds; it does not require the box to have positive area. Use is_valid when both conditions are needed.

Parameters:

Name Type Description Default
frame_width int

Width of the frame.

required
frame_height int

Height of the frame.

required

Returns:

Type Description
bool

True if all coordinates lie within the frame, otherwise False.

Source code in open_image_models/detection/core/base.py
def is_inside(self, frame_width: int, frame_height: int) -> bool:
    """
    Checks whether all coordinates lie within frame boundaries.

    This method only checks coordinate bounds; it does not require the box to have positive area. Use `is_valid`
    when both conditions are needed.

    Args:
        frame_width: Width of the frame.
        frame_height: Height of the frame.

    Returns:
        `True` if all coordinates lie within the frame, otherwise `False`.
    """
    return self.x1 >= 0 and self.y1 >= 0 and self.x2 <= frame_width and self.y2 <= frame_height

is_valid

is_valid(frame_width: int, frame_height: int) -> bool

Checks whether the bounding box is non-empty and inside a frame.

Parameters:

Name Type Description Default
frame_width int

Width of the frame.

required
frame_height int

Height of the frame.

required

Returns:

Type Description
bool

True if the coordinates are ordered, have positive area, and lie inside the frame boundaries,

bool

otherwise False.

Source code in open_image_models/detection/core/base.py
def is_valid(self, frame_width: int, frame_height: int) -> bool:
    """
    Checks whether the bounding box is non-empty and inside a frame.

    Args:
        frame_width: Width of the frame.
        frame_height: Height of the frame.

    Returns:
        `True` if the coordinates are ordered, have positive area, and lie inside the frame boundaries,
        otherwise `False`.
    """
    return not self.is_empty and self.is_inside(frame_width, frame_height)

DetectionResult dataclass

DetectionResult(
    label: str, confidence: float, bounding_box: BoundingBox
)

Represents the result of an object detection.

label instance-attribute

label: str

Detected object label

confidence instance-attribute

confidence: float

Confidence score of the detection

bounding_box instance-attribute

bounding_box: BoundingBox

Bounding box of the detected object

from_detection_data classmethod

from_detection_data(
    bbox_data: tuple[int, int, int, int],
    confidence: float,
    label: str,
) -> DetectionResult

Creates a DetectionResult instance from bounding box data, confidence, and a class label.

Parameters:

Name Type Description Default
bbox_data tuple[int, int, int, int]

Bounding box coordinates as (x1, y1, x2, y2).

required
confidence float

Detection confidence score.

required
label str

Detected class label.

required

Returns:

Type Description
DetectionResult

A detection result containing the supplied data.

Source code in open_image_models/detection/core/base.py
@classmethod
def from_detection_data(
    cls,
    bbox_data: tuple[int, int, int, int],
    confidence: float,
    label: str,
) -> "DetectionResult":
    """
    Creates a `DetectionResult` instance from bounding box data, confidence, and a class label.

    Args:
        bbox_data: Bounding box coordinates as `(x1, y1, x2, y2)`.
        confidence: Detection confidence score.
        label: Detected class label.

    Returns:
        A detection result containing the supplied data.
    """
    bounding_box = BoundingBox(*bbox_data)
    return cls(label, confidence, bounding_box)

ObjectDetector

Bases: Protocol

predict

predict(
    images: Any,
) -> list[DetectionResult] | list[list[DetectionResult]]

Perform object detection on one or multiple images.

Parameters:

Name Type Description Default
images Any

A single image as a numpy array, a single image path as a string, a list of images as numpy arrays, or a list of image file paths.

required

Returns:

Type Description
list[DetectionResult] | list[list[DetectionResult]]

A list of DetectionResult for a single image input,

list[DetectionResult] | list[list[DetectionResult]]

or a list of lists of DetectionResult for multiple images.

Source code in open_image_models/detection/core/base.py
def predict(self, images: Any) -> list[DetectionResult] | list[list[DetectionResult]]:
    """
    Perform object detection on one or multiple images.

    Args:
        images: A single image as a numpy array, a single image path as a string, a list of images as numpy arrays,
                or a list of image file paths.

    Returns:
        A list of DetectionResult for a single image input,
        or a list of lists of DetectionResult for multiple images.
    """

display_predictions

display_predictions(image: ndarray) -> ndarray

Run object detection on the input image and display the predictions on the image.

Parameters:

Name Type Description Default
image ndarray

An input image as a numpy array.

required

Returns:

Type Description
ndarray

The image with bounding boxes and labels drawn on it.

Source code in open_image_models/detection/core/base.py
def display_predictions(self, image: np.ndarray) -> np.ndarray:
    """
    Run object detection on the input image and display the predictions on the image.

    Args:
        image: An input image as a numpy array.

    Returns:
        The image with bounding boxes and labels drawn on it.
    """

ModelInputShape dataclass

ModelInputShape(
    image_size: tuple[int, int], dynamic_batch: bool
)

Relevant dimensions read from a detector's NCHW input shape.

normalize_class_labels

normalize_class_labels(
    class_labels: ClassLabels,
) -> dict[int, str]

Normalize class labels into an explicit class-ID mapping.

Parameters:

Name Type Description Default
class_labels ClassLabels

Contiguous labels or a mapping from model class IDs to labels.

required

Returns:

Type Description
dict[int, str]

A class-ID-to-label dictionary.

Raises:

Type Description
ValueError

If no labels are supplied or a class ID or label is invalid.

Source code in open_image_models/detection/core/base.py
def normalize_class_labels(class_labels: ClassLabels) -> dict[int, str]:
    """
    Normalize class labels into an explicit class-ID mapping.

    Args:
        class_labels: Contiguous labels or a mapping from model class IDs to labels.

    Returns:
        A class-ID-to-label dictionary.

    Raises:
        ValueError: If no labels are supplied or a class ID or label is invalid.
    """
    if isinstance(class_labels, str):
        raise ValueError("class_labels must contain at least one label")

    labels = dict(class_labels.items()) if isinstance(class_labels, Mapping) else dict(enumerate(class_labels))
    if not labels:
        raise ValueError("class_labels must contain at least one label")
    if any(isinstance(class_id, bool) or not isinstance(class_id, int) or class_id < 0 for class_id in labels):
        raise ValueError("class label IDs must be non-negative integers")
    if any(not isinstance(label, str) or not label for label in labels.values()):
        raise ValueError("class labels must be non-empty strings")
    return labels

inspect_model_input_shape

inspect_model_input_shape(
    input_shape: Sequence[Any],
) -> ModelInputShape

Validates a detector input shape and determines its batching capability.

Parameters:

Name Type Description Default
input_shape Sequence[Any]

ONNX model input shape in NCHW format.

required

Returns:

Type Description
ModelInputShape

Static image dimensions and whether the batch dimension is dynamic.

Raises:

Type Description
ValueError

If the shape is not NCHW, does not use three channels, has dynamic spatial dimensions, or has a fixed batch size other than one.

Source code in open_image_models/detection/core/base.py
def inspect_model_input_shape(input_shape: Sequence[Any]) -> ModelInputShape:
    """
    Validates a detector input shape and determines its batching capability.

    Args:
        input_shape: ONNX model input shape in NCHW format.

    Returns:
        Static image dimensions and whether the batch dimension is dynamic.

    Raises:
        ValueError: If the shape is not NCHW, does not use three channels, has
            dynamic spatial dimensions, or has a fixed batch size other than one.
    """
    if len(input_shape) != 4:
        raise ValueError(f"Expected model input shape in NCHW format, got {input_shape}")

    batch_size, channels, height, width = input_shape
    if channels != 3:
        raise ValueError(f"Expected model input with 3 channels, got {channels}")
    if not isinstance(height, int) or not isinstance(width, int):
        raise ValueError(f"Expected static input height and width, got {input_shape}")
    if isinstance(batch_size, int) and batch_size != 1:
        raise ValueError(f"Expected a dynamic batch or fixed batch size 1, got {batch_size}")

    return ModelInputShape(image_size=(height, width), dynamic_batch=not isinstance(batch_size, int))

resolve_image_inputs

resolve_image_inputs(
    images: Any,
) -> tuple[list[ndarray], bool]

Normalize supported detector inputs into loaded image arrays.

Parameters:

Name Type Description Default
images Any

A single image array/path or a list of image arrays/paths.

required

Returns:

Type Description
tuple[list[ndarray], bool]

A tuple of loaded BGR images and whether the original input was a single image.

Source code in open_image_models/detection/core/base.py
def resolve_image_inputs(images: Any) -> tuple[list[np.ndarray], bool]:
    """
    Normalize supported detector inputs into loaded image arrays.

    Args:
        images: A single image array/path or a list of image arrays/paths.

    Returns:
        A tuple of loaded BGR images and whether the original input was a single image.
    """
    if isinstance(images, np.ndarray):
        return [images], True
    if isinstance(images, str | os.PathLike):
        return [_load_image(images)], True
    if isinstance(images, list):
        if all(isinstance(img, np.ndarray) for img in images):
            return cast(list[np.ndarray], images), False
        if all(isinstance(img, str | os.PathLike) for img in images):
            return [_load_image(img) for img in images], False
        raise TypeError("List must contain either all numpy arrays or all image file paths.")
    raise TypeError("Input must be a numpy array, a list of numpy arrays, or a list of image file paths.")

draw_detection_results

draw_detection_results(
    image: ndarray, detections: list[DetectionResult]
) -> ndarray

Draw detection results on an image.

Parameters:

Name Type Description Default
image ndarray

Input image to mutate.

required
detections list[DetectionResult]

Detection results to draw.

required

Returns:

Type Description
ndarray

The input image with bounding boxes and labels drawn on it.

Source code in open_image_models/detection/core/base.py
def draw_detection_results(image: np.ndarray, detections: list[DetectionResult]) -> np.ndarray:
    """
    Draw detection results on an image.

    Args:
        image: Input image to mutate.
        detections: Detection results to draw.

    Returns:
        The input image with bounding boxes and labels drawn on it.
    """
    for detection in detections:
        bbox = detection.bounding_box
        label = f"{detection.label}: {detection.confidence:.2f}"
        cv2.rectangle(image, (bbox.x1, bbox.y1), (bbox.x2, bbox.y2), (0, 255, 0), 2)
        (text_width, text_height), baseline = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
        cv2.rectangle(
            image,
            (bbox.x1, bbox.y1 - text_height - baseline),
            (bbox.x1 + text_width, bbox.y1),
            (0, 255, 0),
            thickness=cv2.FILLED,
        )
        cv2.putText(
            image,
            label,
            (bbox.x1, bbox.y1 - baseline),
            cv2.FONT_HERSHEY_SIMPLEX,
            0.5,
            (0, 0, 0),
            1,
        )
    return image

Open Image Models HUB.

DetectionModelName module-attribute

DetectionModelName = Literal[
    "rf-detr-nano-384-coco",
    "rf-detr-small-512-coco",
    "rf-detr-medium-576-coco",
    "rf-detr-large-704-coco",
    "yolo-v9-s-608-license-plate-end2end",
    "yolo-v9-t-640-license-plate-end2end",
    "yolo-v9-t-512-license-plate-end2end",
    "yolo-v9-t-416-license-plate-end2end",
    "yolo-v9-t-384-license-plate-end2end",
    "yolo-v9-t-256-license-plate-end2end",
]

Names of the available object detection models.

LicensePlateModelName module-attribute

LicensePlateModelName = Literal[
    "yolo-v9-s-608-license-plate-end2end",
    "yolo-v9-t-640-license-plate-end2end",
    "yolo-v9-t-512-license-plate-end2end",
    "yolo-v9-t-416-license-plate-end2end",
    "yolo-v9-t-384-license-plate-end2end",
    "yolo-v9-t-256-license-plate-end2end",
]

Names of the available license plate detection models.

DetectionModelSpec dataclass

DetectionModelSpec(
    url: str,
    backend: DetectorBackend,
    class_labels: ClassLabels,
    default_conf_thresh: float,
)

Configuration required to construct a detector for a trained model.

Attributes:

Name Type Description
url str

URL of the ONNX model file.

backend DetectorBackend

Inference backend used by the model.

class_labels ClassLabels

Labels corresponding to the model's class IDs.

default_conf_thresh float

Default confidence threshold for predictions.

DETECTION_MODELS module-attribute

DETECTION_MODELS: dict[
    DetectionModelName, DetectionModelSpec
] = {
    "rf-detr-nano-384-coco": DetectionModelSpec(
        url=f"{BASE_URL}/rf-detr-nano-384-coco.onnx",
        backend="rf_detr",
        class_labels=COCO_CLASSES,
        default_conf_thresh=0.5,
    ),
    "rf-detr-small-512-coco": DetectionModelSpec(
        url=f"{BASE_URL}/rf-detr-small-512-coco.onnx",
        backend="rf_detr",
        class_labels=COCO_CLASSES,
        default_conf_thresh=0.5,
    ),
    "rf-detr-medium-576-coco": DetectionModelSpec(
        url=f"{BASE_URL}/rf-detr-medium-576-coco.onnx",
        backend="rf_detr",
        class_labels=COCO_CLASSES,
        default_conf_thresh=0.5,
    ),
    "rf-detr-large-704-coco": DetectionModelSpec(
        url=f"{BASE_URL}/rf-detr-large-704-coco.onnx",
        backend="rf_detr",
        class_labels=COCO_CLASSES,
        default_conf_thresh=0.5,
    ),
    "yolo-v9-s-608-license-plate-end2end": DetectionModelSpec(
        url=f"{BASE_URL}/yolo-v9-s-608-license-plates-end2end.onnx",
        backend="yolo_v9",
        class_labels=("License Plate",),
        default_conf_thresh=0.25,
    ),
    "yolo-v9-t-640-license-plate-end2end": DetectionModelSpec(
        url=f"{BASE_URL}/yolo-v9-t-640-license-plates-end2end.onnx",
        backend="yolo_v9",
        class_labels=("License Plate",),
        default_conf_thresh=0.25,
    ),
    "yolo-v9-t-512-license-plate-end2end": DetectionModelSpec(
        url=f"{BASE_URL}/yolo-v9-t-512-license-plates-end2end.onnx",
        backend="yolo_v9",
        class_labels=("License Plate",),
        default_conf_thresh=0.25,
    ),
    "yolo-v9-t-416-license-plate-end2end": DetectionModelSpec(
        url=f"{BASE_URL}/yolo-v9-t-416-license-plates-end2end.onnx",
        backend="yolo_v9",
        class_labels=("License Plate",),
        default_conf_thresh=0.25,
    ),
    "yolo-v9-t-384-license-plate-end2end": DetectionModelSpec(
        url=f"{BASE_URL}/yolo-v9-t-384-license-plates-end2end.onnx",
        backend="yolo_v9",
        class_labels=("License Plate",),
        default_conf_thresh=0.25,
    ),
    "yolo-v9-t-256-license-plate-end2end": DetectionModelSpec(
        url=f"{BASE_URL}/yolo-v9-t-256-license-plates-end2end.onnx",
        backend="yolo_v9",
        class_labels=("License Plate",),
        default_conf_thresh=0.25,
    ),
}

Detection models available through create_detector.