nsr51324 commited on
Commit
9aa20d6
·
verified ·
1 Parent(s): 83c4397

Upload UI.py

Browse files
Files changed (1) hide show
  1. UI.py +236 -0
UI.py ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from collections import Counter
4
+ from pathlib import Path
5
+
6
+ import gradio as gr
7
+
8
+ from ultralytics import YOLO
9
+
10
+ ROOT = Path(__file__).resolve().parent
11
+
12
+ MODEL_CANDIDATES = [
13
+ ROOT / "runs" / "detect" / "yolov8_road-2" / "weights" / "best.pt",
14
+ ROOT / "runs" / "detect" / "yolov8_road" / "weights" / "best.pt",
15
+ ROOT / "best.pt",
16
+ ROOT / "yolov8n.pt",
17
+ ]
18
+
19
+ MODEL_PATH = next((path for path in MODEL_CANDIDATES if path.exists()), None)
20
+ if MODEL_PATH is None:
21
+ raise FileNotFoundError(
22
+ "No model weights file was found. Please place 'best.pt' inside the "
23
+ "'weights' folder or in the project root."
24
+ )
25
+
26
+ model = YOLO(str(MODEL_PATH))
27
+
28
+
29
+ def detect_damage(image):
30
+ if image is None:
31
+ raise gr.Error("Please upload an image before starting detection.")
32
+
33
+ result = model(image, conf=0.25, imgsz=640, stream=False)[0]
34
+ annotated_image = result.plot()
35
+
36
+ boxes = result.boxes
37
+ if boxes is None or len(boxes) == 0:
38
+ summary = "✅ No damage was detected in this image."
39
+ return annotated_image, summary
40
+
41
+ detected_names = []
42
+ confidences = []
43
+ for box in boxes:
44
+ class_id = int(box.cls.item())
45
+ class_name = model.names[class_id]
46
+ confidence = round(float(box.conf.item()), 2)
47
+ detected_names.append(class_name)
48
+ confidences.append(confidence)
49
+
50
+ counts = Counter(detected_names)
51
+ lines = []
52
+ lines.append(f"Total objects detected: {len(detected_names)}")
53
+ lines.append("")
54
+ lines.append("Breakdown by type:")
55
+ for name, count in counts.items():
56
+ lines.append(f" • {name}: {count}")
57
+ lines.append("")
58
+ lines.append("Confidence scores:")
59
+ for name, confidence in zip(detected_names, confidences):
60
+ lines.append(f" • {name}: {confidence:.2f}")
61
+
62
+ summary = "\n".join(lines)
63
+ return annotated_image, summary
64
+
65
+
66
+ CUSTOM_CSS = """
67
+ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700;800&family=Inter:wght@400;500;600&display=swap');
68
+
69
+ * {
70
+ font-family: 'Inter', 'Poppins', sans-serif !important;
71
+ }
72
+
73
+ .gradio-container {
74
+ background: radial-gradient(circle at 10% 0%, #1e293b 0%, #0f172a 45%, #020617 100%) !important;
75
+ }
76
+
77
+ .hero {
78
+ background: linear-gradient(120deg, #0ea5e9 0%, #2563eb 45%, #7c3aed 100%);
79
+ padding: 42px 40px;
80
+ border-radius: 24px;
81
+ color: #ffffff;
82
+ box-shadow: 0 20px 45px rgba(37, 99, 235, 0.35);
83
+ position: relative;
84
+ overflow: hidden;
85
+ margin-bottom: 24px;
86
+ border: 1px solid rgba(255,255,255,0.15);
87
+ }
88
+
89
+ .hero::after {
90
+ content: "";
91
+ position: absolute;
92
+ top: -60px;
93
+ right: -60px;
94
+ width: 220px;
95
+ height: 220px;
96
+ background: rgba(255,255,255,0.08);
97
+ border-radius: 50%;
98
+ }
99
+
100
+ .hero-eyebrow {
101
+ display: inline-block;
102
+ font-size: 12px;
103
+ letter-spacing: 2px;
104
+ text-transform: uppercase;
105
+ font-weight: 600;
106
+ background: rgba(255,255,255,0.15);
107
+ padding: 6px 14px;
108
+ border-radius: 999px;
109
+ margin-bottom: 14px;
110
+ backdrop-filter: blur(4px);
111
+ }
112
+
113
+ .hero-title {
114
+ font-family: 'Poppins', sans-serif !important;
115
+ font-size: 34px;
116
+ font-weight: 800;
117
+ margin: 0 0 10px 0;
118
+ letter-spacing: -0.5px;
119
+ }
120
+
121
+ .hero-subtitle {
122
+ font-size: 15.5px;
123
+ color: rgba(255,255,255,0.9);
124
+ max-width: 640px;
125
+ line-height: 1.6;
126
+ font-weight: 400;
127
+ }
128
+
129
+ .panel {
130
+ border: 1px solid rgba(148, 163, 184, 0.18) !important;
131
+ border-radius: 20px !important;
132
+ padding: 22px !important;
133
+ background: rgba(15, 23, 42, 0.6) !important;
134
+ backdrop-filter: blur(10px);
135
+ box-shadow: 0 10px 30px rgba(0,0,0,0.25);
136
+ }
137
+
138
+ .panel-title {
139
+ font-family: 'Poppins', sans-serif !important;
140
+ font-size: 17px;
141
+ font-weight: 700;
142
+ color: #e2e8f0 !important;
143
+ margin-bottom: 4px;
144
+ display: flex;
145
+ align-items: center;
146
+ gap: 8px;
147
+ }
148
+
149
+ .panel-caption {
150
+ font-size: 13px;
151
+ color: #94a3b8 !important;
152
+ margin-bottom: 14px;
153
+ }
154
+
155
+ .primary-btn {
156
+ background: linear-gradient(90deg, #2563eb, #7c3aed) !important;
157
+ border: none !important;
158
+ color: white !important;
159
+ font-weight: 600 !important;
160
+ border-radius: 12px !important;
161
+ box-shadow: 0 8px 20px rgba(124, 58, 237, 0.35) !important;
162
+ transition: transform 0.15s ease, box-shadow 0.15s ease !important;
163
+ }
164
+
165
+ .primary-btn:hover {
166
+ transform: translateY(-1px);
167
+ box-shadow: 0 10px 26px rgba(124, 58, 237, 0.45) !important;
168
+ }
169
+
170
+ footer {
171
+ display: none !important;
172
+ }
173
+ """
174
+
175
+ with gr.Blocks(
176
+ theme=gr.themes.Soft(
177
+ primary_hue="blue",
178
+ secondary_hue="violet",
179
+ neutral_hue="slate",
180
+ ),
181
+ css=CUSTOM_CSS,
182
+ title="Road Damage Detection Studio",
183
+ ) as demo:
184
+ gr.HTML(
185
+ """
186
+ <div class="hero">
187
+ <span class="hero-eyebrow">AI Vision · Infrastructure Inspection</span>
188
+ <div class="hero-title">🛣️ Road Damage Detection Studio</div>
189
+ <div class="hero-subtitle">
190
+ Upload a photo of a road surface and let the detection engine
191
+ automatically locate, classify, and score every type of damage
192
+ — cracks, potholes, and more — in seconds.
193
+ </div>
194
+ </div>
195
+ """
196
+ )
197
+
198
+ with gr.Row(equal_height=True):
199
+ with gr.Column(scale=1):
200
+ with gr.Group(elem_classes=["panel"]):
201
+ gr.HTML('<div class="panel-title">📤 Upload Image</div>')
202
+ gr.HTML('<div class="panel-caption">Choose a clear photo of the road surface to analyze.</div>')
203
+ image_input = gr.Image(
204
+ label="",
205
+ type="pil",
206
+ height=420,
207
+ sources=["upload"],
208
+ )
209
+ run_btn = gr.Button("✨ Run Detection", variant="primary", elem_classes=["primary-btn"])
210
+
211
+ with gr.Column(scale=1):
212
+ with gr.Group(elem_classes=["panel"]):
213
+ gr.HTML('<div class="panel-title">🔎 Detection Result</div>')
214
+ gr.HTML('<div class="panel-caption">Annotated image and detailed summary will appear here.</div>')
215
+ output_image = gr.Image(label="", height=420)
216
+ output_text = gr.Textbox(
217
+ label="Summary",
218
+ lines=12,
219
+ max_lines=20,
220
+ )
221
+
222
+ run_btn.click(
223
+ fn=detect_damage,
224
+ inputs=[image_input],
225
+ outputs=[output_image, output_text],
226
+ api_name="detect_damage",
227
+ )
228
+
229
+
230
+ if __name__ == "__main__":
231
+ demo.launch(
232
+ server_name="0.0.0.0",
233
+ server_port=7860,
234
+ share=False,
235
+ debug=False,
236
+ )