Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -42,6 +42,8 @@ try:
|
|
42 |
from services.plantation.plant_count import process_plants
|
43 |
from services.plantation.plant_health import process_plant_health
|
44 |
from services.plantation.missing_patch_check import process_missing_patches
|
|
|
|
|
45 |
except ImportError as e:
|
46 |
print(f"Failed to import service modules: {str(e)}")
|
47 |
logging.error(f"Import error: {str(e)}")
|
@@ -64,7 +66,7 @@ last_frame: Optional[np.ndarray] = None
|
|
64 |
last_metrics: Dict[str, Any] = {}
|
65 |
last_timestamp: str = ""
|
66 |
detected_plants: List[str] = [] # For plants and missing patches
|
67 |
-
detected_issues: List[str] = [] # For cracks, holes, and
|
68 |
gps_coordinates: List[List[float]] = []
|
69 |
media_loaded: bool = False
|
70 |
active_service: Optional[str] = None
|
@@ -167,30 +169,28 @@ def set_active_service(
|
|
167 |
pl_val: bool
|
168 |
) -> Tuple[Optional[str], str]:
|
169 |
global active_service
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
"
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
if
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
logging.info("No service category enabled.")
|
193 |
-
return None, "No Service Category Enabled"
|
194 |
|
195 |
def generate_line_chart() -> Optional[str]:
|
196 |
if not detected_counts:
|
@@ -291,31 +291,35 @@ def monitor_feed() -> Tuple[
|
|
291 |
thermal_flag = False
|
292 |
|
293 |
try:
|
294 |
-
# Process
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
|
|
|
|
|
|
|
|
319 |
|
320 |
# Apply shadow detection
|
321 |
try:
|
@@ -348,7 +352,7 @@ def monitor_feed() -> Tuple[
|
|
348 |
int(box[3] * scale_y)
|
349 |
]
|
350 |
|
351 |
-
# Overlay detections on the original frame
|
352 |
for item in all_detected_items:
|
353 |
box = item.get("box", [])
|
354 |
if not box:
|
@@ -356,17 +360,38 @@ def monitor_feed() -> Tuple[
|
|
356 |
x_min, y_min, x_max, y_max = box
|
357 |
label = item.get("label", "")
|
358 |
dtype = item.get("type", "")
|
359 |
-
|
|
|
|
|
360 |
if dtype == "plant":
|
361 |
-
color = (
|
362 |
-
|
363 |
-
|
364 |
-
elif dtype == "hole":
|
365 |
-
color = (0, 0, 255) # Blue for holes
|
366 |
elif dtype == "missing_patch":
|
367 |
-
color = (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
368 |
else:
|
369 |
-
color = (255, 255,
|
|
|
370 |
cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), color, 2)
|
371 |
cv2.putText(frame, label, (x_min, y_min - 10),
|
372 |
cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
|
@@ -380,7 +405,7 @@ def monitor_feed() -> Tuple[
|
|
380 |
|
381 |
except Exception as e:
|
382 |
log_entries.append(f"Processing Error: {str(e)}")
|
383 |
-
logging.error(f"Processing error
|
384 |
all_detected_items = []
|
385 |
|
386 |
# Update detection metrics
|
@@ -408,7 +433,7 @@ def monitor_feed() -> Tuple[
|
|
408 |
detected_plants.append(captured_frame_path)
|
409 |
if len(detected_plants) > 100:
|
410 |
detected_plants.pop(0)
|
411 |
-
|
412 |
detected_issues.append(captured_frame_path)
|
413 |
if len(detected_issues) > 100:
|
414 |
detected_issues.pop(0)
|
@@ -446,16 +471,21 @@ def monitor_feed() -> Tuple[
|
|
446 |
|
447 |
# Update global variables
|
448 |
frame_count += 1
|
449 |
-
last_timestamp = datetime.now().strftime("%Y-%m
|
450 |
last_frame = frame.copy()
|
451 |
last_metrics = metrics
|
452 |
|
453 |
# Track detections for metrics
|
454 |
plant_detected = len([item for item in all_detected_items if item.get("type") == "plant"])
|
455 |
crack_detected = len([item for item in all_detected_items if item.get("type") == "crack"])
|
456 |
-
hole_detected = len([item for item in all_detected_items if item.get("type") == "hole"])
|
457 |
missing_detected = len([item for item in all_detected_items if item.get("type") == "missing_patch"])
|
458 |
-
|
|
|
|
|
|
|
|
|
|
|
459 |
|
460 |
# Log frame processing details in the requested format
|
461 |
processing_time = time.time() - start_time
|
@@ -466,6 +496,10 @@ def monitor_feed() -> Tuple[
|
|
466 |
"cracks": crack_detected,
|
467 |
"holes": hole_detected,
|
468 |
"missing_patches": missing_detected,
|
|
|
|
|
|
|
|
|
469 |
"gps": gps_coord,
|
470 |
"processing_time_ms": processing_time * 1000
|
471 |
}
|
@@ -485,7 +519,7 @@ def monitor_feed() -> Tuple[
|
|
485 |
cv2.putText(frame, f"{last_timestamp}", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
|
486 |
|
487 |
# Generate map
|
488 |
-
map_items = [item for item in last_metrics.get("items", []) if item.get("type") in ["crack", "hole", "missing_patch"]]
|
489 |
map_path = generate_map(gps_coordinates[-5:], map_items)
|
490 |
|
491 |
return (
|
@@ -503,7 +537,7 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="green"))
|
|
503 |
gr.Markdown(
|
504 |
"""
|
505 |
# 🛡️ NHAI Drone Road Inspection Dashboard
|
506 |
-
Monitor highway conditions in real-time using drone footage or static images.
|
507 |
"""
|
508 |
)
|
509 |
|
@@ -520,17 +554,17 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="green"))
|
|
520 |
|
521 |
with gr.Row():
|
522 |
with gr.Column():
|
523 |
-
uc_toggle = gr.Checkbox(label="Enable Under Construction Services", value=
|
524 |
-
uc_status = gr.Textbox(label="Under Construction Status", value="
|
525 |
with gr.Column():
|
526 |
-
om_toggle = gr.Checkbox(label="Enable Operations Maintenance Services", value=
|
527 |
-
om_status = gr.Textbox(label="Operations Maintenance Status", value="
|
528 |
with gr.Column():
|
529 |
-
rs_toggle = gr.Checkbox(label="Enable Road Safety Services", value=
|
530 |
-
rs_status = gr.Textbox(label="Road Safety Status", value="
|
531 |
with gr.Column():
|
532 |
-
pl_toggle = gr.Checkbox(label="Enable Plantation Services", value=
|
533 |
-
pl_status = gr.Textbox(label="Plantation Status", value="
|
534 |
|
535 |
status_text = gr.Markdown("**Status:** 🟢 Ready (Upload a media file to start)")
|
536 |
|
@@ -600,10 +634,10 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="green"))
|
|
600 |
|
601 |
def update_toggles(uc_val: bool, om_val: bool, rs_val: bool, pl_val: bool) -> Tuple[str, str, str, str, str]:
|
602 |
active, status_message = set_active_service("toggle", uc_val, om_val, rs_val, pl_val)
|
603 |
-
uc_status_val = "Enabled" if
|
604 |
-
om_status_val = "Enabled" if
|
605 |
-
rs_status_val = "Enabled" if
|
606 |
-
pl_status_val = "Enabled" if
|
607 |
return (
|
608 |
uc_status_val, om_status_val, rs_status_val, pl_status_val, status_message
|
609 |
)
|
|
|
42 |
from services.plantation.plant_count import process_plants
|
43 |
from services.plantation.plant_health import process_plant_health
|
44 |
from services.plantation.missing_patch_check import process_missing_patches
|
45 |
+
# General object detection
|
46 |
+
from services.object_detection import detect_objects
|
47 |
except ImportError as e:
|
48 |
print(f"Failed to import service modules: {str(e)}")
|
49 |
logging.error(f"Import error: {str(e)}")
|
|
|
66 |
last_metrics: Dict[str, Any] = {}
|
67 |
last_timestamp: str = ""
|
68 |
detected_plants: List[str] = [] # For plants and missing patches
|
69 |
+
detected_issues: List[str] = [] # For cracks, holes, and other issues
|
70 |
gps_coordinates: List[List[float]] = []
|
71 |
media_loaded: bool = False
|
72 |
active_service: Optional[str] = None
|
|
|
169 |
pl_val: bool
|
170 |
) -> Tuple[Optional[str], str]:
|
171 |
global active_service
|
172 |
+
# Enable all requested services
|
173 |
+
enabled_services = []
|
174 |
+
if uc_val:
|
175 |
+
enabled_services.append("under_construction")
|
176 |
+
if om_val:
|
177 |
+
enabled_services.append("operations_maintenance")
|
178 |
+
if rs_val:
|
179 |
+
enabled_services.append("road_safety")
|
180 |
+
if pl_val:
|
181 |
+
enabled_services.append("plantation")
|
182 |
+
|
183 |
+
if not enabled_services:
|
184 |
+
active_service = None
|
185 |
+
log_entries.append("No service category enabled.")
|
186 |
+
logging.info("No service category enabled.")
|
187 |
+
return None, "No Service Category Enabled"
|
188 |
+
|
189 |
+
# Since multiple services are requested, we'll process all enabled services
|
190 |
+
active_service = "all_enabled" # Custom state to process all enabled services
|
191 |
+
log_entries.append(f"Enabled services: {', '.join(enabled_services)}")
|
192 |
+
logging.info(f"Enabled services: {', '.join(enabled_services)}")
|
193 |
+
return active_service, f"Enabled: {', '.join([s.replace('_', ' ').title() for s in enabled_services])}"
|
|
|
|
|
194 |
|
195 |
def generate_line_chart() -> Optional[str]:
|
196 |
if not detected_counts:
|
|
|
291 |
thermal_flag = False
|
292 |
|
293 |
try:
|
294 |
+
# Process all enabled services
|
295 |
+
# Under Construction Services
|
296 |
+
earthwork_dets, detection_frame = process_earthwork(detection_frame)
|
297 |
+
culvert_dets, detection_frame = process_culverts(detection_frame)
|
298 |
+
bridge_pier_dets, detection_frame = process_bridge_piers(detection_frame)
|
299 |
+
all_detected_items.extend(earthwork_dets + culvert_dets + bridge_pier_dets)
|
300 |
+
|
301 |
+
# Operations Maintenance Services
|
302 |
+
crack_hole_dets, detection_frame = detect_cracks_and_holes(detection_frame)
|
303 |
+
pothole_dets, detection_frame = process_potholes(detection_frame)
|
304 |
+
signage_dets, detection_frame = process_signages(detection_frame)
|
305 |
+
all_detected_items.extend(crack_hole_dets + pothole_dets + signage_dets)
|
306 |
+
|
307 |
+
# Road Safety Services
|
308 |
+
barrier_dets, detection_frame = process_barriers(detection_frame)
|
309 |
+
lighting_dets, detection_frame = process_lighting(detection_frame)
|
310 |
+
accident_dets, detection_frame = process_accident_spots(detection_frame)
|
311 |
+
pothole_crack_dets, detection_frame = detect_potholes_and_cracks(detection_frame)
|
312 |
+
all_detected_items.extend(barrier_dets + lighting_dets + accident_dets + pothole_crack_dets)
|
313 |
+
|
314 |
+
# Plantation Services
|
315 |
+
plant_dets, detection_frame = process_plants(detection_frame)
|
316 |
+
health_dets, detection_frame = process_plant_health(detection_frame)
|
317 |
+
missing_dets, detection_frame = process_missing_patches(detection_frame)
|
318 |
+
all_detected_items.extend(plant_dets + health_dets + missing_dets)
|
319 |
+
|
320 |
+
# General Object Detection (cars, bikes, humans, dogs, etc.)
|
321 |
+
object_dets, detection_frame = detect_objects(detection_frame)
|
322 |
+
all_detected_items.extend(object_dets)
|
323 |
|
324 |
# Apply shadow detection
|
325 |
try:
|
|
|
352 |
int(box[3] * scale_y)
|
353 |
]
|
354 |
|
355 |
+
# Overlay detections on the original frame with specified colors
|
356 |
for item in all_detected_items:
|
357 |
box = item.get("box", [])
|
358 |
if not box:
|
|
|
360 |
x_min, y_min, x_max, y_max = box
|
361 |
label = item.get("label", "")
|
362 |
dtype = item.get("type", "")
|
363 |
+
health = item.get("health", "") # For plant health
|
364 |
+
|
365 |
+
# Assign colors based on detection type as per requirements
|
366 |
if dtype == "plant":
|
367 |
+
color = (255, 0, 0) # Blue mark for plant count
|
368 |
+
if health == "healthy":
|
369 |
+
color = (255, 165, 0) # Orange mark for healthy plants
|
|
|
|
|
370 |
elif dtype == "missing_patch":
|
371 |
+
color = (0, 0, 255) # Red mark for missing patches
|
372 |
+
elif dtype == "earthwork":
|
373 |
+
color = (255, 105, 180) # Pink for earthwork
|
374 |
+
elif dtype == "culvert":
|
375 |
+
color = (0, 165, 255) # Blue and orange mix (approximated)
|
376 |
+
elif dtype == "bridge_pier":
|
377 |
+
color = (255, 99, 71) # Light red for bridge piers
|
378 |
+
elif dtype == "pothole" or dtype == "hole":
|
379 |
+
color = (255, 0, 0) # Red for potholes (from pothole_detection and pothole_crack_detection)
|
380 |
+
elif dtype == "crack":
|
381 |
+
color = (255, 105, 180) # Pink for cracks
|
382 |
+
elif dtype == "signage":
|
383 |
+
color = (255, 255, 0) # Yellow for signage
|
384 |
+
elif dtype == "car":
|
385 |
+
color = (128, 0, 128) # Purple for cars
|
386 |
+
elif dtype == "bike":
|
387 |
+
color = (0, 255, 255) # Cyan for bikes
|
388 |
+
elif dtype == "person":
|
389 |
+
color = (0, 255, 0) # Green for humans
|
390 |
+
elif dtype == "dog":
|
391 |
+
color = (139, 69, 19) # Brown for dogs
|
392 |
else:
|
393 |
+
color = (255, 255, 255) # White for other objects
|
394 |
+
|
395 |
cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), color, 2)
|
396 |
cv2.putText(frame, label, (x_min, y_min - 10),
|
397 |
cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
|
|
|
405 |
|
406 |
except Exception as e:
|
407 |
log_entries.append(f"Processing Error: {str(e)}")
|
408 |
+
logging.error(f"Processing error: {str(e)}")
|
409 |
all_detected_items = []
|
410 |
|
411 |
# Update detection metrics
|
|
|
433 |
detected_plants.append(captured_frame_path)
|
434 |
if len(detected_plants) > 100:
|
435 |
detected_plants.pop(0)
|
436 |
+
else:
|
437 |
detected_issues.append(captured_frame_path)
|
438 |
if len(detected_issues) > 100:
|
439 |
detected_issues.pop(0)
|
|
|
471 |
|
472 |
# Update global variables
|
473 |
frame_count += 1
|
474 |
+
last_timestamp = datetime.now().strftime("%Y-%m-d %H:%M:%S")
|
475 |
last_frame = frame.copy()
|
476 |
last_metrics = metrics
|
477 |
|
478 |
# Track detections for metrics
|
479 |
plant_detected = len([item for item in all_detected_items if item.get("type") == "plant"])
|
480 |
crack_detected = len([item for item in all_detected_items if item.get("type") == "crack"])
|
481 |
+
hole_detected = len([item for item in all_detected_items if item.get("type") == "hole" or item.get("type") == "pothole"])
|
482 |
missing_detected = len([item for item in all_detected_items if item.get("type") == "missing_patch"])
|
483 |
+
car_detected = len([item for item in all_detected_items if item.get("type") == "car"])
|
484 |
+
bike_detected = len([item for item in all_detected_items if item.get("type") == "bike"])
|
485 |
+
person_detected = len([item for item in all_detected_items if item.get("type") == "person"])
|
486 |
+
dog_detected = len([item for item in all_detected_items if item.get("type") == "dog"])
|
487 |
+
detected_counts.append(plant_detected + crack_detected + hole_detected + missing_detected +
|
488 |
+
car_detected + bike_detected + person_detected + dog_detected)
|
489 |
|
490 |
# Log frame processing details in the requested format
|
491 |
processing_time = time.time() - start_time
|
|
|
496 |
"cracks": crack_detected,
|
497 |
"holes": hole_detected,
|
498 |
"missing_patches": missing_detected,
|
499 |
+
"cars": car_detected,
|
500 |
+
"bikes": bike_detected,
|
501 |
+
"persons": person_detected,
|
502 |
+
"dogs": dog_detected,
|
503 |
"gps": gps_coord,
|
504 |
"processing_time_ms": processing_time * 1000
|
505 |
}
|
|
|
519 |
cv2.putText(frame, f"{last_timestamp}", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
|
520 |
|
521 |
# Generate map
|
522 |
+
map_items = [item for item in last_metrics.get("items", []) if item.get("type") in ["crack", "hole", "pothole", "missing_patch"]]
|
523 |
map_path = generate_map(gps_coordinates[-5:], map_items)
|
524 |
|
525 |
return (
|
|
|
537 |
gr.Markdown(
|
538 |
"""
|
539 |
# 🛡️ NHAI Drone Road Inspection Dashboard
|
540 |
+
Monitor highway conditions in real-time using drone footage or static images. All services are enabled as requested.
|
541 |
"""
|
542 |
)
|
543 |
|
|
|
554 |
|
555 |
with gr.Row():
|
556 |
with gr.Column():
|
557 |
+
uc_toggle = gr.Checkbox(label="Enable Under Construction Services", value=True)
|
558 |
+
uc_status = gr.Textbox(label="Under Construction Status", value="Enabled", interactive=False)
|
559 |
with gr.Column():
|
560 |
+
om_toggle = gr.Checkbox(label="Enable Operations Maintenance Services", value=True)
|
561 |
+
om_status = gr.Textbox(label="Operations Maintenance Status", value="Enabled", interactive=False)
|
562 |
with gr.Column():
|
563 |
+
rs_toggle = gr.Checkbox(label="Enable Road Safety Services", value=True)
|
564 |
+
rs_status = gr.Textbox(label="Road Safety Status", value="Enabled", interactive=False)
|
565 |
with gr.Column():
|
566 |
+
pl_toggle = gr.Checkbox(label="Enable Plantation Services", value=True)
|
567 |
+
pl_status = gr.Textbox(label="Plantation Status", value="Enabled", interactive=False)
|
568 |
|
569 |
status_text = gr.Markdown("**Status:** 🟢 Ready (Upload a media file to start)")
|
570 |
|
|
|
634 |
|
635 |
def update_toggles(uc_val: bool, om_val: bool, rs_val: bool, pl_val: bool) -> Tuple[str, str, str, str, str]:
|
636 |
active, status_message = set_active_service("toggle", uc_val, om_val, rs_val, pl_val)
|
637 |
+
uc_status_val = "Enabled" if "under_construction" in status_message.lower() else "Disabled"
|
638 |
+
om_status_val = "Enabled" if "operations_maintenance" in status_message.lower() else "Disabled"
|
639 |
+
rs_status_val = "Enabled" if "road_safety" in status_message.lower() else "Disabled"
|
640 |
+
pl_status_val = "Enabled" if "plantation" in status_message.lower() else "Disabled"
|
641 |
return (
|
642 |
uc_status_val, om_status_val, rs_status_val, pl_status_val, status_message
|
643 |
)
|