John Walley commited on
Commit
f8b925c
Β·
1 Parent(s): 91d687e
Files changed (4) hide show
  1. .gitignore +57 -0
  2. README.md +149 -5
  3. app.py +433 -0
  4. requirements.txt +5 -0
.gitignore ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual environments
24
+ venv/
25
+ env/
26
+ ENV/
27
+ .venv
28
+
29
+ # IDEs
30
+ .vscode/
31
+ .idea/
32
+ *.swp
33
+ *.swo
34
+ *~
35
+ .DS_Store
36
+ .claude/
37
+
38
+ # Jupyter
39
+ .ipynb_checkpoints
40
+
41
+ # Model files (YOLO will download on first run)
42
+ *.pt
43
+ *.onnx
44
+ *.torchscript
45
+ *.tflite
46
+ *.pb
47
+
48
+ # Gradio
49
+ gradio_cached_examples/
50
+ flagged/
51
+
52
+ # Logs
53
+ *.log
54
+
55
+ # Environment
56
+ .env
57
+ .env.local
README.md CHANGED
@@ -1,14 +1,158 @@
1
  ---
2
  title: Murderer Detector
3
- emoji: ⚑
4
- colorFrom: indigo
5
- colorTo: gray
6
  sdk: gradio
7
  sdk_version: 6.0.1
8
  app_file: app.py
9
  pinned: false
10
  license: apache-2.0
11
- short_description: Be safe out there!
12
  ---
13
 
14
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  title: Murderer Detector
3
+ emoji: πŸ”ͺ
4
+ colorFrom: red
5
+ colorTo: black
6
  sdk: gradio
7
  sdk_version: 6.0.1
8
  app_file: app.py
9
  pinned: false
10
  license: apache-2.0
11
+ short_description: Detect suspicious individuals lurking behind you with AI!
12
  ---
13
 
14
+ # πŸ”ͺ Murderer Detector
15
+
16
+ [![Gradio](https://img.shields.io/badge/Gradio-6.0.1-orange)](https://gradio.app/)
17
+ [![Python](https://img.shields.io/badge/Python-3.10+-blue)](https://www.python.org/)
18
+ [![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](LICENSE)
19
+
20
+ > **WARNING:** This app uses HIGHLY ADVANCED AI TECHNOLOGY to detect potential murderers lurking behind you!
21
+
22
+ ## What is This?
23
+
24
+ A humorous real-time person detection app that detects suspicious individuals lurking **behind** you. Built with Gradio 6.0.1 and YOLOv8.
25
+
26
+ **This is for funs.** No actual threat detection occurs. Don't call the cops on your roommates.
27
+
28
+ ## Features
29
+
30
+ - **Real-time webcam streaming** with unified display (no separate input/output)
31
+ - **Smart user detection** - filters out the user (largest person) and only flags people behind them
32
+ - **Person detection** with YOLOv8-nano
33
+ - **Hilarious single-line labels** with emojis and threat percentages:
34
+ - πŸ₯£ SERIAL BREAKFAST SKIPPER (87%)
35
+ - πŸ“š DANGEROUS BOOK READER (92%)
36
+ - πŸ›οΈ FITTED SHEET FOLDER (76%)
37
+ - β˜• NOTORIOUS TEA DRINKER (95%)
38
+ - πŸ”Œ OWNS MULTIPLE USB-C CABLES (83%)
39
+ - ...and 15 more!
40
+ - **Color-coded threat levels** (red/orange/yellow based on percentage)
41
+ - **Large, readable text** optimized for webcam viewing
42
+ - **Running suspect count** in header
43
+
44
+ ## Quick Start
45
+
46
+ ### Run Locally
47
+
48
+ ```bash
49
+ # Install dependencies
50
+ pip install -r requirements.txt
51
+
52
+ # Run the app (includes share=True for instant public URL)
53
+ python app.py
54
+ ```
55
+
56
+ The app will launch at http://localhost:7860 and provide a public shareable link!
57
+
58
+ ### Deploy to Hugging Face Spaces
59
+
60
+ 1. Create a new Space on Hugging Face
61
+ 2. Upload these files:
62
+ - `app.py`
63
+ - `requirements.txt`
64
+ - `README.md`
65
+ 3. Your app will automatically deploy!
66
+
67
+ ## For Developers
68
+
69
+ This app is intentionally structured to be easily modified for **serious computer vision applications**. The code is organized into clear modules:
70
+
71
+ ### Architecture
72
+
73
+ ```
74
+ PersonDetector β†’ Detection Module (swap YOLO for any model)
75
+ MurdererClassifier β†’ Classification Logic (replace with real ML)
76
+ FrameAnnotator β†’ Annotation Layer (customize visuals)
77
+ MurdererDetector β†’ Main Pipeline (orchestrates everything)
78
+ ```
79
+
80
+ ### Modify for Serious Use Cases
81
+
82
+ **Security Monitoring:**
83
+ - Replace `MurdererClassifier` with anomaly detection
84
+ - Add action recognition (violence, falls, intrusions)
85
+ - Integrate alerts and logging
86
+
87
+ **PPE Detection:**
88
+ - Modify `PersonDetector` to detect helmets, vests, masks
89
+ - Add compliance scoring in `MurdererClassifier`
90
+ - Update annotations to show violations
91
+
92
+ **Customer Analytics:**
93
+ - Track people counting and dwell time
94
+ - Add age/gender classification
95
+ - Generate heatmaps in `FrameAnnotator`
96
+
97
+ **Social Distancing:**
98
+ - Calculate distances between detected persons
99
+ - Flag violations with visual warnings
100
+ - Log statistics over time
101
+
102
+ ### Key Components
103
+
104
+ **app.py:53** - `PersonDetector.detect_persons()` - Swap detection models here
105
+
106
+ **app.py:127** - `MurdererClassifier.classify()` - Replace with real ML inference
107
+
108
+ **app.py:183** - `FrameAnnotator.annotate_frame()` - Customize visualization
109
+
110
+ **app.py:342** - `MurdererDetector._filter_user()` - Logic to exclude the user (largest person)
111
+
112
+ All classes are well-documented with inline comments explaining modification points.
113
+
114
+ ## Technical Details
115
+
116
+ - **Detection**: YOLOv8-nano (fast, lightweight, ~6MB model)
117
+ - **Streaming**: Gradio 6.x Image streaming with unified input/output
118
+ - **Processing**: Real-time with OpenCV
119
+ - **User Filtering**: Excludes largest person (assumed to be the user)
120
+ - **Deployment**: Optimized for Hugging Face Spaces with share=True enabled
121
+
122
+ ## How to Use
123
+
124
+ 1. **Run the app** - It launches with a public shareable link
125
+ 2. **Enable webcam** - Click the webcam button in the interface
126
+ 3. **Position someone behind you** - The app needs at least 2 people (you + someone behind you)
127
+ 4. **Watch the detection** - Only people behind you get flagged as "threats"
128
+ 5. **Share the link** - Use the Gradio share link to show friends
129
+
130
+ **Note:** If you're the only person in frame, nothing will be detected (by design!)
131
+
132
+ ## License
133
+
134
+ Apache 2.0 - Use this code for anything! Education, commercial projects, world domination, etc.
135
+
136
+ ## Credits
137
+
138
+ Built with:
139
+ - [Gradio 6.0.1](https://gradio.app/) for the UI and streaming
140
+ - [Ultralytics YOLOv8](https://github.com/ultralytics/ultralytics) for person detection
141
+ - Excessive amounts of coffee and true crime documentaries
142
+
143
+ ## Contributing
144
+
145
+ Found a funnier label? Want to improve the detection? Open a PR!
146
+
147
+ Ideas for improvements:
148
+ - More emoji labels (currently 20, could add 50+)
149
+ - Sound effects when new suspects appear
150
+ - Threat level history/tracking
151
+ - Better user filtering (depth detection, face recognition)
152
+ - Multiple webcam angles
153
+ - Export "suspect reports" as PDF
154
+ - Multiple language support
155
+
156
+ ---
157
+
158
+ **Remember:** The real murderers are the friends we made along the way. Stay safe out there! πŸ”ͺ
app.py ADDED
@@ -0,0 +1,433 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Murderer Detector - A Humorous Webcam Person Detection Demo
3
+
4
+ This app demonstrates real-time person detection with humorous labeling.
5
+ It's structured to be easily modified for serious applications like:
6
+ - Security monitoring
7
+ - PPE detection
8
+ - Customer analytics
9
+ - Social distancing monitoring
10
+
11
+ Architecture:
12
+ 1. Detection Module: Uses YOLO for person detection (easily swappable)
13
+ 2. Classification Logic: Generates humorous labels (swap for real ML inference)
14
+ 3. Annotation Layer: Draws boxes and labels (customize visuals)
15
+ 4. Streaming Handler: Processes webcam feed via Gradio
16
+ """
17
+
18
+ import gradio as gr
19
+ import cv2
20
+ import numpy as np
21
+ from ultralytics import YOLO
22
+ import random
23
+ from typing import Tuple, List, Dict
24
+ import time
25
+
26
+
27
+ # ============================================================================
28
+ # DETECTION MODULE
29
+ # Swap this section for different detection models or backends
30
+ # ============================================================================
31
+
32
+ class PersonDetector:
33
+ """
34
+ Person detection using YOLO.
35
+
36
+ For serious applications, modify this to:
37
+ - Use different models (MediaPipe, custom trained models)
38
+ - Add specific object detection (weapons, PPE, etc.)
39
+ - Integrate with cloud APIs (AWS Rekognition, Google Vision)
40
+ """
41
+
42
+ def __init__(self, model_name: str = "yolov8n.pt", confidence: float = 0.5):
43
+ """
44
+ Initialize the person detector.
45
+
46
+ Args:
47
+ model_name: YOLO model to use (n=nano, s=small, m=medium, l=large)
48
+ confidence: Detection confidence threshold
49
+ """
50
+ self.model = YOLO(model_name)
51
+ self.confidence = confidence
52
+
53
+ def detect_persons(self, frame: np.ndarray) -> List[Dict]:
54
+ """
55
+ Detect persons in a frame.
56
+
57
+ Args:
58
+ frame: Input image as numpy array (BGR format)
59
+
60
+ Returns:
61
+ List of detections with bounding boxes and confidence scores
62
+ """
63
+ # Run inference
64
+ results = self.model(frame, conf=self.confidence,
65
+ classes=[0], verbose=False)
66
+
67
+ detections = []
68
+ for result in results:
69
+ boxes = result.boxes
70
+ for box in boxes:
71
+ x1, y1, x2, y2 = box.xyxy[0].cpu().numpy()
72
+ confidence = float(box.conf[0])
73
+
74
+ detections.append({
75
+ 'bbox': (int(x1), int(y1), int(x2), int(y2)),
76
+ 'confidence': confidence
77
+ })
78
+
79
+ return detections
80
+
81
+
82
+ # ============================================================================
83
+ # CLASSIFICATION LOGIC
84
+ # Replace this section for serious applications
85
+ # ============================================================================
86
+
87
+ class MurdererClassifier:
88
+ """
89
+ Humorous 'threat' classification.
90
+
91
+ For serious applications, replace with:
92
+ - Emotion detection models
93
+ - Action recognition (violence, falls, etc.)
94
+ - Anomaly detection
95
+ - Age/gender classification
96
+ """
97
+
98
+ # Short, punchy threat labels
99
+ LABELS = [
100
+ "πŸ₯£ SERIAL BREAKFAST SKIPPER",
101
+ "😴 SUSPICIOUSLY WELL-RESTED",
102
+ "πŸ“Ί TRUE CRIME WATCHER",
103
+ "πŸ“š DANGEROUS BOOK READER",
104
+ "πŸ₯„ SERIAL CEREAL KILLER",
105
+ "😊 TOO POLITE. SUSPICIOUS.",
106
+ "πŸ‘€ PROFESSIONAL LURKER",
107
+ "πŸͺ΄ PLANT WHISPERER",
108
+ "πŸ• ALLEGED DOG PETTER",
109
+ "β˜• NOTORIOUS TEA DRINKER",
110
+ "πŸ€” CONFIRMED OVERTHINKER",
111
+ "🧍 BACKGROUND STANDER",
112
+ "πŸ’€ GETS 8 HOURS SLEEP",
113
+ "πŸ’§ DRINKS WATER DAILY",
114
+ "πŸ”Œ OWNS MULTIPLE USB-C CABLES",
115
+ "🎡 CAN WHISTLE & SNAP",
116
+ "πŸ›οΈ FITTED SHEET FOLDER",
117
+ "πŸ“– READ 3+ BOOKS",
118
+ "🌿 TALKS TO HOUSEPLANTS",
119
+ "🎯 UNUSUALLY GOOD AT TRIVIA",
120
+ ]
121
+
122
+ def __init__(self):
123
+ """Initialize the classifier with tracking for consistent labels."""
124
+ self.person_history = {}
125
+ self.next_id = 0
126
+
127
+ def classify(self, detection: Dict) -> Dict:
128
+ """
129
+ Generate humorous classification for a detected person.
130
+
131
+ Args:
132
+ detection: Detection dict with bbox and confidence
133
+
134
+ Returns:
135
+ Classification dict with label and threat level
136
+ """
137
+ # Generate random threat assessment
138
+ threat_level = random.randint(45, 99)
139
+ label = random.choice(self.LABELS)
140
+
141
+ return {
142
+ 'threat_level': threat_level,
143
+ 'label': label,
144
+ 'confidence': detection['confidence']
145
+ }
146
+
147
+
148
+ # ============================================================================
149
+ # ANNOTATION LAYER
150
+ # Customize this section for different visual styles
151
+ # ============================================================================
152
+
153
+ class FrameAnnotator:
154
+ """
155
+ Draws annotations on frames.
156
+
157
+ Modify this to:
158
+ - Change colors, styles, fonts
159
+ - Add different visualization modes
160
+ - Include overlay graphics or warnings
161
+ - Show statistics or heatmaps
162
+ """
163
+
164
+ def __init__(self):
165
+ """Initialize annotator with color schemes."""
166
+ self.colors = {
167
+ 'high_threat': (0, 0, 255), # Red
168
+ 'medium_threat': (0, 165, 255), # Orange
169
+ 'low_threat': (0, 255, 255), # Yellow
170
+ 'text_bg': (0, 0, 0), # Black
171
+ 'text': (255, 255, 255) # White
172
+ }
173
+
174
+ def get_threat_color(self, threat_level: int) -> Tuple[int, int, int]:
175
+ """Get color based on threat level."""
176
+ if threat_level >= 80:
177
+ return self.colors['high_threat']
178
+ elif threat_level >= 60:
179
+ return self.colors['medium_threat']
180
+ else:
181
+ return self.colors['low_threat']
182
+
183
+ def annotate_frame(
184
+ self,
185
+ frame: np.ndarray,
186
+ detections: List[Dict],
187
+ classifications: List[Dict]
188
+ ) -> np.ndarray:
189
+ """
190
+ Draw annotations on frame.
191
+
192
+ Args:
193
+ frame: Input frame
194
+ detections: List of detection dicts
195
+ classifications: List of classification dicts
196
+
197
+ Returns:
198
+ Annotated frame
199
+ """
200
+ annotated = frame.copy()
201
+
202
+ # Draw header
203
+ self._draw_header(annotated, len(detections))
204
+
205
+ # Annotate each detection
206
+ for detection, classification in zip(detections, classifications):
207
+ self._draw_detection(annotated, detection, classification)
208
+
209
+ return annotated
210
+
211
+ def _draw_header(self, frame: np.ndarray, num_suspects: int):
212
+ """Draw header with suspect count."""
213
+ header_text = f"🚨 SUSPECTS DETECTED: {num_suspects} 🚨"
214
+ font = cv2.FONT_HERSHEY_DUPLEX
215
+ font_scale = 0.8
216
+ thickness = 2
217
+
218
+ # Get text size
219
+ (text_width, text_height), baseline = cv2.getTextSize(
220
+ header_text, font, font_scale, thickness
221
+ )
222
+
223
+ # Draw background
224
+ cv2.rectangle(
225
+ frame,
226
+ (0, 0),
227
+ (frame.shape[1], text_height + baseline + 20),
228
+ (0, 0, 0),
229
+ -1
230
+ )
231
+
232
+ # Draw text
233
+ x = (frame.shape[1] - text_width) // 2
234
+ y = text_height + 10
235
+ cv2.putText(
236
+ frame, header_text, (x, y),
237
+ font, font_scale, (0, 0, 255), thickness
238
+ )
239
+
240
+ def _draw_detection(
241
+ self,
242
+ frame: np.ndarray,
243
+ detection: Dict,
244
+ classification: Dict
245
+ ):
246
+ """Draw bounding box and labels for a detection."""
247
+ x1, y1, x2, y2 = detection['bbox']
248
+ threat_level = classification['threat_level']
249
+ color = self.get_threat_color(threat_level)
250
+
251
+ # Draw bounding box
252
+ cv2.rectangle(frame, (x1, y1), (x2, y2), color, 3)
253
+
254
+ # Create single label with threat level
255
+ label = f"{classification['label']} ({threat_level}%)"
256
+
257
+ # Draw label with larger, more readable text
258
+ font = cv2.FONT_HERSHEY_DUPLEX
259
+ font_scale = 0.7
260
+ thickness = 2
261
+ padding = 8
262
+
263
+ (text_width, text_height), baseline = cv2.getTextSize(
264
+ label, font, font_scale, thickness
265
+ )
266
+
267
+ # Position label above bounding box, or below if too close to top
268
+ y_offset = y1 - 10
269
+ if y_offset - text_height - padding < 0:
270
+ y_offset = y2 + text_height + padding + 10
271
+
272
+ # Draw background rectangle
273
+ cv2.rectangle(
274
+ frame,
275
+ (x1, y_offset - text_height - padding),
276
+ (x1 + text_width + padding * 2, y_offset + baseline + padding),
277
+ self.colors['text_bg'],
278
+ -1
279
+ )
280
+
281
+ # Draw text
282
+ cv2.putText(
283
+ frame,
284
+ label,
285
+ (x1 + padding, y_offset),
286
+ font,
287
+ font_scale,
288
+ color,
289
+ thickness
290
+ )
291
+
292
+
293
+ # ============================================================================
294
+ # STREAMING HANDLER
295
+ # Main processing pipeline
296
+ # ============================================================================
297
+
298
+ class MurdererDetector:
299
+ """
300
+ Main application class that combines all modules.
301
+ """
302
+
303
+ def __init__(self):
304
+ """Initialize all components."""
305
+ print("πŸ” Initializing Murderer Detector...")
306
+ self.detector = PersonDetector(model_name="yolov8n.pt", confidence=0.5)
307
+ self.classifier = MurdererClassifier()
308
+ self.annotator = FrameAnnotator()
309
+ print("βœ… Ready to detect suspicious individuals!")
310
+
311
+ def process_frame(self, frame: np.ndarray) -> np.ndarray:
312
+ """
313
+ Process a single frame.
314
+
315
+ Args:
316
+ frame: Input frame from webcam
317
+
318
+ Returns:
319
+ Annotated frame
320
+ """
321
+ if frame is None:
322
+ return None
323
+
324
+ # Detect all persons
325
+ all_detections = self.detector.detect_persons(frame)
326
+
327
+ # Filter out the user (largest person, presumably closest to camera)
328
+ # Only flag people behind the user
329
+ detections = self._filter_user(all_detections)
330
+
331
+ # Classify each detection
332
+ classifications = [
333
+ self.classifier.classify(det) for det in detections
334
+ ]
335
+
336
+ # Annotate frame
337
+ annotated = self.annotator.annotate_frame(
338
+ frame, detections, classifications
339
+ )
340
+
341
+ return annotated
342
+
343
+ def _filter_user(self, detections: List[Dict]) -> List[Dict]:
344
+ """
345
+ Filter out the user (largest person) from detections.
346
+
347
+ The assumption is that the user is sitting in front of the webcam
348
+ and will be the largest person in the frame. We want to flag only
349
+ people behind them.
350
+
351
+ Args:
352
+ detections: List of all person detections
353
+
354
+ Returns:
355
+ Filtered detections excluding the user
356
+ """
357
+ if len(detections) <= 1:
358
+ # If only one person or no people, don't flag anyone
359
+ return []
360
+
361
+ # Calculate area for each detection
362
+ detections_with_area = []
363
+ for det in detections:
364
+ x1, y1, x2, y2 = det['bbox']
365
+ area = (x2 - x1) * (y2 - y1)
366
+ detections_with_area.append((det, area))
367
+
368
+ # Sort by area (largest first)
369
+ detections_with_area.sort(key=lambda x: x[1], reverse=True)
370
+
371
+ # Return all except the largest (the user)
372
+ return [det for det, _ in detections_with_area[1:]]
373
+
374
+
375
+ # ============================================================================
376
+ # GRADIO INTERFACE
377
+ # ============================================================================
378
+
379
+ def create_interface():
380
+ """Create and configure the Gradio interface."""
381
+
382
+ # Initialize detector
383
+ app = MurdererDetector()
384
+
385
+ # Create interface
386
+ with gr.Blocks(title="Murderer Detector πŸ”ͺ") as demo:
387
+
388
+ gr.Markdown("""
389
+ # πŸ”ͺ Murderer Detector πŸ”
390
+
391
+ **DISCLAIMER:** This is for funs.
392
+ """)
393
+
394
+ # Unified webcam display (input and output combined)
395
+ webcam = gr.Image(
396
+ sources="webcam",
397
+ streaming=True,
398
+ label="Murderer Detector (requires webcam on)"
399
+ )
400
+
401
+ gr.Markdown("""
402
+ # πŸ“Š How It Works
403
+
404
+ 1. ** Enable your webcam ** - Click the webcam button above
405
+ 2. ** Detects creepers behind you **
406
+
407
+ # 🎯 Detection Features
408
+
409
+ - Real-time person detection using YOLOv8
410
+ - Threat level assessment(totally scientific πŸ˜…)
411
+ - Color-coded danger ratings
412
+ - Running suspect count
413
+ """)
414
+
415
+ # Set up streaming (unified input/output)
416
+ webcam.stream(
417
+ fn=app.process_frame,
418
+ inputs=[webcam],
419
+ outputs=[webcam],
420
+ stream_every=0.1,
421
+ concurrency_limit=30
422
+ )
423
+
424
+ return demo
425
+
426
+
427
+ # ============================================================================
428
+ # MAIN
429
+ # ============================================================================
430
+
431
+ if __name__ == "__main__":
432
+ demo = create_interface()
433
+ demo.launch(share=True)
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ gradio==6.0.1
2
+ opencv-python-headless==4.10.0.84
3
+ numpy==1.26.4
4
+ pillow==10.4.0
5
+ ultralytics>=8.3.0