Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -10,9 +10,9 @@ from huggingface_hub import hf_hub_download
|
|
| 10 |
import warnings
|
| 11 |
warnings.filterwarnings('ignore')
|
| 12 |
|
| 13 |
-
# ============================================
|
| 14 |
-
# 1. LOAD MODELS
|
| 15 |
-
# ============================================
|
| 16 |
print("Loading YOLOv11 model from Hugging Face Hub...")
|
| 17 |
model_path = hf_hub_download(
|
| 18 |
repo_id="SkyGuardAI/drone-detection-yolov11",
|
|
@@ -30,9 +30,9 @@ blip_model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image
|
|
| 30 |
blip_model.eval()
|
| 31 |
print("BLIP model loaded successfully.")
|
| 32 |
|
| 33 |
-
# ============================================
|
| 34 |
# 2. HEATMAP FUNCTIONS
|
| 35 |
-
# ============================================
|
| 36 |
layer_outputs = {}
|
| 37 |
|
| 38 |
def hook_fn(module, input, output):
|
|
@@ -90,9 +90,9 @@ def generate_heatmap(model, image):
|
|
| 90 |
print(f"Heatmap error: {e}")
|
| 91 |
return None
|
| 92 |
|
| 93 |
-
# ============================================
|
| 94 |
# 3. DYNAMIC CAPTION (BLIP)
|
| 95 |
-
# ============================================
|
| 96 |
def generate_dynamic_caption(image):
|
| 97 |
try:
|
| 98 |
if isinstance(image, np.ndarray):
|
|
@@ -114,9 +114,9 @@ def generate_dynamic_caption(image):
|
|
| 114 |
print(f"Caption error: {e}")
|
| 115 |
return "AI model is analyzing the scene."
|
| 116 |
|
| 117 |
-
# ============================================
|
| 118 |
# 4. XAI REPORT
|
| 119 |
-
# ============================================
|
| 120 |
def build_xai_report(is_drone, confidence, drone_count, processing_time, image_caption):
|
| 121 |
if is_drone:
|
| 122 |
drone_text = "a drone" if drone_count == 1 else f"{drone_count} drones"
|
|
@@ -208,9 +208,9 @@ Scattered activation pattern confirms absence of strong drone-like features.
|
|
| 208 |
"""
|
| 209 |
return report
|
| 210 |
|
| 211 |
-
# ============================================
|
| 212 |
# 5. MAIN PIPELINE FUNCTION
|
| 213 |
-
# ============================================
|
| 214 |
def drone_detection_pipeline(input_image):
|
| 215 |
try:
|
| 216 |
if isinstance(input_image, Image.Image):
|
|
@@ -257,99 +257,92 @@ def drone_detection_pipeline(input_image):
|
|
| 257 |
blank = np.zeros((480, 640, 3), dtype=np.uint8)
|
| 258 |
return blank, blank, error_msg
|
| 259 |
|
| 260 |
-
# ============================================
|
| 261 |
-
# 6. SKYGUARD
|
| 262 |
-
# ============================================
|
| 263 |
custom_css = """
|
| 264 |
-
/*
|
| 265 |
-
.gradio-container {
|
| 266 |
-
background:
|
| 267 |
-
font-family: 'Segoe UI', 'Roboto', '
|
| 268 |
}
|
| 269 |
-
/* Header styling */
|
| 270 |
.skyguard-header {
|
| 271 |
text-align: center;
|
| 272 |
padding: 1.5rem 0 0.5rem 0;
|
| 273 |
-
border-bottom: 2px solid #f5c518;
|
| 274 |
margin-bottom: 1.5rem;
|
| 275 |
}
|
| 276 |
.skyguard-header h1 {
|
| 277 |
font-size: 3rem;
|
| 278 |
font-weight: 800;
|
| 279 |
-
letter-spacing:
|
| 280 |
-
color: #
|
| 281 |
-
|
| 282 |
-
margin-bottom: 0;
|
| 283 |
}
|
| 284 |
.skyguard-header .tagline {
|
| 285 |
-
font-size: 1.
|
| 286 |
-
font-weight:
|
| 287 |
-
color: #
|
| 288 |
letter-spacing: 1px;
|
| 289 |
-
margin-top: 0.
|
| 290 |
}
|
| 291 |
.skyguard-header .sub {
|
| 292 |
-
font-size: 0.
|
| 293 |
-
color: #
|
| 294 |
margin-top: 0.5rem;
|
| 295 |
}
|
| 296 |
-
/* Buttons */
|
| 297 |
.gr-button-primary {
|
| 298 |
-
background:
|
| 299 |
-
border:
|
| 300 |
color: white !important;
|
| 301 |
font-weight: 700 !important;
|
| 302 |
border-radius: 30px !important;
|
| 303 |
-
padding: 10px
|
| 304 |
transition: all 0.2s ease !important;
|
| 305 |
text-transform: uppercase !important;
|
| 306 |
letter-spacing: 1px;
|
| 307 |
}
|
| 308 |
.gr-button-primary:hover {
|
|
|
|
| 309 |
transform: scale(1.02);
|
| 310 |
-
|
| 311 |
-
box-shadow: 0 0 12px rgba(245,197,24,0.3);
|
| 312 |
-
}
|
| 313 |
-
/* Tabs styling */
|
| 314 |
-
.tab-nav {
|
| 315 |
-
background-color: #0f1725 !important;
|
| 316 |
-
border-radius: 8px 8px 0 0;
|
| 317 |
}
|
|
|
|
| 318 |
.gr-tabs .tab-nav button {
|
| 319 |
-
background-color: #
|
| 320 |
-
color: #
|
| 321 |
font-weight: 600 !important;
|
| 322 |
border-radius: 8px 8px 0 0 !important;
|
| 323 |
-
padding:
|
| 324 |
-
margin-right:
|
| 325 |
}
|
| 326 |
.gr-tabs .tab-nav button.selected {
|
| 327 |
-
background-color: #
|
| 328 |
-
color:
|
| 329 |
-
border-bottom: 2px solid #f5c518 !important;
|
| 330 |
}
|
| 331 |
-
/* Input
|
| 332 |
.gr-box, .gr-form, .gr-input, .gr-panel {
|
| 333 |
-
background-color: #
|
| 334 |
-
border: 1px solid #
|
| 335 |
border-radius: 12px !important;
|
| 336 |
}
|
| 337 |
/* Labels */
|
| 338 |
label, .gr-form label {
|
| 339 |
-
color: #
|
| 340 |
font-weight: 500 !important;
|
| 341 |
}
|
| 342 |
-
/* Markdown text */
|
| 343 |
.gr-markdown p, .gr-markdown {
|
| 344 |
-
color: #
|
| 345 |
}
|
| 346 |
/* Footer */
|
| 347 |
.skyguard-footer {
|
| 348 |
text-align: center;
|
| 349 |
margin-top: 30px;
|
| 350 |
font-size: 12px;
|
| 351 |
-
color: #
|
| 352 |
-
border-top: 1px solid #
|
| 353 |
padding-top: 15px;
|
| 354 |
}
|
| 355 |
"""
|
|
@@ -360,7 +353,7 @@ with gr.Blocks(title="SkyGuard - Drone Detection System", theme=gr.themes.Soft()
|
|
| 360 |
<h1>SKYGUARD</h1>
|
| 361 |
<div class="tagline">SEE EVERY THREAT BEFORE IT LANDS</div>
|
| 362 |
<div class="sub">YOLOv11 Detection | Explainable AI (XAI) | BLIP Captioning</div>
|
| 363 |
-
<div class="sub" style="font-size:0.
|
| 364 |
</div>
|
| 365 |
""")
|
| 366 |
|
|
@@ -389,8 +382,8 @@ with gr.Blocks(title="SkyGuard - Drone Detection System", theme=gr.themes.Soft()
|
|
| 389 |
</div>
|
| 390 |
""")
|
| 391 |
|
| 392 |
-
# ============================================
|
| 393 |
# 7. RUN APP
|
| 394 |
-
# ============================================
|
| 395 |
if __name__ == "__main__":
|
| 396 |
demo.launch()
|
|
|
|
| 10 |
import warnings
|
| 11 |
warnings.filterwarnings('ignore')
|
| 12 |
|
| 13 |
+
# ============================================================
|
| 14 |
+
# 1. LOAD MODELS (CHANGE USERNAME BELOW)
|
| 15 |
+
# ============================================================
|
| 16 |
print("Loading YOLOv11 model from Hugging Face Hub...")
|
| 17 |
model_path = hf_hub_download(
|
| 18 |
repo_id="SkyGuardAI/drone-detection-yolov11",
|
|
|
|
| 30 |
blip_model.eval()
|
| 31 |
print("BLIP model loaded successfully.")
|
| 32 |
|
| 33 |
+
# ============================================================
|
| 34 |
# 2. HEATMAP FUNCTIONS
|
| 35 |
+
# ============================================================
|
| 36 |
layer_outputs = {}
|
| 37 |
|
| 38 |
def hook_fn(module, input, output):
|
|
|
|
| 90 |
print(f"Heatmap error: {e}")
|
| 91 |
return None
|
| 92 |
|
| 93 |
+
# ============================================================
|
| 94 |
# 3. DYNAMIC CAPTION (BLIP)
|
| 95 |
+
# ============================================================
|
| 96 |
def generate_dynamic_caption(image):
|
| 97 |
try:
|
| 98 |
if isinstance(image, np.ndarray):
|
|
|
|
| 114 |
print(f"Caption error: {e}")
|
| 115 |
return "AI model is analyzing the scene."
|
| 116 |
|
| 117 |
+
# ============================================================
|
| 118 |
# 4. XAI REPORT
|
| 119 |
+
# ============================================================
|
| 120 |
def build_xai_report(is_drone, confidence, drone_count, processing_time, image_caption):
|
| 121 |
if is_drone:
|
| 122 |
drone_text = "a drone" if drone_count == 1 else f"{drone_count} drones"
|
|
|
|
| 208 |
"""
|
| 209 |
return report
|
| 210 |
|
| 211 |
+
# ============================================================
|
| 212 |
# 5. MAIN PIPELINE FUNCTION
|
| 213 |
+
# ============================================================
|
| 214 |
def drone_detection_pipeline(input_image):
|
| 215 |
try:
|
| 216 |
if isinstance(input_image, Image.Image):
|
|
|
|
| 257 |
blank = np.zeros((480, 640, 3), dtype=np.uint8)
|
| 258 |
return blank, blank, error_msg
|
| 259 |
|
| 260 |
+
# ============================================================
|
| 261 |
+
# 6. SKYGUARD INTERFACE (WHITE BACKGROUND, DARK BLUE BUTTONS)
|
| 262 |
+
# ============================================================
|
| 263 |
custom_css = """
|
| 264 |
+
/* White background for main container and body */
|
| 265 |
+
.gradio-container, body, .gradio-container .main {
|
| 266 |
+
background: #ffffff !important;
|
| 267 |
+
font-family: 'Segoe UI', 'Roboto', 'Helvetica Neue', sans-serif;
|
| 268 |
}
|
| 269 |
+
/* Header styling - dark text, centered */
|
| 270 |
.skyguard-header {
|
| 271 |
text-align: center;
|
| 272 |
padding: 1.5rem 0 0.5rem 0;
|
|
|
|
| 273 |
margin-bottom: 1.5rem;
|
| 274 |
}
|
| 275 |
.skyguard-header h1 {
|
| 276 |
font-size: 3rem;
|
| 277 |
font-weight: 800;
|
| 278 |
+
letter-spacing: 3px;
|
| 279 |
+
color: #0a2b4e; /* dark blue */
|
| 280 |
+
margin-bottom: 0.2rem;
|
|
|
|
| 281 |
}
|
| 282 |
.skyguard-header .tagline {
|
| 283 |
+
font-size: 1.2rem;
|
| 284 |
+
font-weight: 600;
|
| 285 |
+
color: #1e4a76; /* medium dark blue */
|
| 286 |
letter-spacing: 1px;
|
| 287 |
+
margin-top: 0.2rem;
|
| 288 |
}
|
| 289 |
.skyguard-header .sub {
|
| 290 |
+
font-size: 0.9rem;
|
| 291 |
+
color: #2c5282;
|
| 292 |
margin-top: 0.5rem;
|
| 293 |
}
|
| 294 |
+
/* Buttons - dark blue */
|
| 295 |
.gr-button-primary {
|
| 296 |
+
background: #0a2b4e !important;
|
| 297 |
+
border: none !important;
|
| 298 |
color: white !important;
|
| 299 |
font-weight: 700 !important;
|
| 300 |
border-radius: 30px !important;
|
| 301 |
+
padding: 10px 28px !important;
|
| 302 |
transition: all 0.2s ease !important;
|
| 303 |
text-transform: uppercase !important;
|
| 304 |
letter-spacing: 1px;
|
| 305 |
}
|
| 306 |
.gr-button-primary:hover {
|
| 307 |
+
background: #1e4a76 !important;
|
| 308 |
transform: scale(1.02);
|
| 309 |
+
box-shadow: 0 4px 12px rgba(10,43,78,0.3);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 310 |
}
|
| 311 |
+
/* Tabs styling - simple and clean */
|
| 312 |
.gr-tabs .tab-nav button {
|
| 313 |
+
background-color: #eef2f5 !important;
|
| 314 |
+
color: #0a2b4e !important;
|
| 315 |
font-weight: 600 !important;
|
| 316 |
border-radius: 8px 8px 0 0 !important;
|
| 317 |
+
padding: 8px 20px !important;
|
| 318 |
+
margin-right: 4px;
|
| 319 |
}
|
| 320 |
.gr-tabs .tab-nav button.selected {
|
| 321 |
+
background-color: #0a2b4e !important;
|
| 322 |
+
color: white !important;
|
|
|
|
| 323 |
}
|
| 324 |
+
/* Input and output boxes - light grey border */
|
| 325 |
.gr-box, .gr-form, .gr-input, .gr-panel {
|
| 326 |
+
background-color: #f9fafb !important;
|
| 327 |
+
border: 1px solid #d1d5db !important;
|
| 328 |
border-radius: 12px !important;
|
| 329 |
}
|
| 330 |
/* Labels */
|
| 331 |
label, .gr-form label {
|
| 332 |
+
color: #1e293b !important;
|
| 333 |
font-weight: 500 !important;
|
| 334 |
}
|
| 335 |
+
/* Markdown text (report) */
|
| 336 |
.gr-markdown p, .gr-markdown {
|
| 337 |
+
color: #1e293b;
|
| 338 |
}
|
| 339 |
/* Footer */
|
| 340 |
.skyguard-footer {
|
| 341 |
text-align: center;
|
| 342 |
margin-top: 30px;
|
| 343 |
font-size: 12px;
|
| 344 |
+
color: #6c757d;
|
| 345 |
+
border-top: 1px solid #e2e8f0;
|
| 346 |
padding-top: 15px;
|
| 347 |
}
|
| 348 |
"""
|
|
|
|
| 353 |
<h1>SKYGUARD</h1>
|
| 354 |
<div class="tagline">SEE EVERY THREAT BEFORE IT LANDS</div>
|
| 355 |
<div class="sub">YOLOv11 Detection | Explainable AI (XAI) | BLIP Captioning</div>
|
| 356 |
+
<div class="sub" style="font-size:0.75rem; color:#3b6e9e;">Mohamed Khider University of Biskra - Computer Science | Biskra, Algeria</div>
|
| 357 |
</div>
|
| 358 |
""")
|
| 359 |
|
|
|
|
| 382 |
</div>
|
| 383 |
""")
|
| 384 |
|
| 385 |
+
# ============================================================
|
| 386 |
# 7. RUN APP
|
| 387 |
+
# ============================================================
|
| 388 |
if __name__ == "__main__":
|
| 389 |
demo.launch()
|