Zone Counter
DeGirum Tools API Reference Guide. Count objects present in polygonal zones.
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=TrueCompatible with ObjectTracker analyzer upstream
Results structure matches ZoneCounter for easy migration
Configuration Options
zones: Dictionary mapping zone names to polygonsclass_list: Optional list of class labels to counttriggering_position: Anchor point or IoPA-based triggeringtimeout_frames: Hysteresis threshold for symmetric entry/exit smoothingenable_zone_events: Generate zone-level eventsshow_overlay: Visual annotationsper_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 + 1consecutive 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=Trueif > 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:
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:
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:
result
Inference result to analyze
required
annotate(result, ...)
annotate(result, image)
Draw zone overlays and counts on the image.
Parameters:
result
Inference result with zone data
required
image
ndarray
Image to annotate
required
Returns:
ndarray
Annotated image
window_attach(win_name)
window_attach(win_name)
Attach an OpenCV window for interactive polygon editing.
Parameters:
win_name
str
Name of the OpenCV window to attach to
required
Last updated
Was this helpful?

