SuriRaja commited on
Commit
c2ed860
Β·
verified Β·
1 Parent(s): 085ef33

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +111 -117
app.py CHANGED
@@ -5,6 +5,10 @@ import requests
5
  import tempfile
6
  import mediapipe as mp
7
  import os
 
 
 
 
8
 
9
  # === CONFIGURATION ===
10
  API_KEY = "AIzaSyDojJrpauA0XZtCCDUuo9xeQHZQamYKsC4"
@@ -12,133 +16,123 @@ CCTVFEED_IDS = ['1KJRkSf2SKEZ1mXS9_si65IwMBtjs6p4n']
12
  REG_FOLDER_ID = '1qkcR7nQTEtiMH9OFUv2bGxVn08E3dKjF'
13
  INTRUDER_FOLDER_ID = '1PPAUWU-wMx7fek73p-hqPqYQypYtG8Ob'
14
 
15
- # === SETUP ===
16
  mp_face_detection = mp.solutions.face_detection
17
- mp_drawing = mp.solutions.drawing_utils
18
  face_detector = mp_face_detection.FaceDetection(model_selection=0, min_detection_confidence=0.5)
19
 
20
- # === UTILS ===
21
- def get_drive_files(folder_id, mime_prefix="image/"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  url = f"https://www.googleapis.com/drive/v3/files?q='{folder_id}'+in+parents&key={API_KEY}&fields=files(id,name,mimeType)"
23
- r = requests.get(url)
24
- files = r.json().get("files", [])
25
- return [f for f in files if f["mimeType"].startswith(mime_prefix)]
26
 
27
- def get_image_from_drive(file_id):
28
  url = f"https://drive.google.com/uc?id={file_id}&export=download"
29
- r = requests.get(url)
30
- img_array = np.asarray(bytearray(r.content), dtype=np.uint8)
31
- img = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
32
- return img
 
 
33
 
34
- def extract_face_embeddings(img):
35
- rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
36
  results = face_detector.process(rgb)
37
- faces = []
38
  if results.detections:
39
  for det in results.detections:
40
  bbox = det.location_data.relative_bounding_box
41
- h, w, _ = img.shape
42
- x, y = int(bbox.xmin * w), int(bbox.ymin * h)
43
- bw, bh = int(bbox.width * w), int(bbox.height * h)
44
- face_crop = img[max(0, y):y+bh, max(0, x):x+bw]
45
- if face_crop.size > 0:
46
- resized = cv2.resize(face_crop, (128, 128))
47
- faces.append(resized)
48
- return faces
49
-
50
- def compare_faces(face1, face2):
51
- try:
52
- diff = cv2.absdiff(face1, face2)
53
- return np.mean(diff)
54
- except:
55
- return 9999
56
-
57
- def upload_intruder_image(img_array, name_hint="intruder"):
58
- _, buffer = cv2.imencode('.jpg', img_array)
59
- img_bytes = buffer.tobytes()
60
- upload_url = f"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&key={API_KEY}"
61
-
62
- metadata = {
63
- "name": f"{name_hint}.jpg",
64
- "parents": [INTRUDER_FOLDER_ID]
65
- }
66
-
67
- boundary = "foo_bar_baz"
68
- headers = {
69
- "Content-Type": f"multipart/related; boundary={boundary}"
70
- }
71
-
72
- meta_json = str(metadata).replace("'", '"')
73
- body_prefix = (
74
- "--" + boundary + "\r\n"
75
- "Content-Type: application/json; charset=UTF-8\r\n\r\n"
76
- + meta_json + "\r\n"
77
- "--" + boundary + "\r\n"
78
- "Content-Type: image/jpeg\r\n\r\n"
79
- ).encode("utf-8")
80
-
81
- body_suffix = ("\r\n--" + boundary + "--").encode("utf-8")
82
- multipart_body = body_prefix + img_bytes + body_suffix
83
-
84
- r = requests.post(upload_url, headers=headers, data=multipart_body)
85
- return r.status_code == 200
86
-
87
- def download_video(link):
88
- r = requests.get(link, stream=True)
89
- temp = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
90
- for chunk in r.iter_content(chunk_size=1024*1024):
91
- temp.write(chunk)
92
- temp.close()
93
- return temp.name
94
-
95
- # === MAIN ===
96
  st.title("πŸ” Intruder Detection from CCTV Feed")
97
- st.write("Streaming videos from Google Drive, detecting faces using MediaPipe, and uploading unmatched intruders.")
98
-
99
- # Load registered faces
100
- st.sidebar.header("βœ… Registered Faces")
101
- registered_faces = []
102
- reg_files = get_drive_files(REG_FOLDER_ID, "image/")
103
- for f in reg_files:
104
- img = get_image_from_drive(f['id'])
105
- faces = extract_face_embeddings(img)
106
- registered_faces.extend(faces)
107
- for face in faces:
108
- st.sidebar.image(cv2.cvtColor(face, cv2.COLOR_BGR2RGB), caption=f['name'], width=100)
109
-
110
- # Process CCTV videos
111
- with st.spinner("Processing CCTV videos..."):
112
- total_detections = 0
113
  for folder_id in CCTVFEED_IDS:
114
- url = f"https://www.googleapis.com/drive/v3/files?q='{folder_id}'+in+parents&key={API_KEY}&fields=files(id,name,mimeType)"
115
- response = requests.get(url)
116
- files = response.json().get("files", [])
117
- for f in files:
118
- if f["mimeType"].startswith("video/"):
119
- st.subheader(f"πŸŽ₯ {f['name']}")
120
- link = f"https://drive.google.com/uc?id={f['id']}&export=download"
121
- video_file = download_video(link)
122
- cap = cv2.VideoCapture(video_file)
123
- found_intruder = False
124
-
125
- while cap.isOpened():
126
- ret, frame = cap.read()
127
- if not ret:
128
- break
129
- faces = extract_face_embeddings(frame)
130
- for face in faces:
131
- st.sidebar.image(cv2.cvtColor(face, cv2.COLOR_BGR2RGB), caption="Detected", width=100)
132
- distances = [compare_faces(face, reg_face) for reg_face in registered_faces]
133
- if not distances or min(distances) > 45: # Distance threshold
134
- uploaded = upload_intruder_image(face, f"intruder_{f['name']}")
135
- if uploaded:
136
- st.warning("⚠️ Intruder uploaded to Google Drive!")
137
- else:
138
- st.error("Failed to upload intruder.")
139
- found_intruder = True
140
- cap.release()
141
- os.remove(video_file)
142
- if not found_intruder:
143
- st.success("βœ… No intruders found.")
144
- st.info("🎯 Completed processing all videos.")
 
 
 
 
 
 
5
  import tempfile
6
  import mediapipe as mp
7
  import os
8
+ import pickle
9
+ from googleapiclient.discovery import build
10
+ from googleapiclient.http import MediaFileUpload
11
+ from PIL import Image
12
 
13
  # === CONFIGURATION ===
14
  API_KEY = "AIzaSyDojJrpauA0XZtCCDUuo9xeQHZQamYKsC4"
 
16
  REG_FOLDER_ID = '1qkcR7nQTEtiMH9OFUv2bGxVn08E3dKjF'
17
  INTRUDER_FOLDER_ID = '1PPAUWU-wMx7fek73p-hqPqYQypYtG8Ob'
18
 
 
19
  mp_face_detection = mp.solutions.face_detection
 
20
  face_detector = mp_face_detection.FaceDetection(model_selection=0, min_detection_confidence=0.5)
21
 
22
+ # === INTRUDER UPLOAD ===
23
+ def get_drive_service():
24
+ try:
25
+ with open("token.pickle", "rb") as token:
26
+ creds = pickle.load(token)
27
+ return build("drive", "v3", credentials=creds)
28
+ except Exception as e:
29
+ print(f"❌ Drive auth failed: {e}")
30
+ return None
31
+
32
+ def upload_intruder_face(image_path):
33
+ service = get_drive_service()
34
+ if service is None:
35
+ print("πŸ”’ Upload skipped (auth failed)")
36
+ return
37
+
38
+ metadata = {"name": os.path.basename(image_path), "parents": [INTRUDER_FOLDER_ID]}
39
+ media = MediaFileUpload(image_path, mimetype="image/jpeg")
40
+ try:
41
+ service.files().create(body=metadata, media_body=media, fields="id").execute()
42
+ print(f"βœ… Uploaded to INTRUDER folder: {image_path}")
43
+ except Exception as e:
44
+ print(f"❌ Upload failed: {e}")
45
+
46
+ # === HELPERS ===
47
+ def get_drive_files(folder_id, allowed_mime):
48
  url = f"https://www.googleapis.com/drive/v3/files?q='{folder_id}'+in+parents&key={API_KEY}&fields=files(id,name,mimeType)"
49
+ response = requests.get(url)
50
+ files = response.json().get("files", [])
51
+ return [(f["name"], f["id"]) for f in files if f["mimeType"] in allowed_mime]
52
 
53
+ def download_file(file_id, suffix):
54
  url = f"https://drive.google.com/uc?id={file_id}&export=download"
55
+ response = requests.get(url, stream=True)
56
+ temp = tempfile.NamedTemporaryFile(delete=False, suffix=suffix)
57
+ for chunk in response.iter_content(chunk_size=1024 * 1024):
58
+ temp.write(chunk)
59
+ temp.close()
60
+ return temp.name
61
 
62
+ def extract_face_embedding(image):
63
+ rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
64
  results = face_detector.process(rgb)
 
65
  if results.detections:
66
  for det in results.detections:
67
  bbox = det.location_data.relative_bounding_box
68
+ h, w, _ = image.shape
69
+ x1 = int(bbox.xmin * w)
70
+ y1 = int(bbox.ymin * h)
71
+ x2 = int((bbox.xmin + bbox.width) * w)
72
+ y2 = int((bbox.ymin + bbox.height) * h)
73
+ face_crop = image[y1:y2, x1:x2]
74
+ return cv2.resize(face_crop, (128, 128))
75
+ return None
76
+
77
+ def is_match(face1, face2):
78
+ if face1 is None or face2 is None:
79
+ return False
80
+ diff = np.linalg.norm(face1.astype("float") - face2.astype("float"))
81
+ return diff < 30.0
82
+
83
+ # === STREAMLIT UI ===
84
+ st.set_page_config(page_title="Intruder Detection", layout="wide")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  st.title("πŸ” Intruder Detection from CCTV Feed")
86
+ st.write("Streaming videos from Google Drive, detecting and matching faces.")
87
+
88
+ sidebar_faces = []
89
+
90
+ with st.spinner("Loading registered faces..."):
91
+ registered = []
92
+ reg_images = get_drive_files(REG_FOLDER_ID, ["image/jpeg", "image/png"])
93
+ for name, fid in reg_images:
94
+ img_path = download_file(fid, ".jpg")
95
+ img = cv2.imread(img_path)
96
+ emb = extract_face_embedding(img)
97
+ if emb is not None:
98
+ registered.append((name, emb))
99
+
100
+ with st.spinner("Scanning CCTV feed..."):
101
+ total_intruders = 0
102
  for folder_id in CCTVFEED_IDS:
103
+ videos = get_drive_files(folder_id, ["video/mp4", "video/x-msvideo", "video/avi"])
104
+ for vname, fid in videos:
105
+ st.subheader(f"πŸŽ₯ {vname}")
106
+ vid_path = download_file(fid, ".mp4")
107
+ cap = cv2.VideoCapture(vid_path)
108
+ frame_count = 0
109
+ matched_faces = 0
110
+ unmatched_faces = 0
111
+
112
+ while cap.isOpened():
113
+ ret, frame = cap.read()
114
+ if not ret:
115
+ break
116
+ face_img = extract_face_embedding(frame)
117
+ if face_img is not None:
118
+ match_found = any(is_match(face_img, emb) for _, emb in registered)
119
+ if match_found:
120
+ matched_faces += 1
121
+ else:
122
+ unmatched_faces += 1
123
+ temp = tempfile.NamedTemporaryFile(delete=False, suffix=".jpg")
124
+ cv2.imwrite(temp.name, face_img)
125
+ upload_intruder_face(temp.name)
126
+ sidebar_faces.append(temp.name)
127
+ frame_count += 1
128
+ cap.release()
129
+
130
+ st.success(f"🎯 Processed {frame_count} frames β€” Matched: {matched_faces}, Unmatched: {unmatched_faces}")
131
+ total_intruders += unmatched_faces
132
+
133
+ st.info(f"🎯 Completed processing all videos. Intruders detected: {total_intruders}")
134
+
135
+ with st.sidebar:
136
+ st.markdown("## 🚨 Intruder Snapshots")
137
+ for face_path in sidebar_faces:
138
+ st.image(face_path, width=160)