Oval Annotator

Draw elliptical footprints at the bottom of detected objects for ground-plane visualization.

Output
PixelFlow Oval Annotator

Overview

The oval() annotator draws elliptical arcs at the bottom center of each detection's bounding box. This creates a natural ground-plane footprint effect, ideal for spatial awareness, shadow effects, and tracking visualizations where you want to indicate object presence on the ground.

Python
pf.annotators.oval(image, detections)

Function Signature

Python
def oval(    image: np.ndarray,    detections: Detections,    thickness: Optional[int] = None,    start_angle: int = -45,    end_angle: int = 235,    colors: Optional[List[Tuple[int, int, int]]] = None) -> np.ndarray

Parameters

Parameter Type Default Description
image np.ndarray required Input image in BGR format. Modified in-place.
detections Detections required PixelFlow detections with bounding boxes.
thickness int or None None Line thickness in pixels. None = auto-adapt to image size.
start_angle int -45 Starting angle of ellipse arc in degrees.
end_angle int 235 Ending angle of ellipse arc in degrees.
colors List[tuple] or None None List of BGR colors. None = use default palette.

Returns:
np.ndarray - The input image with elliptical footprints drawn (same array, modified in-place).

Basic Usage

Python
import cv2import pixelflow as pffrom ultralytics import YOLO# Load image and run detectionimage = cv2.imread("pedestrians.jpg")model = YOLO("yolo11n.pt")results = model.predict(image)detections = pf.from_ultralytics(results)# Draw elliptical footprintsimage = pf.annotators.oval(image, detections)cv2.imshow("Result", image)cv2.waitKey(0)

How It Works

The ellipse is positioned and sized based on the bounding box:

  • Center: Bottom-center of the bounding box (x_center, y2)
  • Width: Matches the full width of the bounding box
  • Height: 25% of the width for natural ground-plane proportions
  • Arc: By default, draws bottom arc from -45° to 235° (~280°)
Markdown
     ┌─────────────────────┐     │                     │     │     Bounding Box    │     │                     │     │                     │     └──────────┬──────────┘                │ center point            ╭───┴───╮           ╱         ╲          (  ellipse  )    ← Footprint drawn here           ╲         ╱            ╰───────╯

Angle Control

The start_angle and end_angle parameters control which portion of the ellipse is drawn. Angles follow OpenCV convention:

Markdown
              90° (down)    180° ───────┼─────── 0° (right)    (left)      │             270° (up)
Python
# Default: bottom arc (-45° to 235°)image = pf.annotators.oval(image, detections)# Full ellipse (complete circle)image = pf.annotators.oval(image, detections, start_angle=0, end_angle=360)# Narrow bottom arc (subtle footprint)image = pf.annotators.oval(image, detections, start_angle=30, end_angle=150)# Top arc onlyimage = pf.annotators.oval(image, detections, start_angle=180, end_angle=360)
Output
Default arc (0° to 360°)
Output
Full ellipse (180° to 360°)

Styling Options

Custom Thickness

Python
# Thin lines for subtle effectimage = pf.annotators.oval(image, detections, thickness=1)# Thick lines for emphasisimage = pf.annotators.oval(image, detections, thickness=4)

Custom Colors

Python
# Custom colors (BGR format)custom_colors = [    (0, 255, 255),   # Cyan    (255, 0, 255),   # Magenta    (255, 255, 0),   # Yellow]image = pf.annotators.oval(image, detections, colors=custom_colors)

Common Patterns

Pedestrian Tracking Visualization

Combine oval footprints with labels to show tracked people with ground-plane indicators:

Python
# Tracking visualization with footprintsimage = pf.annotators.oval(image, detections)image = pf.annotators.label(image, detections, "ID: {tracker_id}")

Alternative to Bounding Boxes

Use ovals instead of boxes for a cleaner, less cluttered visualization:

Python
# Clean visualization without boxesimage = pf.annotators.oval(image, detections)image = pf.annotators.label(image, detections, position='top_center')

Combined with Boxes

Python
# Full visualization: box + oval footprint + labelimage = pf.annotators.box(image, detections)image = pf.annotators.oval(image, detections)image = pf.annotators.label(image, detections)

Shadow Effect

Create a shadow-like effect with dark colored full ellipses:

Python
# Dark shadow-like footprintimage = pf.annotators.oval(    image, detections,    start_angle=0,    end_angle=360,    colors=[(50, 50, 50)],  # Dark gray    thickness=2)image = pf.annotators.box(image, detections)

Notes

  • In-place modification: The input image is modified directly. Use image.copy() if you need the original preserved.
  • Anti-aliased: Uses cv2.LINE_AA for smooth curves.
  • Adaptive sizing: Thickness automatically adapts to image resolution when not specified.
  • Proportions: Ellipse height is fixed at 25% of width for natural ground-plane appearance.
  • Color cycling: If more detections than colors, colors will cycle through the list.

See Also

  • box() - Draw rectangular bounding boxes
  • anchors() - Draw anchor points on detections
  • label() - Add text labels to detections