SuriRaja commited on
Commit
979fea5
·
verified ·
1 Parent(s): 60578bb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -9
app.py CHANGED
@@ -5,6 +5,10 @@
5
  # - (NEW) Per-employee live timers on video overlays: Working and Idle counters (mm:ss)
6
  # - (NEW) Employees view shows the same live Working/Idle seconds
7
  # - (Patch I–K) Real-time streaming pace: higher default FPS, up to 60 FPS slider, process every frame when possible, time-synced display (no fixed sleeps).
 
 
 
 
8
 
9
  import os, json, math, tempfile, time
10
  from datetime import datetime, date
@@ -683,9 +687,20 @@ with tab_live:
683
  last_display_t = time.perf_counter()
684
  target_dt = 1.0 / float(src_fps if src_fps and src_fps > 0 else 25.0)
685
 
 
 
 
686
  while cap.isOpened() and frame_no < max_frames:
 
 
 
 
 
 
 
687
  ret, frame = cap.read()
688
- if not ret: break
 
689
  pos = int(cap.get(cv2.CAP_PROP_POS_FRAMES))
690
  if pos % step != 0:
691
  frame_no += 1
@@ -696,6 +711,21 @@ with tab_live:
696
  last_display_t = time.perf_counter()
697
  continue
698
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
699
  do_process = True
700
  gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
701
  if prev_gray is not None and skip_near_identical:
@@ -712,15 +742,27 @@ with tab_live:
712
  frame_no += 1
713
  continue
714
 
715
- dets = run_yolo_on_frame(model, frame, conf_thres)
716
- persons = [d for d in dets if d.cls == "person"]
717
- phones = [d for d in dets if d.cls in ("cell phone","mobile phone","phone")]
 
718
 
719
  vis = blur_faces_if_needed(frame, face_cascade, st.session_state.privacy_blur)
720
- rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
721
 
722
- face_pairs = get_face_pairs_insight(rgb)
723
- face_boxes_only = [b for (b,_) in face_pairs]
 
 
 
 
 
 
 
 
 
 
 
 
724
 
725
  for idx, p in enumerate(persons):
726
  # motion / base activity
@@ -732,7 +774,7 @@ with tab_live:
732
  # identify person
733
  name = None
734
  for (fbox, emb) in face_pairs:
735
- fx1, fy1, fx2, fy2 = fbox
736
  cx = (fx1+fx2)/2; cy = (fy1+fy2)/2
737
  if (p.box[0] <= cx <= p.box[2]) and (p.box[1] <= cy <= p.box[3]):
738
  name = recognize_name_from_embedding(emb, st.session_state.face_db)
@@ -856,7 +898,9 @@ with tab_live:
856
  last_display_t = time.perf_counter()
857
 
858
  frame_no += 1
859
- prog.progress(min(1.0, frame_no/max_frames))
 
 
860
 
861
  cap.release(); os.remove(tmp_path); prog.progress(1.0)
862
  st.success(f"Tile {tile_index+1}: processed {frame_no} frames")
 
5
  # - (NEW) Per-employee live timers on video overlays: Working and Idle counters (mm:ss)
6
  # - (NEW) Employees view shows the same live Working/Idle seconds
7
  # - (Patch I–K) Real-time streaming pace: higher default FPS, up to 60 FPS slider, process every frame when possible, time-synced display (no fixed sleeps).
8
+ # - (Patch M) Real-time catch-up reader (clip plays in wall time; drop backlog if behind)
9
+ # - (Patch O) Downscale only for inference (rescale boxes for draw)
10
+ # - (Patch P) Run InsightFace every ~5 processed frames (reuse embeddings in between)
11
+ # - (Patch Q) Update progress bar every ~10 frames
12
 
13
  import os, json, math, tempfile, time
14
  from datetime import datetime, date
 
687
  last_display_t = time.perf_counter()
688
  target_dt = 1.0 / float(src_fps if src_fps and src_fps > 0 else 25.0)
689
 
690
+ # Patch M: wall-clock anchor (real-time catch-up)
691
+ wall_t0 = time.perf_counter()
692
+
693
  while cap.isOpened() and frame_no < max_frames:
694
+ # ---- Patch M: real-time catch-up reader ----
695
+ elapsed = time.perf_counter() - wall_t0
696
+ target_idx = int(elapsed * (src_fps if src_fps and src_fps > 0 else 25.0))
697
+ cur_idx = int(cap.get(cv2.CAP_PROP_POS_FRAMES))
698
+ if target_idx > cur_idx + 1:
699
+ cap.set(cv2.CAP_PROP_POS_FRAMES, target_idx)
700
+
701
  ret, frame = cap.read()
702
+ if not ret:
703
+ break
704
  pos = int(cap.get(cv2.CAP_PROP_POS_FRAMES))
705
  if pos % step != 0:
706
  frame_no += 1
 
711
  last_display_t = time.perf_counter()
712
  continue
713
 
714
+ # ---- Patch O: downscale only for inference; rescale boxes for draw
715
+ H0, W0 = frame.shape[:2]
716
+ infer_scale = 1.0
717
+ if W0 > 1280:
718
+ infer_scale = 1280.0 / W0
719
+ infer_frame = cv2.resize(frame, (int(W0*infer_scale), int(H0*infer_scale)), interpolation=cv2.INTER_AREA)
720
+ else:
721
+ infer_frame = frame
722
+
723
+ def _inv(b):
724
+ if infer_scale == 1.0: return b
725
+ x1,y1,x2,y2 = b
726
+ inv = 1.0 / infer_scale
727
+ return (int(x1*inv), int(y1*inv), int(x2*inv), int(y2*inv))
728
+
729
  do_process = True
730
  gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
731
  if prev_gray is not None and skip_near_identical:
 
742
  frame_no += 1
743
  continue
744
 
745
+ # YOLO on infer_frame, rescale boxes back
746
+ dets = run_yolo_on_frame(model, infer_frame, conf_thres)
747
+ persons = [DetBox(d.cls, d.conf, _inv(d.box)) for d in dets if d.cls == "person"]
748
+ phones = [DetBox(d.cls, d.conf, _inv(d.box)) for d in dets if d.cls in ("cell phone","mobile phone","phone")]
749
 
750
  vis = blur_faces_if_needed(frame, face_cascade, st.session_state.privacy_blur)
 
751
 
752
+ # ---- Patch P: run InsightFace every ~5 processed frames; reuse otherwise
753
+ if 'last_face_pairs' not in st.session_state: st.session_state.last_face_pairs = []
754
+ if 'last_face_update_pos' not in st.session_state: st.session_state.last_face_update_pos = -999
755
+ if (pos - st.session_state.last_face_update_pos) >= 5:
756
+ rgb_infer = cv2.cvtColor(infer_frame, cv2.COLOR_BGR2RGB)
757
+ face_pairs = get_face_pairs_insight(rgb_infer)
758
+ st.session_state.last_face_pairs = face_pairs
759
+ st.session_state.last_face_update_pos = pos
760
+ else:
761
+ face_pairs = st.session_state.last_face_pairs
762
+ face_boxes_only = [_inv(b) for (b, _) in face_pairs]
763
+
764
+ # (legacy var kept; harmless)
765
+ rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
766
 
767
  for idx, p in enumerate(persons):
768
  # motion / base activity
 
774
  # identify person
775
  name = None
776
  for (fbox, emb) in face_pairs:
777
+ fx1, fy1, fx2, fy2 = _inv(fbox)
778
  cx = (fx1+fx2)/2; cy = (fy1+fy2)/2
779
  if (p.box[0] <= cx <= p.box[2]) and (p.box[1] <= cy <= p.box[3]):
780
  name = recognize_name_from_embedding(emb, st.session_state.face_db)
 
898
  last_display_t = time.perf_counter()
899
 
900
  frame_no += 1
901
+ # Patch Q: throttle progress updates
902
+ if frame_no % 10 == 0:
903
+ prog.progress(min(1.0, frame_no/max_frames))
904
 
905
  cap.release(); os.remove(tmp_path); prog.progress(1.0)
906
  st.success(f"Tile {tile_index+1}: processed {frame_no} frames")