Enhance alert processing in camera stream
- Added debug print statements for camera IP configuration at load time. - Modified CAMERA_IPS initialization to correctly reference environment variables. - Adjusted YOLO_CONF value for improved detection sensitivity. - Refactored alert logic to accumulate pending alerts before saving, allowing for better management of alert metadata and image saving. - Implemented saving of annotated alerts with unique filenames to prevent collisions.main
parent
ea349663fd
commit
50ecbdcc50
|
|
@ -13,12 +13,18 @@ load_dotenv(override=True)
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
# Load-time debug for camera config (safe to leave; only prints on startup)
|
||||||
|
print(
|
||||||
|
"[Surveillance] camera_ip_1=" + str(os.getenv("camera_ip_1")) +
|
||||||
|
" camera_ip_2=" + str(os.getenv("camera_ip_2"))
|
||||||
|
)
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Configuration
|
# Configuration
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
USERNAME = os.getenv("username")
|
USERNAME = os.getenv("username")
|
||||||
PASSWORD = os.getenv("password")
|
PASSWORD = os.getenv("password")
|
||||||
CAMERA_IPS = [os.getenv(f"camera_ip_{i+1}") for i in range(1, 3)]
|
CAMERA_IPS = [os.getenv(f"camera_ip_{i}") for i in range(1, 3)]
|
||||||
CAMERAS = [
|
CAMERAS = [
|
||||||
{
|
{
|
||||||
"id": f"cam{i + 1}",
|
"id": f"cam{i + 1}",
|
||||||
|
|
@ -34,7 +40,7 @@ PROXIMITY_PX = 200 # max pixel distance to consider two people "together"
|
||||||
GROUP_TIME_THRESHOLD = 20 # seconds before an alert fires
|
GROUP_TIME_THRESHOLD = 20 # seconds before an alert fires
|
||||||
ALERT_COOLDOWN = 60 # seconds between successive alerts
|
ALERT_COOLDOWN = 60 # seconds between successive alerts
|
||||||
MIN_GROUP_SIZE = 2
|
MIN_GROUP_SIZE = 2
|
||||||
YOLO_CONF = 0.5
|
YOLO_CONF = 0.25
|
||||||
INFERENCE_DEVICE = 0
|
INFERENCE_DEVICE = 0
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
@ -249,8 +255,9 @@ def _process_stream():
|
||||||
for gid in stale:
|
for gid in stale:
|
||||||
del _group_trackers[gid]
|
del _group_trackers[gid]
|
||||||
|
|
||||||
# --- Alert logic ---
|
# --- Alert logic (mark + metadata; save after drawing overlays) ---
|
||||||
alert_this_frame = False
|
alert_this_frame = False
|
||||||
|
pending_alerts = [] # list of (gid, people_count, duration_seconds)
|
||||||
for gid, gdata in _group_trackers.items():
|
for gid, gdata in _group_trackers.items():
|
||||||
duration = gdata["last_seen"] - gdata["first_seen"]
|
duration = gdata["last_seen"] - gdata["first_seen"]
|
||||||
if duration >= GROUP_TIME_THRESHOLD and not gdata["alerted"]:
|
if duration >= GROUP_TIME_THRESHOLD and not gdata["alerted"]:
|
||||||
|
|
@ -258,21 +265,7 @@ def _process_stream():
|
||||||
gdata["alerted"] = True
|
gdata["alerted"] = True
|
||||||
alert_this_frame = True
|
alert_this_frame = True
|
||||||
_last_alert_time = now
|
_last_alert_time = now
|
||||||
|
pending_alerts.append((gid, gdata["member_count"], duration))
|
||||||
os.makedirs("alerts", exist_ok=True)
|
|
||||||
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
||||||
alert_path = f"alerts/alert_{ts}.jpg"
|
|
||||||
cv2.imwrite(alert_path, frame)
|
|
||||||
|
|
||||||
alert_info = {
|
|
||||||
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
|
||||||
"people": gdata["member_count"],
|
|
||||||
"duration": round(duration, 1),
|
|
||||||
"image": alert_path,
|
|
||||||
}
|
|
||||||
with lock:
|
|
||||||
state["alerts"].insert(0, alert_info)
|
|
||||||
state["alerts"] = state["alerts"][:50]
|
|
||||||
|
|
||||||
# --- Draw overlays ---
|
# --- Draw overlays ---
|
||||||
display = frame.copy()
|
display = frame.copy()
|
||||||
|
|
@ -308,6 +301,25 @@ def _process_stream():
|
||||||
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3,
|
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# --- Save annotated alerts ---
|
||||||
|
if pending_alerts:
|
||||||
|
os.makedirs("alerts", exist_ok=True)
|
||||||
|
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
|
for gid, people, duration in pending_alerts:
|
||||||
|
# Include group id to avoid collisions when multiple groups alert in one second.
|
||||||
|
alert_path = f"alerts/alert_{ts}_gid{gid}.jpg"
|
||||||
|
cv2.imwrite(alert_path, display)
|
||||||
|
|
||||||
|
alert_info = {
|
||||||
|
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
|
"people": people,
|
||||||
|
"duration": round(duration, 1),
|
||||||
|
"image": alert_path,
|
||||||
|
}
|
||||||
|
with lock:
|
||||||
|
state["alerts"].insert(0, alert_info)
|
||||||
|
state["alerts"] = state["alerts"][:50]
|
||||||
|
|
||||||
# --- Update shared state ---
|
# --- Update shared state ---
|
||||||
groups_json = []
|
groups_json = []
|
||||||
for gid, gi, gc in frame_group_data:
|
for gid, gi, gc in frame_group_data:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue