Files
reTraining/backend/live_render.py
T

61 lines
3.0 KiB
Python

"""Burning the counting overlay into the frame, as an MJPEG.
Split out of `live_count.py` to keep it inside the 400-line limit. This is the
fallback preview, used for archive files; a WebRTC session draws the same
geometry on a canvas in the browser instead (REQ-177).
"""
import cv2
def render(session, frame, detections, ignored, counter):
height, width = frame.shape[:2]
# Shade what the region excludes. Without this the neighbouring truck's
# sacks simply vanish from the overlay, and "are they being ignored?"
# looks identical to "is the model missing them?".
if session.line_x_start > 0 or session.line_x_end < width:
shade = frame.copy()
if session.line_x_start > 0:
cv2.rectangle(shade, (0, 0), (session.line_x_start, height), (0, 0, 0), -1)
if session.line_x_end < width:
cv2.rectangle(shade, (session.line_x_end, 0), (width, height), (0, 0, 0), -1)
cv2.addWeighted(shade, 0.55, frame, 0.45, 0, frame)
# Ignored detections stay visible, in grey, so the region can be judged.
for det in ignored:
x1, y1, x2, y2 = (int(v) for v in det.bbox)
cv2.rectangle(frame, (x1, y1), (x2, y2), (130, 130, 130), 1)
for edge in (session.line_x_start, session.line_x_end):
if 0 < edge < width:
cv2.line(frame, (edge, 0), (edge, height), (255, 0, 255), 2)
cv2.putText(frame, "IGNORED", (max(4, session.line_x_start - 92), height - 14),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 1, cv2.LINE_AA)
cv2.putText(frame, "IGNORED", (min(width - 88, session.line_x_end + 8), height - 14),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 1, cv2.LINE_AA)
for det in detections:
x1, y1, x2, y2 = (int(v) for v in det.bbox)
counted = bool(counter.counted_tracks.get(det.track_id))
colour = (74, 222, 128) if counted else (248, 191, 113)
cv2.rectangle(frame, (x1, y1), (x2, y2), colour, 2)
cv2.putText(frame, f"#{det.track_id} {det.confidence:.2f}", (x1, max(14, y1 - 6)),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, colour, 1, cv2.LINE_AA)
cv2.line(frame, (session.line_x_start, session.line_y), (session.line_x_end, session.line_y),
(0, 255, 255), 2)
for edge in (session.line_y - session.margin, session.line_y + session.margin):
cv2.line(frame, (session.line_x_start, edge), (session.line_x_end, edge),
(0, 160, 160), 1)
panel = f"IN {session.loading} OUT {session.unloading} NET {session.loading - session.unloading}"
cv2.rectangle(frame, (12, 12), (12 + 9 * len(panel) + 20, 84), (0, 0, 0), -1)
cv2.putText(frame, panel, (24, 46), cv2.FONT_HERSHEY_SIMPLEX, 0.8,
(74, 222, 128), 2, cv2.LINE_AA)
cv2.putText(frame, f"{session.fps:.1f} fps {session.tracked} tracked {session.ignored} ignored",
(24, 72), cv2.FONT_HERSHEY_SIMPLEX, 0.55, (200, 200, 200), 1, cv2.LINE_AA)
ok, buffer = cv2.imencode(".jpg", frame, [cv2.IMWRITE_JPEG_QUALITY, 75])
return buffer.tobytes() if ok else None