Zone Counter

DeGirum Tools API Reference Guide. Count objects present in polygonal zones.

circle-info

This API Reference is based on DeGirum Tools version 0.25.1.

Zone Counter Analyzer Module Overview

This module provides a zone counting analyzer (ZoneCounter) with support for both traditional list-based zones and named zones (dictionary-based). It features clean separation of concerns and a user-friendly API.

Key Features

  • Named Zones: Use descriptive names instead of numeric indices

  • Clean Architecture: Separation of geometry (spatial) and state (temporal) logic

  • Zone Events: Track entry, exit, occupied, and empty events per zone

  • All ZoneCounter Features: Supports all triggering methods, tracking, timeouts, etc.

  • Better Maintainability: Smaller, focused components that are easier to test and extend

Architecture

The implementation separates concerns into focused components:

  • _ZoneGeometry: Handles spatial logic - polygon shapes, masks, and triggering

  • _ZoneState: Handles temporal logic - object tracking, timeouts, occupancy state

  • ZoneCounter: Orchestrates the components and generates events

Typical Usage

from degirum_tools.analyzers import ZoneCounter

counter = ZoneCounter(
    zones={
        "entrance": entrance_polygon,
        "parking_spot_1": spot1_polygon,
        "exit_area": exit_polygon,
    },
    use_tracking=True,
    timeout_frames=3,  # Hysteresis threshold
    enable_zone_events=True,
)

model.attach_analyzers(counter)
result = model(frame)

# Access named zone counts
print(result.zone_counts)  # {"entrance": {...}, "parking_spot_1": {...}, ...}

# Access zone events
for event in result.zone_events:
    print(f"{event['event_type']} in {event['zone_id']} at {event['timestamp']}")

Zone Events

When enable_zone_events=True, the analyzer generates four types of events:

  • zone_entry: Track becomes established in zone (after timeout_frames + 1 consecutive in-zone detections)

  • zone_exit: Track exits zone (hysteresis counter reaches 0)

  • zone_occupied: Zone transitions from empty to occupied (when first track becomes established)

  • zone_empty: Zone transitions from occupied to empty (after all tracks exit)

Event structure:

Integration Notes

  • Requires detection results with bounding boxes

  • Zone events require use_tracking=True

  • Compatible with ObjectTracker analyzer upstream

  • Results structure matches ZoneCounter for easy migration

Configuration Options

  • zones: Dictionary mapping zone names to polygons

  • class_list: Optional list of class labels to count

  • triggering_position: Anchor point or IoPA-based triggering

  • timeout_frames: Hysteresis threshold for symmetric entry/exit smoothing

  • enable_zone_events: Generate zone-level events

  • show_overlay: Visual annotations

  • per_class_display: Show per-class counts

Hysteresis Smoothing

The analyzer uses symmetric hysteresis for stable zone presence detection:

  • timeout_frames: Controls the hysteresis threshold. Objects need timeout_frames + 1 consecutive in-zone detections to become "established" (counted). The internal counter increments when in zone, decrements when outside or missing, and is clamped to [0, timeout_frames + 1]. Objects exit when the counter reaches 0.

  • Symmetric behavior: The same threshold applies for both entry and exit, providing smooth transitions without flickering. Brief departures don't reset the counter, and brief appearances don't immediately establish presence.

  • Default: 0 (immediate entry/exit on first detection). Requires use_tracking=True if > 0.

Classes

ZoneCounter

ZoneCounter

Bases: ResultAnalyzerBase

Analyzer that counts objects inside user-defined polygonal zones.

This analyzer integrates with PySDK inference results to determine whether detected or tracked objects lie within user-defined polygon zones. It supports per-class counting, object tracking with symmetric hysteresis (timeout_frames) for entry/exit smoothing, zone events, and interactive editing.

Backward compatible with old ZoneCounter API (list of zones) while supporting new dict-based named zones interface.

Attributes:

Name
Type
Description

key_in_zone

Key for zone presence flags in result objects

key_frames_in_zone

Key for frame counts in result objects

key_time_in_zone

Key for time-in-zone in result objects

key_zone_events

Key for zone events list in result objects

ZoneCounter Methods

__init__(zones=None, ...)

__init__(zones=None, *, count_polygons=None, class_list=None, per_class_display=False, triggering_position=AnchorPoint.BOTTOM_CENTER, bounding_box_scale=1.0, iopa_threshold=0.0, use_tracking=False, timeout_frames=0, enable_zone_events=False, window_name=None, show_overlay=True, show_inzone_counters=None, annotation_color=None, annotation_line_width=None)

Initialize ZoneCounter.

Parameters:

Name
Type
Description
Default

zones

Union[Dict[str, ndarray], List[ndarray], ndarray, None]

Dict mapping zone names to polygons (new style) OR list of polygons (old style backward compat)

None

class_list

Optional[List[str]]

List of class labels to count (None = all classes)

None

per_class_display

bool

Show per-class counts separately

False

triggering_position

Optional[Union[List[AnchorPoint], AnchorPoint]]

Anchor point(s) or None for IoPA

BOTTOM_CENTER

bounding_box_scale

float

Scale factor for bboxes (greater than 0, up to 1)

1.0

iopa_threshold

Union[float, List[float]]

IoPA threshold (single value or list per zone)

0.0

use_tracking

bool

Enable object tracking

False

timeout_frames

int

Hysteresis threshold for zone presence (requires tracking if > 0). Objects need timeout_frames + 1 consecutive in-zone detections to become established (counted), and the counter decrements when outside/missing. Objects exit when counter reaches 0.

0

enable_zone_events

bool

Generate zone-level events (requires tracking)

False

window_name

Optional[str]

OpenCV window name for interactive polygon editing (None = disabled)

None

show_overlay

bool

Draw zone overlays

True

show_inzone_counters

Optional[str]

Show presence counters ('time', 'frames', 'all', None)

None

annotation_color

Optional[tuple]

RGB color for overlays (None = auto)

None

annotation_line_width

Optional[int]

Line width for overlays (None = auto)

None

analyze(result)

analyze(result)

Analyze inference result and update zone counts and events.

Parameters:

Name
Type
Description
Default

result

Inference result to analyze

required

annotate(result, ...)

annotate(result, image)

Draw zone overlays and counts on the image.

Parameters:

Name
Type
Description
Default

result

Inference result with zone data

required

image

ndarray

Image to annotate

required

Returns:

Type
Description

ndarray

Annotated image

window_attach(win_name)

window_attach(win_name)

Attach an OpenCV window for interactive polygon editing.

Parameters:

Name
Type
Description
Default

win_name

str

Name of the OpenCV window to attach to

required

Last updated

Was this helpful?