Motion detect fraction small area of frame

This commit is contained in:
proitlab committed 2026-07-10 06:28:53 +07:00
1 parent 9d9d5f903c
commit ff87201a76
2 files changed
+30 -6

No files matched your search

+13 -4
View File
@@ -138,11 +138,20 @@ CROSS_SNAPSHOT_CLEANUP_SEC=60
# --- Rate / performance ---
# Enable motion detection pre-filter: skip inference on frames with no movement
# (true/false, default: false). When enabled, frames below MOTION_THRESHOLD are
# skipped, saving NPU/CPU load.
# (true/false, default: false), saving NPU/CPU load. Motion is measured by the
# fraction of pixels that changed (localized-motion aware), NOT the whole-frame
# average, so an object entering the edge of the frame is detected immediately.
MOTION_DETECTION_ENABLED=false
# Mean absolute pixel difference threshold (0–255) to consider a frame as having
# motion. Lower = more sensitive. Default 5.0.
# Per-pixel intensity change (0-255) for a pixel to count as "moved". Lower = more
# sensitive to subtle movement. Default 25.
MOTION_PIXEL_DELTA=25
# Fraction of frame pixels (0-1) that must change to trigger inference. Lower =
# more sensitive / detects smaller or farther objects sooner. Default 0.002 (0.2%).
MOTION_MIN_AREA_FRAC=0.002
# Heartbeat: always run inference at least every N frames even with no detected
# motion, so a slow or barely-moving object is never missed for long. Default 15.
MOTION_HEARTBEAT_FRAMES=15
# (Deprecated) old whole-frame mean-difference threshold; no longer used.
MOTION_THRESHOLD=5.0
# Sliding window in seconds for computing the crossing rate (objects/minute)
RATE_WINDOW_SEC=60
+17 -2
View File
@@ -111,6 +111,14 @@ IS_LIVE = SOURCE.lower().startswith(("rtsp://", "http://"))
MOTION_DETECTION_ENABLED = os.getenv("MOTION_DETECTION_ENABLED", "false").lower() == "true"
MOTION_THRESHOLD = float(os.getenv("MOTION_THRESHOLD", "5.0"))
# Per-pixel intensity change (0-255) for a pixel to count as "moved".
MOTION_PIXEL_DELTA = int(os.getenv("MOTION_PIXEL_DELTA", "25"))
# Fraction of frame pixels that must change (0-1) to trigger inference. Small,
# so an object entering the edge of the frame is detected immediately.
MOTION_MIN_AREA_FRAC = float(os.getenv("MOTION_MIN_AREA_FRAC", "0.002"))
# Always run inference at least every N frames even if no motion (heartbeat), so a
# slow/stationary object is never missed for long.
MOTION_HEARTBEAT_FRAMES = int(os.getenv("MOTION_HEARTBEAT_FRAMES", "15"))
CROSS_FLASH_FRAMES = 12
POPUP_LIFETIME = 20
@@ -1078,6 +1086,7 @@ def run():
frame_idx = 0
inf_ms = 0.0
prev_gray = None
frames_since_infer = 0
video_writer = None
crossing_times = deque()
counter_in = 0
@@ -1138,15 +1147,21 @@ def run():
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
if prev_gray is not None:
diff = cv2.absdiff(gray, prev_gray)
mean_diff = cv2.mean(diff)[0]
skip_inference = mean_diff < MOTION_THRESHOLD
moved = int(np.count_nonzero(diff > MOTION_PIXEL_DELTA))
moved_frac = moved / diff.size
skip_inference = moved_frac < MOTION_MIN_AREA_FRAC
if frames_since_infer >= MOTION_HEARTBEAT_FRAMES:
skip_inference = False
prev_gray = gray
detections = []
if not skip_inference:
frames_since_infer = 0
inf_start = time.time()
detections = model(frame)
inf_ms = inf_ms * 0.9 + (time.time() - inf_start) * 1000 * 0.1
else:
frames_since_infer += 1
object_boxes_xyxy = []
object_scores = []