Enhance alert display and processing in camera stream

- Implemented live overlays to indicate alerting groups and their details.
- Updated person box annotations to reflect alert status with color coding.
- Improved saving of annotated alerts by including group-specific information and unique filenames.
- Added visual indicators for alert groups, including group size and duration.
main
bahawal.baloch 2026-04-02 16:20:16 +05:00
parent 50ecbdcc50
commit a1da64e017
1 changed files with 85 additions and 5 deletions

View File

@ -270,12 +270,34 @@ def _process_stream():
# --- Draw overlays --- # --- Draw overlays ---
display = frame.copy() display = frame.copy()
for x1, y1, x2, y2, conf in person_boxes: pending_gid_set = {gid for gid, _, _ in pending_alerts}
cv2.rectangle(display, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) alert_person_indices = set()
for gid, grp_indices, _gc in frame_group_data:
if gid in pending_gid_set:
alert_person_indices.update(grp_indices)
# Live overlay: mark any person that belongs to any alerting group.
if pending_alerts:
max_people = max(people for _gid, people, _dur in pending_alerts)
max_dur = max(dur for _gid, _people, dur in pending_alerts)
cv2.putText(
display,
f"ALERT: {len(pending_alerts)} group(s) | {max_people} people | {int(max_dur)}s",
(12, 32),
cv2.FONT_HERSHEY_SIMPLEX,
0.8,
(0, 0, 255),
3,
)
for idx, (x1, y1, x2, y2, conf) in enumerate(person_boxes):
is_alert_person = idx in alert_person_indices
box_color = (0, 0, 255) if is_alert_person else (0, 255, 0)
cv2.rectangle(display, (int(x1), int(y1)), (int(x2), int(y2)), box_color, 2)
cv2.putText( cv2.putText(
display, f"{conf:.0%}", display, f"{conf:.0%}",
(int(x1), int(y1) - 6), (int(x1), int(y1) - 6),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2, cv2.FONT_HERSHEY_SIMPLEX, 0.5, box_color, 2,
) )
for gid, grp_indices, gc in frame_group_data: for gid, grp_indices, gc in frame_group_data:
@ -301,14 +323,72 @@ 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 --- # --- Save annotated alerts (separate per group) ---
if pending_alerts: if pending_alerts:
os.makedirs("alerts", exist_ok=True) os.makedirs("alerts", exist_ok=True)
ts = datetime.now().strftime("%Y%m%d_%H%M%S") ts = datetime.now().strftime("%Y%m%d_%H%M%S")
frame_group_by_id = {gid: (grp_indices, gc) for gid, grp_indices, gc in frame_group_data}
for gid, people, duration in pending_alerts: for gid, people, duration in pending_alerts:
grp_indices, gc = frame_group_by_id.get(gid, (None, None))
if grp_indices is None:
continue
alert_display = frame.copy()
alert_person_set = set(grp_indices)
# Header annotation for this specific alert group.
cv2.putText(
alert_display,
f"ALERT GROUP {gid} | {people} people | {int(duration)}s",
(12, 32),
cv2.FONT_HERSHEY_SIMPLEX,
0.9,
(0, 0, 255),
3,
)
# Draw only the person boxes relevant to this group.
for idx, (x1, y1, x2, y2, conf) in enumerate(person_boxes):
is_alert_person = idx in alert_person_set
box_color = (0, 0, 255) if is_alert_person else (0, 255, 0)
cv2.rectangle(alert_display, (int(x1), int(y1)), (int(x2), int(y2)), box_color, 2)
cv2.putText(
alert_display,
f"{conf:.0%}",
(int(x1), int(y1) - 6),
cv2.FONT_HERSHEY_SIMPLEX,
0.5,
box_color,
2,
)
# Draw only the circle/label for this group.
radius = int(PROXIMITY_PX * 0.6)
cv2.circle(alert_display, (int(gc[0]), int(gc[1])), radius, (0, 0, 255), 2)
cv2.putText(
alert_display,
f"Group: {len(grp_indices)} | {duration:.0f}s",
(int(gc[0]) - 70, int(gc[1]) - radius - 10),
cv2.FONT_HERSHEY_SIMPLEX,
0.55,
(0, 0, 255),
2,
)
cv2.putText(
alert_display,
"ALERT",
(int(gc[0]) - 35, int(gc[1]) + radius + 25),
cv2.FONT_HERSHEY_SIMPLEX,
0.8,
(0, 0, 255),
3,
)
# Include group id to avoid collisions when multiple groups alert in one second. # Include group id to avoid collisions when multiple groups alert in one second.
alert_path = f"alerts/alert_{ts}_gid{gid}.jpg" alert_path = f"alerts/alert_{ts}_gid{gid}.jpg"
cv2.imwrite(alert_path, display) cv2.imwrite(alert_path, alert_display)
alert_info = { alert_info = {
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),