Motion detect fraction small area of frame
This commit is contained in:
1 parent
9d9d5f903c
commit
ff87201a76
2 files changed
+30
-6
No files matched your search
+13
-4
@@ -138,11 +138,20 @@ CROSS_SNAPSHOT_CLEANUP_SEC=60
|
|||||||
|
|
||||||
# --- Rate / performance ---
|
# --- Rate / performance ---
|
||||||
# Enable motion detection pre-filter: skip inference on frames with no movement
|
# Enable motion detection pre-filter: skip inference on frames with no movement
|
||||||
# (true/false, default: false). When enabled, frames below MOTION_THRESHOLD are
|
# (true/false, default: false), saving NPU/CPU load. Motion is measured by the
|
||||||
# skipped, saving NPU/CPU load.
|
# 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
|
MOTION_DETECTION_ENABLED=false
|
||||||
# Mean absolute pixel difference threshold (0–255) to consider a frame as having
|
# Per-pixel intensity change (0-255) for a pixel to count as "moved". Lower = more
|
||||||
# motion. Lower = more sensitive. Default 5.0.
|
# 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
|
MOTION_THRESHOLD=5.0
|
||||||
# Sliding window in seconds for computing the crossing rate (objects/minute)
|
# Sliding window in seconds for computing the crossing rate (objects/minute)
|
||||||
RATE_WINDOW_SEC=60
|
RATE_WINDOW_SEC=60
|
||||||
|
|||||||
+17
-2
@@ -111,6 +111,14 @@ IS_LIVE = SOURCE.lower().startswith(("rtsp://", "http://"))
|
|||||||
|
|
||||||
MOTION_DETECTION_ENABLED = os.getenv("MOTION_DETECTION_ENABLED", "false").lower() == "true"
|
MOTION_DETECTION_ENABLED = os.getenv("MOTION_DETECTION_ENABLED", "false").lower() == "true"
|
||||||
MOTION_THRESHOLD = float(os.getenv("MOTION_THRESHOLD", "5.0"))
|
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
|
CROSS_FLASH_FRAMES = 12
|
||||||
POPUP_LIFETIME = 20
|
POPUP_LIFETIME = 20
|
||||||
@@ -1078,6 +1086,7 @@ def run():
|
|||||||
frame_idx = 0
|
frame_idx = 0
|
||||||
inf_ms = 0.0
|
inf_ms = 0.0
|
||||||
prev_gray = None
|
prev_gray = None
|
||||||
|
frames_since_infer = 0
|
||||||
video_writer = None
|
video_writer = None
|
||||||
crossing_times = deque()
|
crossing_times = deque()
|
||||||
counter_in = 0
|
counter_in = 0
|
||||||
@@ -1138,15 +1147,21 @@ def run():
|
|||||||
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||||
if prev_gray is not None:
|
if prev_gray is not None:
|
||||||
diff = cv2.absdiff(gray, prev_gray)
|
diff = cv2.absdiff(gray, prev_gray)
|
||||||
mean_diff = cv2.mean(diff)[0]
|
moved = int(np.count_nonzero(diff > MOTION_PIXEL_DELTA))
|
||||||
skip_inference = mean_diff < MOTION_THRESHOLD
|
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
|
prev_gray = gray
|
||||||
|
|
||||||
detections = []
|
detections = []
|
||||||
if not skip_inference:
|
if not skip_inference:
|
||||||
|
frames_since_infer = 0
|
||||||
inf_start = time.time()
|
inf_start = time.time()
|
||||||
detections = model(frame)
|
detections = model(frame)
|
||||||
inf_ms = inf_ms * 0.9 + (time.time() - inf_start) * 1000 * 0.1
|
inf_ms = inf_ms * 0.9 + (time.time() - inf_start) * 1000 * 0.1
|
||||||
|
else:
|
||||||
|
frames_since_infer += 1
|
||||||
|
|
||||||
object_boxes_xyxy = []
|
object_boxes_xyxy = []
|
||||||
object_scores = []
|
object_scores = []
|
||||||
|
|||||||
Reference in new issue
Block a user