ADharsh22 commited on
Commit
ab8eba2
·
1 Parent(s): 00c73ec

FINAL STABILITY FIX: Switched to VideoProcessorBase, added 'av', and used @st .cache_resource to eliminate thread/shutdown race conditions.

Browse files
Files changed (2) hide show
  1. app.py +41 -58
  2. requirements.txt +2 -1
app.py CHANGED
@@ -1,56 +1,47 @@
1
  import streamlit as st
2
  import cv2 # OpenCV for image processing
3
  import numpy as np
4
- import av
5
- # NOTE: Use VideoProcessorBase as the primary class as VideoTransformerBase is deprecated
6
  from streamlit_webrtc import webrtc_streamer, VideoProcessorBase, WebRtcMode
7
 
8
- # --- PLACEHOLDER IMPORTS (UNCOMMENT/ADJUST AS NEEDED) ---
9
- # NOTE: Make sure these core libraries are in your requirements.txt
10
- # import deepface
11
- # from src.detect import detect_faces
12
- # from src.recognize import recognize_face
13
 
14
  # --- CONFIGURATION ---
15
  RECOGNITION_THRESHOLD = 0.6
16
- FRAME_SKIP = 3 # Process every 3rd frame for performance
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
- # --- VIDEO PROCESSING CLASS ---
20
- # Using VideoProcessorBase to align with current streamlit-webrtc practices
21
- class FaceRecognitionProcessor(VideoProcessorBase):
22
- """
23
- A class that processes video frames in real-time for face recognition.
24
- """
25
- def __init__(self):
26
- # Initialize models once here
27
- self.frame_count = 0
28
- # ... your model loading initialization ...
29
-
30
- def recv(self, frame):
31
- # The frame is now an av.VideoFrame object, convert to numpy array
32
- img = frame.to_ndarray(format="bgr24")
33
-
34
- self.frame_count += 1
35
- if self.frame_count % FRAME_SKIP != 0:
36
- return frame # Return the original frame if skipping
37
-
38
- # --- Your Face Detection and Recognition Logic Goes Here ---
39
- # Example placeholder logic:
40
- h, w, _ = img.shape
41
- faces = [(w//4, h//4, w//2, h//2)] # Placeholder bounding box
42
-
43
- for (x, y, w, h) in faces:
44
- recognized_name = "Unknown"
45
- score = 0.0
46
- color = (0, 0, 255)
47
-
48
- cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)
49
- label = f"{recognized_name}: {score:.2f}"
50
- cv2.putText(img, label, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, color, 2)
51
-
52
- # Convert back to av.VideoFrame before returning
53
- return av.VideoFrame.from_ndarray(img, format="bgr24")
54
 
55
  # --- STREAMLIT UI ---
56
 
@@ -60,22 +51,14 @@ def main():
60
  st.title("Smart Office Face Recognition System 📸")
61
  st.sidebar.title("Configuration")
62
 
63
- RECOGNITION_THRESHOLD = st.sidebar.slider(
64
- "Recognition Threshold", min_value=0.0, max_value=1.0, value=0.6, step=0.05
65
- )
66
 
67
- # Use a stable key
68
- STREAMER_KEY = "face-recognition-stream-final"
69
-
70
- # --- CRITICAL FIX: The webrtc_streamer call itself must be outside the wrapper ---
71
- # The fix is to ensure the component is always called/rendered, but the initialization
72
- # of heavy resources (models) is safely handled inside a cached function (if needed).
73
-
74
  webrtc_streamer(
75
- key=STREAMER_KEY,
76
  mode=WebRtcMode.SENDRECV,
77
 
78
- # --- FIX 2: Enhanced STUN/TURN configuration to resolve aioice errors ---
79
  rtc_configuration={
80
  "iceServers": [
81
  {"urls": ["stun:stun.l.google.com:19302"]},
@@ -83,8 +66,8 @@ def main():
83
  ]
84
  },
85
 
86
- # NOTE: Using video_processor_factory and the VideoProcessorBase class
87
- video_processor_factory=FaceRecognitionProcessor,
88
  async_processing=True
89
  )
90
 
@@ -93,5 +76,5 @@ def main():
93
 
94
  # --- EXECUTION ---
95
  if __name__ == "__main__":
96
- # You MUST also install the package 'av' (pip install av) to use VideoProcessorBase
97
  main()
 
1
  import streamlit as st
2
  import cv2 # OpenCV for image processing
3
  import numpy as np
4
+ import av # <--- REQUIRED: Must be in requirements.txt (pip install av)
 
5
  from streamlit_webrtc import webrtc_streamer, VideoProcessorBase, WebRtcMode
6
 
7
+ # --- PLACEHOLDER IMPORTS (Adjust as needed) ---
8
+ # ...
 
 
 
9
 
10
  # --- CONFIGURATION ---
11
  RECOGNITION_THRESHOLD = 0.6
12
+ FRAME_SKIP = 3
13
 
14
+ # --- CACHE THE MODEL/FACTORY (CRITICAL FIX FOR THREADING) ---
15
+ # This ensures the processor and its threads are initialized only ONCE.
16
+ @st.cache_resource
17
+ def get_face_processor_factory():
18
+ """Returns the processor class, ensuring it is cached."""
19
+
20
+ class FaceRecognitionProcessor(VideoProcessorBase):
21
+ """Processes video frames using the standard VideoProcessorBase."""
22
+ def __init__(self):
23
+ # Initialize models once here (safely cached by @st.cache_resource)
24
+ self.frame_count = 0
25
+ # Example: self.detection_model = load_your_model()
26
+
27
+ def recv(self, frame: av.VideoFrame) -> av.VideoFrame:
28
+ # Convert frame from av.VideoFrame to numpy array (BGR)
29
+ img = frame.to_ndarray(format="bgr24")
30
+
31
+ self.frame_count += 1
32
+ if self.frame_count % FRAME_SKIP != 0:
33
+ return frame # Return the original frame if skipping
34
+
35
+ # --- Your Face Detection and Recognition Logic Goes Here ---
36
+ h, w, _ = img.shape
37
+ # Placeholder drawing logic:
38
+ x, y, w_box, h_box = w//4, h//4, w//2, h//2
39
+ cv2.rectangle(img, (x, y), (x + w_box, y + h_box), (0, 0, 255), 2)
40
+
41
+ # Convert back to av.VideoFrame before returning
42
+ return av.VideoFrame.from_ndarray(img, format="bgr24")
43
 
44
+ return FaceRecognitionProcessor
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  # --- STREAMLIT UI ---
47
 
 
51
  st.title("Smart Office Face Recognition System 📸")
52
  st.sidebar.title("Configuration")
53
 
54
+ # ... (Sidebar control for threshold) ...
 
 
55
 
56
+ # --- FINAL WEBRTC STREAMER CALL ---
 
 
 
 
 
 
57
  webrtc_streamer(
58
+ key="face-recognition-stream-final-cache",
59
  mode=WebRtcMode.SENDRECV,
60
 
61
+ # --- Enhanced STUN/TURN configuration ---
62
  rtc_configuration={
63
  "iceServers": [
64
  {"urls": ["stun:stun.l.google.com:19302"]},
 
66
  ]
67
  },
68
 
69
+ # Use the CACHED factory function
70
+ video_processor_factory=get_face_processor_factory,
71
  async_processing=True
72
  )
73
 
 
76
 
77
  # --- EXECUTION ---
78
  if __name__ == "__main__":
79
+ # IMPORTANT: Ensure 'av' is in your requirements.txt
80
  main()
requirements.txt CHANGED
@@ -3,4 +3,5 @@ streamlit-webrtc
3
  opencv-python
4
  deepface
5
  numpy
6
- scikit-learn
 
 
3
  opencv-python
4
  deepface
5
  numpy
6
+ scikit-learn
7
+ av