M
Matthew Diakonov
11 min read
The part between the model and the alert

Object detection is not monitoring. The two filters after the model are what decide whether you get an alert.

Read the current explainer pages and the story always stops in the same place: a camera captures a frame, a neural network labels it, an alert fires, false alarms go down by ninety percent. The mechanism that ninety-percent number is pointing at is never shown. This page is about that mechanism, the two concrete filters between the detection and the alert on a Cyrano unit, and the four event classes that are defined by those filters instead of by the model.

See the zone files on a live unit
4.9from 50+ properties
Zone polygons live in plain JSON on the unit, not inside camera firmware
Dwell thresholds are a text edit, not a model retrain
Four concrete event classes, each defined by (zone, dwell, predicate)
Pipeline runs locally; a WAN outage does not pause filtering

What the current explainer pages cover, and what they leave out

Read the top ten explainer pages on this topic back to back and the structure is nearly identical: a paragraph on computer vision and machine learning, a list of object classes the system can recognize (person, vehicle, package, bag), a line about real-time processing, a claim that AI reduces false alarms by up to ninety percent, and a feature table. The mechanism behind the false alarm number is never shown. The words “zone” and “dwell” appear rarely, and when they do they appear as features in a bullet list rather than as the filter stages they actually are.

The reason that gap exists is that the detection model is easy to demo and the filter pipeline is not. A video of a model drawing bounding boxes on a parking lot looks like product. A text file that says “mailroom-door fires after 22:00 local with a 0-second dwell” does not. The filter pipeline is the part that actually makes an AI camera monitoring product livable for a property manager, and it is the part that gets skipped in the writing.

The rest of this page is that file, that rule, and the code that reads it.

The pipeline, end to end, for one frame

Here is the full shape of the decision from a single captured frame to a single emitted event. The detector is one step of five; the zone check and the dwell check are what actually earn their keep.

one frame through the cyrano monitoring pipeline

HDMI captureLayout routerDetectorZone filterDwell filterAlert1920x1080 compositetile: mailroom-01person @ (0.73, 0.55)centroid inside mailroom-door?yes, armed after 22:00accumulate dwell for track_idheld 1.2s >= 0s thresholdpre_action_zone_entry

Where signal survives and where noise dies

At a Class C multifamily property with 16 cameras, the raw person detector fires many hundreds of times a day per camera. Walking through the parking lot. Crossing the lobby on the way to the elevator. Sitting on the steps with a takeout bag. All of them are real detections. Almost none are events an operator should see. The numbers below are the ones we watch in the field.

detections survive the zone filter, then survive the dwell filter

Raw person detections
Raw vehicle detections
Raw package detections
Zone + dwell filter
pre_action_zone_entry
loitering_dwell_exceeded
tailgate_detected
package_dwell_exceeded
0raw person detections per camera per day (median)
0candidates surviving the zone filter
0events surviving the dwell filter
0model retrains required to change any of this

Over a seven-day window on one tracked property, 0% of raw person detections never crossed an armed polygon, and of the ones that did, 0% failed their dwell threshold and were discarded before any outbound call was attempted.

The zone file, on disk, for one camera

Every camera on a Cyrano unit has a file at /var/lib/cyrano/zones/<camera_name>.json that defines its zones. Polygons are in normalized (0, 1) image coordinates so a rule drawn once survives a grid-layout change on the DVR. Editing the file is a text edit. Reload is a signal, not a deploy. This is what an operator actually touches when a property starts generating too many alerts.

/var/lib/cyrano/zones/mailroom-01.json

A dwell threshold that reads 90 seconds today can read 120 seconds tomorrow by changing one number in this file and sending SIGHUP to the filter process. The detection model is untouched.

The filter loop, in about 35 lines of Python

This runs once per frame, after the detector returns its boxes. The detector does not know about zones, dwell, or event classes; the filter loop does. Per-track, per-zone dwell accumulators live in a single in-memory map that periodically flushes to disk, so the pipeline survives a process restart without losing the dwell state mid-event.

cyrano/monitoring/filter_pipeline.py

The four event classes, defined without the detection model

Every event Cyrano delivers to an operator falls into one of four classes. Each class is a triple: a zone shape, a dwell threshold, and a predicate. The detection model is the same underneath all four. This is what makes “AI camera monitoring” a system and not a demo.

pre_action_zone_entry

Zero-second dwell. Fires the moment a track enters an armed polygon such as a pool gate after 22:00 or a dock door on weekends. Used where any presence is a policy violation.

loitering_dwell_exceeded

Default dwell 90s, editable per camera. Fires when a person track accumulates the threshold inside a loitering polygon during its arming schedule. The single most tunable class.

tailgate_detected

Dwell measured between two tracks, not within one. Fires when two person tracks cross an ingress polygon within 1.2 seconds of each other without an intermediate badge event.

package_dwell_exceeded

900-second dwell on a 'package' detection inside a package zone. Fires when a delivery has sat there too long without being picked up. Zone is armed 24/7; the clock is the filter.

What a real shift looks like in the filter log

Below is a slice of the monitoring log from one overnight shift on a 16-camera property. You can see the detector firing constantly, most detections dying at the zone boundary, a few crossing into an armed polygon, and only the subset past the dwell threshold producing an actual event. Nothing in this log is edited.

cyrano monitoring log, overnight shift, one property
3 / ~19k

Across one overnight shift on a 16-camera property, the detector fired on roughly 19,000 frame regions. The zone filter dropped that to 182 candidate track-zone pairs. The dwell filter dropped that to 3 emitted events. Those three are what the operator actually saw.

Cyrano field log, overnight shift on a multifamily property

The three pieces of state that have to live on the unit

A filter pipeline that decides what becomes an alert cannot live anywhere except with the frames. Network round-trips break the dwell timer; cloud storage of polygons breaks the offline case. So the state is local, and it is plain.

Where the monitoring state lives

1

Zone polygons

/var/lib/cyrano/zones/<camera_name>.json. One file per camera. Normalized coordinates so a grid-layout change on the DVR does not break the rule.

2

Dwell state

/var/lib/cyrano/meta/dwell_state. Per-track, per-zone accumulators, periodically flushed. Survives a process restart so a 900-second package timer does not reset when systemd bounces the worker.

3

Arming schedules

Encoded directly in the zone file alongside each polygon. A zone is armed by time of day and day of week; no external cron, no cloud flag.

The two definitions of AI camera monitoring, side by side

The two columns below are the same detection model producing very different operator experiences. What changes between them is not the model; it is the presence of the post-detection filter pipeline.

FeatureObject detection with a dashboardMonitoring (Cyrano)
What the model doesClassify objects per frameClassify objects per frame
What the system does with thatPush every detection to an alert feedRun zone + dwell filters, emit one of four event classes
Where zone rules liveInside camera firmware or cloud config/var/lib/cyrano/zones/<camera>.json on the unit
How dwell is tunedVendor support ticket, or not at allEdit one integer in a JSON file, SIGHUP the worker
Track identity across framesImplicit; per-vendor, often uuidtrack_id keyed per camera, carried into the dwell map
Operator's daily alert volumeOften hundreds per property, ignored within a weekSingle-digit events per camera per day by design
What proves the filter ranFaith in the vendor's false-alarm claimThe log line showing dwell held, threshold met, event emitted

The uncopyable part

You can open the file that defines the alert.

On a Cyrano unit, the rules that turn a detection into an alert are not inside a model, inside a firmware, or inside a cloud console. They are in /var/lib/cyrano/zones as plain JSON, one file per camera, with polygons in normalized coordinates, a dwell threshold in seconds, an arming schedule, and an event class. If an alert fired, you can trace it back to the line in the file. If an alert did not fire, you can trace that back to the same line. That is what separates a monitoring product from a detection product with marketing attached.

Things the filter pipeline quietly suppresses

Resident walking to the mailroom
Delivery driver crossing lobby
Cat in the parking lot
Reflection on a wet sidewalk
Landscaper blowing leaves past a gate
Shopping cart drifting in wind
Tenant smoking near door during day
Package being picked up in under 15 min
Person walking past, not into, a zone
Raccoon at 3 a.m.

Every one of these is a real detection. None of them cross both the zone test and the dwell threshold, so none of them reach the operator. That is the content of the ninety-percent-reduction claim, made legible.

What to ask a vendor to prove they have a monitoring product

The fastest way to separate a detection demo from a monitoring system is to ask for the four artifacts the filter pipeline has to produce. A vendor that ships object detection with a dashboard on top cannot show them. A vendor that ships monitoring has them on the unit.

Ask for the zone file for one camera. Ask for the dwell threshold on the loitering class and how to change it. Ask for the unique identifier that binds a track across consecutive frames. Ask what happens to the dwell state when the worker restarts mid-event. Four concrete answers, or no monitoring claim.

On Cyrano those answers are /var/lib/cyrano/zones/<camera_name>.json, an integer inside that file named dwell_seconds, a per-camera track_id assigned by the tracker between consecutive frames, and a periodic flush to /var/lib/cyrano/meta/dwell_state that survives systemd bouncing the process.

See the zone and dwell files on a live property

A 15-minute call. We open /var/lib/cyrano/zones/ on a production unit with you, tweak a dwell threshold live, and watch the filter log stop emitting the class you just relaxed.

AI camera monitoring security: frequently asked questions

What does 'AI camera monitoring security' actually mean if every explainer defines it the same way?

Almost every top-ranked article on this phrase stops at the detection model: the camera sees a frame, a neural network classifies it as 'person' or 'vehicle' or 'package,' and an alert fires. That is object detection, not monitoring. Monitoring is the second stage, the one that decides whether a given detection deserves a human's attention. On a production system like Cyrano that second stage is a zone polygon (is the detection inside a region I care about right now) plus a dwell timer (has it stayed inside the region long enough to mean something), and the event class emitted to the operator depends entirely on those two pieces of state, not on the model itself.

Why does the zone polygon matter more than the object class?

Because a person in a parking lot during business hours is not an event, but the same person at the same pixel coordinate at 2 a.m. behind the loading dock is. The detection model does not care about time or location; it just returns a bounding box and a label. A zone polygon is a per-camera JSON file that names a region (mailroom-door, package-shelf, pool-gate-after-hours) and couples it to an arming schedule and a dwell threshold. A detection only becomes a candidate event when its bounding box centroid falls inside an armed polygon. That filter alone cuts the vast majority of noise detections a model emits over a 24-hour window, and it costs zero extra inference compute because it runs on the coordinates the model already produced.

What is a 'dwell timer' in this context and why is it separate from the zone check?

A dwell timer is a per-track, per-zone counter that measures how long a specific detection has remained inside a specific zone. The zone check is a single-frame geometry test; the dwell timer is a time-series test. It is the dwell timer that distinguishes a person walking through the frame (0.8 seconds in the zone) from a person loitering (90 seconds in the zone). The two tests answer different questions: the zone says 'is this detection in the right place' and the dwell says 'has it been there long enough to matter.' Combine them and you can describe every real surveillance event without retraining the model. On Cyrano the dwell state lives at /var/lib/cyrano/meta/dwell_state so it survives a process restart.

What are the four event classes Cyrano actually emits, and how are they defined?

pre_action_zone_entry fires the moment a new track enters an armed zone with a 0-second dwell threshold, used for hard perimeters like pool gates after hours. loitering_dwell_exceeded fires when a track has accumulated 90 seconds inside a loitering zone during its arming schedule. tailgate_detected fires when two distinct tracks cross an ingress zone within 1.2 seconds of each other without an intermediate badge event. package_dwell_exceeded fires when an object classified as 'package' sits in a package zone for 900 seconds without being picked up. All four are defined as (zone, dwell threshold, predicate); the detection model does not change between them.

How is this different from what a Verkada, Rhombus, or Ring camera does?

Consumer and enterprise smart cameras ship with pre-baked zone rules inside the camera firmware, and changing them is either impossible or requires a firmware update. The filter parameters are hidden. A Cyrano unit reads zone polygons and dwell thresholds from plain JSON files on local disk, so an operator who finds that 90 seconds of loitering dwell is producing too many false positives at a specific property can bump the threshold to 120 seconds, reload the config, and the change takes effect on the next detection. No model retrain, no cloud round-trip, no firmware push.

Where does the often-quoted '90 percent false alarm reduction' number actually come from?

It is a marketing aggregate, not a measured quantity on any specific system. What reduces false alarms is not 'AI'; it is the combination of a decent detector and a tight post-detection filter pipeline. On a Cyrano unit the quantity we can measure is events-per-day per camera. On a 24-hour window at a Class C multifamily property, a raw 'person' detector fires on the order of 800 to 1,500 times per camera. After the zone filter that drops into low tens. After the dwell filter it drops into low single digits. The ratio matters less than the absolute rate, because what an operator cares about is 'can I actually read every alert that arrived today,' and the answer has to be yes.

Can a Cyrano unit run monitoring without a cloud connection at all?

Yes. Every piece of state the filter pipeline needs (model weights, per-camera zone polygons, dwell thresholds, arming schedules, the dwell counter file) lives on the unit. A full WAN outage does not stop detection or filtering; it only blocks the outbound alert. Events that fire during the outage are written to an append-only NDJSON outbox file and delivered in order when the link returns. That behavior is covered in detail on the AI edge page.

Where are the zone polygons stored and what do they look like?

One JSON file per camera at /var/lib/cyrano/zones/<camera_name>.json. Each file is a list of named zones; each zone has a polygon in normalized (0,1) image coordinates, a dwell threshold in seconds, an arming schedule (for example 'after 22:00 local' or 'weekends only'), and an event_class to emit. Because the format is plain JSON and the path is stable, a field technician can open the file on a USB keyboard and see the exact rules the unit is evaluating. Editing a polygon is a text edit, not a support ticket.

Does this approach work on an HDMI composite coming out of a legacy DVR?

Yes, and that is the whole point of plugging into HDMI. The Cyrano unit decodes the DVR's on-screen composite (for example a 4x4 grid) into tile coordinates, runs the detector over the entire 1920x1080 frame once, and then attributes each detection to a camera based on which tile its centroid landed in. The zone polygons for each camera are expressed in the tile's local coordinate frame, so a polygon drawn on mailroom-01 stays on mailroom-01 even if the grid layout changes from 2x2 to 4x4 later; only the tile mapping changes, not the filter rules.

What should I ask a vendor to prove their AI camera monitoring product is more than object detection?

Four questions. Where are the per-camera zone rules stored, and can I read them. How is the dwell threshold set for each event class, and can I change it without a model retrain. What is the unique identifier used to dedupe a single track across consecutive frames. How does the system behave when the upstream link goes down for six hours. A vendor that cannot answer those four with a specific file path, a specific integer, a specific dedupe key, and a specific buffering behavior is shipping object detection with a dashboard on top, not a monitoring system.

🛡️CyranoEdge AI Security for Apartments
© 2026 Cyrano. All rights reserved.

How did this page land for you?

React to reveal totals

Comments ()

Leave a comment to see what others are saying.

Public and anonymous. No signup.