Count in Zone¶
With Supervision, you can count objects inside a zone in an image or video, this guide counts cars in a traffic video. upstream notebook.
Start by downloading the source video:
Initialize a Model and Load Video¶
Use RF-DETR through Roboflow Inference with its pretrained COCO checkpoint, then load the source video.
The model processes each frame during inference. A shared color palette ensures consistent zone coloring throughout the output video.
import numpy as np
import supervision as sv
from inference import get_model
from supervision.assets import VideoAssets, download_assets
model = get_model(model_id="rfdetr-medium")
VIDEO = download_assets(VideoAssets.VEHICLES_2)
colors = sv.ColorPalette.DEFAULT
Calculate Coordinates¶
Define polygons in source-video pixel coordinates. These coordinates match the sample video:
polygons = [
np.array([[718, 595], [927, 592], [851, 1062], [42, 1059]]),
np.array([[987, 595], [1199, 595], [1893, 1056], [1015, 1062]]),
]
For another video, draw them with the PolygonZone web utility; see the upstream walkthrough.
Define Zones¶
Create a PolygonZone for each polygon, pairing it with a
PolygonZoneAnnotator for the zone overlay and a BoxAnnotator for detection
boxes. Each zone determines which detections fall inside its boundaries.
Note that counts represent per-frame occupancy, not unique visitors across all frames.
import supervision as sv
from ml_pipes.supervision import BoxAnnotator, PolygonZoneAnnotator
zones = [sv.PolygonZone(polygon=polygon) for polygon in polygons]
zone_annotators = [
PolygonZoneAnnotator(
zone=zone,
color=colors.by_idx(index),
thickness=4,
text_thickness=8,
text_scale=4,
)
for index, zone in enumerate(zones)
]
box_annotators = [
BoxAnnotator(
color=colors.by_idx(index),
thickness=4,
)
for index in range(len(polygons))
]
zones = [sv.PolygonZone(polygon=polygon) for polygon in polygons]
zone_annotators = [
sv.PolygonZoneAnnotator(
zone=zone,
color=colors.by_idx(index),
thickness=4,
text_thickness=8,
text_scale=4,
)
for index, zone in enumerate(zones)
]
box_annotators = [
sv.BoxAnnotator(
color=colors.by_idx(index),
thickness=4,
)
for index in range(len(polygons))
]
Run Inference¶
Detect objects in each frame and filter the detections by zone. Annotation needs both the source frame and its detections to draw the boxes and zone counts on the image.
from ml_pipes.core import Pipeline
from ml_pipes.standard import Pick, Recall, Select, Store
from ml_pipes.supervision import Detections, TriggerZone
from ml_pipes.supervision.inference import RoboflowInference
pipeline = Pipeline(
[
Store("source_frame"),
RoboflowInference(model_id="rfdetr-medium"),
Select(0),
Detections.FromInference(),
Store("detections"),
TriggerZone(zones[0]),
Recall("source_frame", prepend=True),
box_annotators[0],
zone_annotators[0],
Pick(0),
Store("first_zone_scene"),
Recall("detections", prepend=True),
Select(0),
TriggerZone(zones[1]),
Recall("first_zone_scene", prepend=True),
box_annotators[1],
zone_annotators[1],
Pick(0),
]
)
def process_frame(frame: np.ndarray, _: int) -> np.ndarray:
return pipeline(frame)
sv.process_video(source_path=VIDEO, target_path="result.mp4", callback=process_frame)
def process_frame(frame: np.ndarray, i) -> np.ndarray:
results = model.infer(frame)[0]
detections = sv.Detections.from_inference(results)
for zone, zone_annotator, box_annotator in zip(
zones, zone_annotators, box_annotators
):
mask = zone.trigger(detections=detections)
detections_filtered = detections[mask]
frame = box_annotator.annotate(scene=frame, detections=detections_filtered)
frame = zone_annotator.annotate(scene=frame)
return frame
sv.process_video(source_path=VIDEO, target_path="result.mp4", callback=process_frame)
Here is an example of output:
Author¶
- Piotr Skalski — Computer Vision Engineer, Roboflow