Zone Counter

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

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?