Spaces:
Running
Running
Isra Info commited on
Update app.py
Browse files
app.py
CHANGED
|
@@ -11,12 +11,11 @@ import warnings
|
|
| 11 |
warnings.filterwarnings('ignore')
|
| 12 |
|
| 13 |
# ============================================================
|
| 14 |
-
# 1.
|
| 15 |
# ============================================================
|
| 16 |
print("Loading YOLOv11 model from Hugging Face Hub...")
|
| 17 |
-
# !! غيّر "YOUR_USERNAME" إلى اسم المستخدم الحقيقي الخاص بك !!
|
| 18 |
model_path = hf_hub_download(
|
| 19 |
-
repo_id="IsraInfo2004/drone-detection-yolov11",
|
| 20 |
filename="best.pt"
|
| 21 |
)
|
| 22 |
model = YOLO(model_path)
|
|
@@ -32,7 +31,7 @@ blip_model.eval()
|
|
| 32 |
print("BLIP model loaded successfully.")
|
| 33 |
|
| 34 |
# ============================================================
|
| 35 |
-
# 2.
|
| 36 |
# ============================================================
|
| 37 |
layer_outputs = {}
|
| 38 |
|
|
@@ -54,7 +53,6 @@ def get_best_layer(model):
|
|
| 54 |
def generate_heatmap(model, image):
|
| 55 |
try:
|
| 56 |
layer_outputs.clear()
|
| 57 |
-
# تأكد من أن الصورة من نوع RGB numpy array
|
| 58 |
if isinstance(image, Image.Image):
|
| 59 |
image = np.array(image)
|
| 60 |
img_resized = cv2.resize(image, (640, 640))
|
|
@@ -93,7 +91,7 @@ def generate_heatmap(model, image):
|
|
| 93 |
return None
|
| 94 |
|
| 95 |
# ============================================================
|
| 96 |
-
# 3.
|
| 97 |
# ============================================================
|
| 98 |
def generate_dynamic_caption(image):
|
| 99 |
try:
|
|
@@ -117,7 +115,7 @@ def generate_dynamic_caption(image):
|
|
| 117 |
return "AI model is analyzing the scene."
|
| 118 |
|
| 119 |
# ============================================================
|
| 120 |
-
# 4.
|
| 121 |
# ============================================================
|
| 122 |
def build_xai_report(is_drone, confidence, drone_count, processing_time, image_caption):
|
| 123 |
confidence_percent = confidence * 100
|
|
@@ -212,29 +210,19 @@ Scattered activation pattern confirms absence of strong drone-like features.
|
|
| 212 |
return report
|
| 213 |
|
| 214 |
# ============================================================
|
| 215 |
-
# 5.
|
| 216 |
# ============================================================
|
| 217 |
def drone_detection_pipeline(input_image):
|
| 218 |
-
"""
|
| 219 |
-
المدخلات: صورة (PIL Image أو numpy array)
|
| 220 |
-
المخرجات: (صورة النتيجة, صورة الخريطة الحرارية, تقرير نصي)
|
| 221 |
-
"""
|
| 222 |
try:
|
| 223 |
-
# تحويل الصورة إلى numpy array (RGB)
|
| 224 |
if isinstance(input_image, Image.Image):
|
| 225 |
img = np.array(input_image)
|
| 226 |
else:
|
| 227 |
img = input_image.copy()
|
| 228 |
|
| 229 |
original_h, original_w = img.shape[:2]
|
| 230 |
-
|
| 231 |
-
# 1. تنفيذ الكشف
|
| 232 |
results = model(img)
|
| 233 |
-
|
| 234 |
-
# 2. إنشاء الخريطة الحرارية
|
| 235 |
heatmap_overlay = generate_heatmap(model, img)
|
| 236 |
|
| 237 |
-
# 3. استخراج معلومات الكشف
|
| 238 |
is_drone = False
|
| 239 |
confidence = 0.0
|
| 240 |
drone_count = 0
|
|
@@ -243,7 +231,6 @@ def drone_detection_pipeline(input_image):
|
|
| 243 |
if boxes_data and boxes_data.data is not None:
|
| 244 |
data = boxes_data.data.cpu().numpy()
|
| 245 |
for det in data:
|
| 246 |
-
# تنسيق det: x1, y1, x2, y2, conf, cls
|
| 247 |
if len(det) >= 6:
|
| 248 |
conf = float(det[4])
|
| 249 |
cls = int(det[5])
|
|
@@ -253,58 +240,48 @@ def drone_detection_pipeline(input_image):
|
|
| 253 |
confidence = max(confidence, conf)
|
| 254 |
is_drone = drone_count > 0
|
| 255 |
|
| 256 |
-
# 4. إنشاء الصورة المعلّمة (مع المربعات)
|
| 257 |
result_img = results[0].plot() if len(results) > 0 else img
|
| 258 |
result_img_rgb = cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB)
|
| 259 |
-
|
| 260 |
-
# 5. إنشاء الوصف النصي
|
| 261 |
caption = generate_dynamic_caption(img)
|
| 262 |
-
|
| 263 |
-
# 6. حساب وقت المعالجة (تقريبي)
|
| 264 |
-
processing_time_ms = 0 # يمكن تركه صفراً أو حسابه فعلياً
|
| 265 |
-
|
| 266 |
-
# 7. بناء التقرير
|
| 267 |
report = build_xai_report(is_drone, confidence, drone_count, processing_time_ms, caption)
|
| 268 |
|
| 269 |
-
# 8. معالجة الخريطة الحرارية لتتناسب مع أبعاد الصورة الأصلية
|
| 270 |
if heatmap_overlay is not None:
|
| 271 |
heatmap_resized = cv2.resize(heatmap_overlay, (original_w, original_h))
|
| 272 |
else:
|
| 273 |
heatmap_resized = np.zeros_like(result_img_rgb)
|
| 274 |
|
| 275 |
return result_img_rgb, heatmap_resized, report
|
| 276 |
-
|
| 277 |
except Exception as e:
|
| 278 |
error_msg = f"An error occurred during processing: {str(e)}"
|
| 279 |
print(error_msg)
|
| 280 |
-
# إرجاع صور فارغة مع رسالة الخطأ
|
| 281 |
blank = np.zeros((480, 640, 3), dtype=np.uint8)
|
| 282 |
return blank, blank, error_msg
|
| 283 |
|
| 284 |
# ============================================================
|
| 285 |
-
# 6.
|
| 286 |
# ============================================================
|
| 287 |
with gr.Blocks(title="Drone Detection with XAI", theme=gr.themes.Soft()) as demo:
|
| 288 |
gr.Markdown("""
|
| 289 |
<div style="text-align: center;">
|
| 290 |
-
<h1>🚁
|
| 291 |
-
<p>
|
| 292 |
-
<p>📌 <strong>
|
| 293 |
</div>
|
| 294 |
""")
|
| 295 |
|
| 296 |
with gr.Row():
|
| 297 |
with gr.Column(scale=1):
|
| 298 |
-
input_image = gr.Image(label="📸
|
| 299 |
-
submit_btn = gr.Button("
|
| 300 |
with gr.Column(scale=2):
|
| 301 |
with gr.Tabs():
|
| 302 |
-
with gr.TabItem("🔍
|
| 303 |
-
output_image = gr.Image(label="
|
| 304 |
-
with gr.TabItem("🔥
|
| 305 |
-
heatmap_image = gr.Image(label="
|
| 306 |
-
with gr.TabItem("📄
|
| 307 |
-
report_text = gr.Markdown(label="
|
| 308 |
|
| 309 |
submit_btn.click(
|
| 310 |
fn=drone_detection_pipeline,
|
|
@@ -315,12 +292,12 @@ with gr.Blocks(title="Drone Detection with XAI", theme=gr.themes.Soft()) as demo
|
|
| 315 |
gr.Markdown("""
|
| 316 |
<div style="text-align: center; margin-top: 30px; font-size: 12px; color: gray;">
|
| 317 |
<hr>
|
| 318 |
-
<p>
|
| 319 |
</div>
|
| 320 |
""")
|
| 321 |
|
| 322 |
# ============================================================
|
| 323 |
-
# 7.
|
| 324 |
# ============================================================
|
| 325 |
if __name__ == "__main__":
|
| 326 |
demo.launch()
|
|
|
|
| 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="IsraInfo2004/drone-detection-yolov11",
|
| 19 |
filename="best.pt"
|
| 20 |
)
|
| 21 |
model = YOLO(model_path)
|
|
|
|
| 31 |
print("BLIP model loaded successfully.")
|
| 32 |
|
| 33 |
# ============================================================
|
| 34 |
+
# 2. HEATMAP FUNCTIONS
|
| 35 |
# ============================================================
|
| 36 |
layer_outputs = {}
|
| 37 |
|
|
|
|
| 53 |
def generate_heatmap(model, image):
|
| 54 |
try:
|
| 55 |
layer_outputs.clear()
|
|
|
|
| 56 |
if isinstance(image, Image.Image):
|
| 57 |
image = np.array(image)
|
| 58 |
img_resized = cv2.resize(image, (640, 640))
|
|
|
|
| 91 |
return None
|
| 92 |
|
| 93 |
# ============================================================
|
| 94 |
+
# 3. DYNAMIC CAPTION (BLIP)
|
| 95 |
# ============================================================
|
| 96 |
def generate_dynamic_caption(image):
|
| 97 |
try:
|
|
|
|
| 115 |
return "AI model is analyzing the scene."
|
| 116 |
|
| 117 |
# ============================================================
|
| 118 |
+
# 4. XAI REPORT (ENGLISH)
|
| 119 |
# ============================================================
|
| 120 |
def build_xai_report(is_drone, confidence, drone_count, processing_time, image_caption):
|
| 121 |
confidence_percent = confidence * 100
|
|
|
|
| 210 |
return report
|
| 211 |
|
| 212 |
# ============================================================
|
| 213 |
+
# 5. MAIN PIPELINE FUNCTION
|
| 214 |
# ============================================================
|
| 215 |
def drone_detection_pipeline(input_image):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 216 |
try:
|
|
|
|
| 217 |
if isinstance(input_image, Image.Image):
|
| 218 |
img = np.array(input_image)
|
| 219 |
else:
|
| 220 |
img = input_image.copy()
|
| 221 |
|
| 222 |
original_h, original_w = img.shape[:2]
|
|
|
|
|
|
|
| 223 |
results = model(img)
|
|
|
|
|
|
|
| 224 |
heatmap_overlay = generate_heatmap(model, img)
|
| 225 |
|
|
|
|
| 226 |
is_drone = False
|
| 227 |
confidence = 0.0
|
| 228 |
drone_count = 0
|
|
|
|
| 231 |
if boxes_data and boxes_data.data is not None:
|
| 232 |
data = boxes_data.data.cpu().numpy()
|
| 233 |
for det in data:
|
|
|
|
| 234 |
if len(det) >= 6:
|
| 235 |
conf = float(det[4])
|
| 236 |
cls = int(det[5])
|
|
|
|
| 240 |
confidence = max(confidence, conf)
|
| 241 |
is_drone = drone_count > 0
|
| 242 |
|
|
|
|
| 243 |
result_img = results[0].plot() if len(results) > 0 else img
|
| 244 |
result_img_rgb = cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB)
|
|
|
|
|
|
|
| 245 |
caption = generate_dynamic_caption(img)
|
| 246 |
+
processing_time_ms = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
| 247 |
report = build_xai_report(is_drone, confidence, drone_count, processing_time_ms, caption)
|
| 248 |
|
|
|
|
| 249 |
if heatmap_overlay is not None:
|
| 250 |
heatmap_resized = cv2.resize(heatmap_overlay, (original_w, original_h))
|
| 251 |
else:
|
| 252 |
heatmap_resized = np.zeros_like(result_img_rgb)
|
| 253 |
|
| 254 |
return result_img_rgb, heatmap_resized, report
|
|
|
|
| 255 |
except Exception as e:
|
| 256 |
error_msg = f"An error occurred during processing: {str(e)}"
|
| 257 |
print(error_msg)
|
|
|
|
| 258 |
blank = np.zeros((480, 640, 3), dtype=np.uint8)
|
| 259 |
return blank, blank, error_msg
|
| 260 |
|
| 261 |
# ============================================================
|
| 262 |
+
# 6. GRADIO INTERFACE (ENGLISH)
|
| 263 |
# ============================================================
|
| 264 |
with gr.Blocks(title="Drone Detection with XAI", theme=gr.themes.Soft()) as demo:
|
| 265 |
gr.Markdown("""
|
| 266 |
<div style="text-align: center;">
|
| 267 |
+
<h1>🚁 Drone Detection System with Explainable AI (XAI)</h1>
|
| 268 |
+
<p>Using <strong>YOLOv11</strong> for detection, <strong>heatmap</strong> for neural network focus visualization, and <strong>BLIP</strong> for dynamic image captioning.</p>
|
| 269 |
+
<p>📌 <strong>Note:</strong> The heatmap is extracted from the deepest convolutional layer of YOLOv11, showing where the model focuses to make decisions.</p>
|
| 270 |
</div>
|
| 271 |
""")
|
| 272 |
|
| 273 |
with gr.Row():
|
| 274 |
with gr.Column(scale=1):
|
| 275 |
+
input_image = gr.Image(label="📸 Upload an image for analysis", type="pil")
|
| 276 |
+
submit_btn = gr.Button("Start Analysis", variant="primary", size="lg")
|
| 277 |
with gr.Column(scale=2):
|
| 278 |
with gr.Tabs():
|
| 279 |
+
with gr.TabItem("🔍 Detection Result"):
|
| 280 |
+
output_image = gr.Image(label="Image with bounding boxes")
|
| 281 |
+
with gr.TabItem("🔥 XAI Heatmap"):
|
| 282 |
+
heatmap_image = gr.Image(label="Neural activation heatmap (Red = high focus)")
|
| 283 |
+
with gr.TabItem("📄 Detailed XAI Report"):
|
| 284 |
+
report_text = gr.Markdown(label="Complete report")
|
| 285 |
|
| 286 |
submit_btn.click(
|
| 287 |
fn=drone_detection_pipeline,
|
|
|
|
| 292 |
gr.Markdown("""
|
| 293 |
<div style="text-align: center; margin-top: 30px; font-size: 12px; color: gray;">
|
| 294 |
<hr>
|
| 295 |
+
<p>Developed with YOLOv11, Gradio, Hugging Face Spaces 🤗 | Model hosted on Hugging Face Hub</p>
|
| 296 |
</div>
|
| 297 |
""")
|
| 298 |
|
| 299 |
# ============================================================
|
| 300 |
+
# 7. RUN APP
|
| 301 |
# ============================================================
|
| 302 |
if __name__ == "__main__":
|
| 303 |
demo.launch()
|