xiaoxinny commited on
Commit
1b323a6
·
verified ·
1 Parent(s): 0526d20

Added updated files

Browse files
Files changed (7) hide show
  1. .gitattributes +2 -0
  2. .gitignore +1 -0
  3. app.py +252 -4
  4. best.pt +3 -0
  5. output.jpg +3 -0
  6. output.mp4 +3 -0
  7. requirements.txt +0 -0
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.mp4 filter=lfs diff=lfs merge=lfs -text
37
+ *.jpg filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ .idea/
app.py CHANGED
@@ -1,7 +1,255 @@
1
  import gradio as gr
 
 
 
 
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ import cv2
3
+ import numpy as np
4
+ from ultralytics import YOLO
5
+ import threading
6
+ import time
7
 
8
+ # Load YOLO model
9
+ model = YOLO("best.pt")
10
+ CLASS_NAMES = ["hard hat", "mask"]
11
 
12
+ # Global variables for camera streaming
13
+ camera_active = False
14
+ current_frame = None
15
+ frame_lock = threading.Lock()
16
+
17
+ # -------------------
18
+ # Video File Processing
19
+ # -------------------
20
+ def predict_video(input_file, selected_classes):
21
+ if input_file is None:
22
+ return None, "No file uploaded"
23
+
24
+ cap = cv2.VideoCapture(input_file)
25
+ if not cap.isOpened():
26
+ return None, "Could not read input file"
27
+
28
+ # Video writer setup
29
+ fourcc = cv2.VideoWriter_fourcc(*"mp4v")
30
+ fps = cap.get(cv2.CAP_PROP_FPS)
31
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
32
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
33
+ out_path = "output.mp4"
34
+ out = cv2.VideoWriter(out_path, fourcc, fps, (width, height))
35
+
36
+ tally_counts = {cls: 0 for cls in selected_classes}
37
+
38
+ while True:
39
+ ret, frame = cap.read()
40
+ if not ret:
41
+ break
42
+
43
+ results = model.predict(frame, conf=0.25, verbose=False)
44
+ frame_out = frame.copy()
45
+
46
+ for r in results:
47
+ for box in r.boxes:
48
+ cls_id = int(box.cls[0])
49
+ conf = float(box.conf[0])
50
+ label = CLASS_NAMES[cls_id] if cls_id < len(CLASS_NAMES) else f"cls{cls_id}"
51
+
52
+ if label in selected_classes:
53
+ x1, y1, x2, y2 = map(int, box.xyxy[0])
54
+ cv2.rectangle(frame_out, (x1, y1), (x2, y2), (0, 255, 0), 2)
55
+ cv2.putText(frame_out, f"{label} {conf:.2f}",
56
+ (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6,
57
+ (0, 255, 0), 2)
58
+ tally_counts[label] += 1
59
+
60
+ out.write(frame_out)
61
+
62
+ cap.release()
63
+ out.release()
64
+
65
+ tally_text = "\n".join([f"{cls}: {count} detections" for cls, count in tally_counts.items()])
66
+ return out_path, tally_text
67
+
68
+ # -------------------
69
+ # Live Camera Functions
70
+ # -------------------
71
+ def camera_thread():
72
+ """Background thread to capture camera frames"""
73
+ global camera_active, current_frame
74
+
75
+ cap = cv2.VideoCapture(0)
76
+ if not cap.isOpened():
77
+ print("Error: Could not open camera")
78
+ return
79
+
80
+ # Set camera properties for better performance
81
+ cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
82
+ cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
83
+ cap.set(cv2.CAP_PROP_FPS, 30)
84
+
85
+ while camera_active:
86
+ ret, frame = cap.read()
87
+ if ret:
88
+ with frame_lock:
89
+ current_frame = frame.copy()
90
+ time.sleep(0.033) # ~30 FPS
91
+
92
+ cap.release()
93
+
94
+ def start_camera():
95
+ """Start the camera streaming"""
96
+ global camera_active
97
+ camera_active = True
98
+ camera_thread_obj = threading.Thread(target=camera_thread, daemon=True)
99
+ camera_thread_obj.start()
100
+ return "Camera started"
101
+
102
+ def stop_camera():
103
+ """Stop the camera streaming"""
104
+ global camera_active
105
+ camera_active = False
106
+ return "Camera stopped"
107
+
108
+ def get_camera_frame(selected_classes):
109
+ """Get current camera frame with detections"""
110
+ global current_frame
111
+
112
+ if not camera_active or current_frame is None:
113
+ return None
114
+
115
+ with frame_lock:
116
+ frame = current_frame.copy()
117
+
118
+ # Run YOLO detection
119
+ results = model.predict(frame, conf=0.25, verbose=False)
120
+ frame_out = frame.copy()
121
+
122
+ detection_count = {cls: 0 for cls in selected_classes}
123
+
124
+ for r in results:
125
+ for box in r.boxes:
126
+ cls_id = int(box.cls[0])
127
+ conf = float(box.conf[0])
128
+ label = CLASS_NAMES[cls_id] if cls_id < len(CLASS_NAMES) else f"cls{cls_id}"
129
+
130
+ if label in selected_classes:
131
+ x1, y1, x2, y2 = map(int, box.xyxy[0])
132
+ cv2.rectangle(frame_out, (x1, y1), (x2, y2), (0, 255, 0), 2)
133
+ cv2.putText(frame_out, f"{label} {conf:.2f}",
134
+ (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6,
135
+ (0, 255, 0), 2)
136
+ detection_count[label] += 1
137
+
138
+ # Convert BGR to RGB for Gradio
139
+ frame_rgb = cv2.cvtColor(frame_out, cv2.COLOR_BGR2RGB)
140
+
141
+ # Create tally text
142
+ tally_text = "\n".join([f"{cls}: {count} detections" for cls, count in detection_count.items()])
143
+
144
+ return frame_rgb, tally_text
145
+
146
+ # -------------------
147
+ # Dynamic UI Update
148
+ # -------------------
149
+ def update_ui(mode):
150
+ if mode == "Upload Video":
151
+ return (
152
+ gr.update(visible=True), # input_file
153
+ gr.update(visible=True), # output_video
154
+ gr.update(visible=False), # output_img
155
+ gr.update(visible=True), # run_btn
156
+ gr.update(visible=False), # start_btn
157
+ gr.update(visible=False), # stop_btn
158
+ gr.update(visible=False) # live_display
159
+ )
160
+ else: # Live Camera
161
+ return (
162
+ gr.update(visible=False), # input_file
163
+ gr.update(visible=False), # output_video
164
+ gr.update(visible=True), # output_img
165
+ gr.update(visible=False), # run_btn
166
+ gr.update(visible=True), # start_btn
167
+ gr.update(visible=True), # stop_btn
168
+ gr.update(visible=True) # live_display
169
+ )
170
+
171
+ # -------------------
172
+ # Gradio Interface
173
+ # -------------------
174
+ with gr.Blocks() as demo:
175
+ gr.Markdown("## 🦺 YOLOv11 Hard Hat & Mask Detector")
176
+
177
+ with gr.Row():
178
+ with gr.Column():
179
+ mode = gr.Radio(["Upload Video", "Live Camera"], value="Upload Video", label="Mode")
180
+ input_file = gr.File(label="Upload Video", type="filepath", visible=True)
181
+ class_toggle = gr.CheckboxGroup(CLASS_NAMES, value=["hard hat", "mask"], label="Select classes")
182
+
183
+ # Buttons
184
+ run_btn = gr.Button("Run Detection", visible=True)
185
+ start_btn = gr.Button("Start Camera", visible=False)
186
+ stop_btn = gr.Button("Stop Camera", visible=False)
187
+
188
+ with gr.Column():
189
+ output_video = gr.Video(label="Detection Output", visible=True)
190
+ output_img = gr.Image(type="numpy", label="Live Detection", visible=False)
191
+ tally_box = gr.Textbox(label="Detection Count", interactive=False)
192
+
193
+ # Live display component (hidden initially)
194
+ live_display = gr.HTML(visible=False)
195
+
196
+ # Dynamically show/hide components based on mode
197
+ mode.change(
198
+ update_ui,
199
+ inputs=mode,
200
+ outputs=[input_file, output_video, output_img, run_btn, start_btn, stop_btn, live_display]
201
+ )
202
+
203
+ # Video processing
204
+ def run_detection(input_file, selected_classes):
205
+ return predict_video(input_file, selected_classes)
206
+
207
+ run_btn.click(
208
+ run_detection,
209
+ inputs=[input_file, class_toggle],
210
+ outputs=[output_video, tally_box]
211
+ )
212
+
213
+ # Camera controls
214
+ start_btn.click(start_camera, outputs=tally_box)
215
+ stop_btn.click(stop_camera, outputs=tally_box)
216
+
217
+ # Live camera feed update
218
+ def update_live_feed(selected_classes):
219
+ if camera_active:
220
+ return get_camera_frame(selected_classes)
221
+ return None, ""
222
+
223
+ # Manual refresh button for live feed
224
+ with gr.Row():
225
+ refresh_btn = gr.Button("Refresh Live Feed", visible=False)
226
+
227
+ # Update refresh button visibility based on mode
228
+ def update_refresh_visibility(mode):
229
+ return gr.update(visible=(mode == "Live Camera"))
230
+
231
+ mode.change(update_refresh_visibility, inputs=mode, outputs=refresh_btn)
232
+
233
+ # Add refresh functionality
234
+ refresh_btn.click(
235
+ update_live_feed,
236
+ inputs=[class_toggle],
237
+ outputs=[output_img, tally_box]
238
+ )
239
+
240
+ # Timer-based update for live camera (runs every 500ms when in live mode)
241
+ def timer_update(selected_classes, mode):
242
+ if mode == "Live Camera" and camera_active:
243
+ return update_live_feed(selected_classes)
244
+ return gr.update(), ""
245
+
246
+ # Create a timer that updates the live feed
247
+ timer = gr.Timer(value=0.5) # 500ms intervals
248
+ timer.tick(
249
+ fn=timer_update,
250
+ inputs=[class_toggle, mode],
251
+ outputs=[output_img, tally_box]
252
+ )
253
+
254
+ if __name__ == "__main__":
255
+ demo.launch()
best.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:71be841c1a725de4b3d732effb126bbb3f90868749f6eeadb234bd184d10aa44
3
+ size 5475546
output.jpg ADDED

Git LFS Details

  • SHA256: 7270a38e405a3b4c9d5a38ba073987f00858078198a7a2969a05c4e3332b7262
  • Pointer size: 132 Bytes
  • Size of remote file: 1.36 MB
output.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f3a5975b46d38db8ed5a40c049e4a3f4b9b3cbe7c0e8ccb9c98ff5cc5e3fb0c6
3
+ size 106419
requirements.txt ADDED
Binary file (2.68 kB). View file