EYEDOL commited on
Commit
16dba1f
Β·
verified Β·
1 Parent(s): 0b23032

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +115 -0
  2. requirements.txt +7 -0
app.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from ultralytics import YOLO
3
+ from PIL import Image
4
+ import numpy as np
5
+ import cv2
6
+
7
+ # Load YOLOv8 model once at startup
8
+ model = YOLO("yolov8n.pt") # nano model β€” fast and free, good for demo
9
+
10
+ def count_people(image):
11
+ if image is None:
12
+ return None, "No image uploaded."
13
+
14
+ # Convert PIL image to numpy array (BGR for OpenCV)
15
+ img_array = np.array(image)
16
+ img_bgr = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR)
17
+
18
+ # Run YOLO inference β€” only detect class 0 (person)
19
+ results = model(img_bgr, classes=[0], conf=0.4)
20
+
21
+ # Get detections
22
+ result = results[0]
23
+ boxes = result.boxes
24
+ count = len(boxes)
25
+
26
+ # Draw bounding boxes on the image
27
+ annotated = img_bgr.copy()
28
+ for box in boxes:
29
+ x1, y1, x2, y2 = map(int, box.xyxy[0])
30
+ conf = float(box.conf[0])
31
+ cv2.rectangle(annotated, (x1, y1), (x2, y2), (0, 200, 100), 2)
32
+ label = f"Person {conf:.0%}"
33
+ cv2.putText(annotated, label, (x1, y1 - 8),
34
+ cv2.FONT_HERSHEY_SIMPLEX, 0.55, (0, 200, 100), 2)
35
+
36
+ # Add count overlay at top
37
+ overlay_text = f"Total People Detected: {count}"
38
+ cv2.rectangle(annotated, (0, 0), (len(overlay_text) * 14 + 20, 45), (0, 0, 0), -1)
39
+ cv2.putText(annotated, overlay_text, (10, 30),
40
+ cv2.FONT_HERSHEY_SIMPLEX, 0.85, (255, 255, 255), 2)
41
+
42
+ # Convert back to RGB for display
43
+ annotated_rgb = cv2.cvtColor(annotated, cv2.COLOR_BGR2RGB)
44
+ output_image = Image.fromarray(annotated_rgb)
45
+
46
+ # Summary text
47
+ if count == 0:
48
+ summary = "πŸ‘€ No people detected in this image."
49
+ elif count == 1:
50
+ summary = "πŸ‘€ 1 person detected."
51
+ else:
52
+ summary = f"πŸ‘₯ {count} people detected."
53
+
54
+ return output_image, summary
55
+
56
+
57
+ # --- Gradio UI ---
58
+ with gr.Blocks(
59
+ title="People Counter β€” YOLOv8",
60
+ theme=gr.themes.Base(
61
+ primary_hue="emerald",
62
+ neutral_hue="slate",
63
+ font=gr.themes.GoogleFont("DM Sans"),
64
+ ),
65
+ css="""
66
+ body { background: #0f1117; }
67
+ .gradio-container { max-width: 860px !important; margin: auto; }
68
+ #title { text-align: center; padding: 2rem 0 0.5rem; }
69
+ #title h1 { font-size: 2.2rem; font-weight: 800; color: #f1f5f9; letter-spacing: -0.5px; }
70
+ #title p { color: #94a3b8; font-size: 1rem; margin-top: 0.3rem; }
71
+ #count-box textarea {
72
+ font-size: 1.3rem !important;
73
+ font-weight: 700 !important;
74
+ text-align: center !important;
75
+ color: #34d399 !important;
76
+ background: #1e293b !important;
77
+ border: 1px solid #334155 !important;
78
+ border-radius: 10px !important;
79
+ }
80
+ .upload-btn { background: #10b981 !important; color: white !important; font-weight: 700 !important; }
81
+ footer { display: none !important; }
82
+ """
83
+ ) as demo:
84
+
85
+ with gr.Column(elem_id="title"):
86
+ gr.HTML("<h1>πŸ” People Counter</h1>")
87
+ gr.HTML("<p>Upload an image β€” YOLOv8 will detect and count every person in it.</p>")
88
+
89
+ with gr.Row():
90
+ with gr.Column():
91
+ input_image = gr.Image(type="pil", label="Upload Image", height=380)
92
+ run_btn = gr.Button("Count People β†’", variant="primary", elem_classes="upload-btn")
93
+
94
+ with gr.Column():
95
+ output_image = gr.Image(type="pil", label="Detection Result", height=380)
96
+ output_text = gr.Textbox(
97
+ label="Count",
98
+ interactive=False,
99
+ elem_id="count-box",
100
+ lines=1
101
+ )
102
+
103
+ run_btn.click(
104
+ fn=count_people,
105
+ inputs=input_image,
106
+ outputs=[output_image, output_text]
107
+ )
108
+
109
+ gr.HTML("""
110
+ <div style='text-align:center; color:#475569; font-size:0.8rem; padding: 1.5rem 0 0.5rem;'>
111
+ Powered by <strong>Ultralytics YOLOv8</strong> Β· Model: yolov8n Β· Class: Person Β· Conf: 0.4
112
+ </div>
113
+ """)
114
+
115
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ ultralytics==8.3.0
2
+ gradio==4.44.0
3
+ opencv-python-headless==4.10.0.84
4
+ Pillow==10.4.0
5
+ numpy==1.26.4
6
+ torch==2.4.0
7
+ torchvision==0.19.0