Spaces:
Sleeping
Sleeping
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 |
)
|