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
parent
50ecbdcc50
commit
a1da64e017
|
|
@ -270,12 +270,34 @@ def _process_stream():
|
|||
# --- Draw overlays ---
|
||||
display = frame.copy()
|
||||
|
||||
for x1, y1, x2, y2, conf in person_boxes:
|
||||
cv2.rectangle(display, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2)
|
||||
pending_gid_set = {gid for gid, _, _ in pending_alerts}
|
||||
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(
|
||||
display, f"{conf:.0%}",
|
||||
(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:
|
||||
|
|
@ -301,14 +323,72 @@ def _process_stream():
|
|||
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3,
|
||||
)
|
||||
|
||||
# --- Save annotated alerts ---
|
||||
# --- Save annotated alerts (separate per group) ---
|
||||
if pending_alerts:
|
||||
os.makedirs("alerts", exist_ok=True)
|
||||
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:
|
||||
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.
|
||||
alert_path = f"alerts/alert_{ts}_gid{gid}.jpg"
|
||||
cv2.imwrite(alert_path, display)
|
||||
cv2.imwrite(alert_path, alert_display)
|
||||
|
||||
alert_info = {
|
||||
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
|
|
|
|||
Loading…
Reference in New Issue