paranox/SourceCode
1
1import streamlit as st2from PIL import Image3import time4from ultralytics import YOLO5import matplotlib.pyplot as plt6import pandas as pd7import numpy as np8import tensorflow as tf9import cv210import traceback11 12# ๐จ PREMIUM PAGE CONFIGURATION13st.set_page_config(14 page_title="SmartLane AI ยท Traffic Intelligence Platform",15 page_icon="๐ฆ",16 layout="wide",17 initial_sidebar_state="collapsed"18)19 20# ๐ ULTRA-PREMIUM DESIGN SYSTEM21st.markdown("""22<style>23 @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600;700&display=swap');24 25 :root {26 --primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);27 --cyber-gradient: linear-gradient(135deg, #00f2fe 0%, #4facfe 50%, #667eea 100%);28 --emergency-gradient: linear-gradient(135deg, #00c400 0%, #11ff11 100%);29 --bg-card: rgba(17, 24, 39, 0.6);30 --text-primary: #f8fafc;31 --text-secondary: #94a3b8;32 --text-muted: #64748b;33 --border-primary: rgba(255, 255, 255, 0.1);34 }35 36 * {37 margin: 0;38 padding: 0;39 box-sizing: border-box;40 }41 42 .stApp {43 background: radial-gradient(ellipse at top, #1e293b 0%, #0a0e1a 50%, #000000 100%);44 background-attachment: fixed;45 }46 47 .stApp::before {48 content: '';49 position: fixed;50 top: 0;51 left: 0;52 right: 0;53 bottom: 0;54 background-image: 55 radial-gradient(at 20% 30%, rgba(102, 126, 234, 0.12) 0px, transparent 50%),56 radial-gradient(at 80% 20%, rgba(139, 92, 246, 0.12) 0px, transparent 50%);57 pointer-events: none;58 z-index: 0;59 }60 61 #MainMenu, footer, header {visibility: hidden;}62 .stDeployButton {display: none;}63 64 .navbar {65 position: fixed;66 top: 0;67 left: 0;68 right: 0;69 z-index: 9999;70 background: rgba(10, 14, 26, 0.85);71 backdrop-filter: blur(24px);72 border-bottom: 1px solid var(--border-primary);73 padding: 1rem 3rem;74 display: flex;75 justify-content: space-between;76 align-items: center;77 box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);78 }79 80 .navbar-logo {81 font-size: 1.5rem;82 font-weight: 900;83 background: var(--cyber-gradient);84 -webkit-background-clip: text;85 -webkit-text-fill-color: transparent;86 text-transform: uppercase;87 }88 89 .navbar-badge {90 background: rgba(102, 126, 234, 0.15);91 border: 1px solid rgba(102, 126, 234, 0.4);92 color: #667eea;93 padding: 0.375rem 1rem;94 border-radius: 24px;95 font-size: 0.7rem;96 font-weight: 700;97 text-transform: uppercase;98 letter-spacing: 1px;99 }100 101 .emergency-alert {102 background: linear-gradient(45deg, #00c400, #11ff11);103 color: white;104 padding: 0.5rem 1.5rem;105 border-radius: 24px;106 font-size: 0.8rem;107 font-weight: 900;108 text-transform: uppercase;109 letter-spacing: 1.5px;110 animation: emergencyPulse 1s ease-in-out infinite;111 box-shadow: 0 0 30px rgba(0, 196, 0, 0.6);112 }113 114 @keyframes emergencyPulse {115 0%, 100% { transform: scale(1); opacity: 1; }116 50% { transform: scale(1.05); opacity: 0.9; }117 }118 119 .hero-section {120 margin-top: 100px;121 padding: 5rem 2rem 4rem;122 text-align: center;123 }124 125 .hero-badge {126 display: inline-flex;127 align-items: center;128 gap: 0.625rem;129 background: rgba(102, 126, 234, 0.1);130 border: 1px solid rgba(102, 126, 234, 0.3);131 padding: 0.625rem 1.5rem;132 border-radius: 50px;133 color: #667eea;134 font-size: 0.875rem;135 font-weight: 700;136 margin-bottom: 2rem;137 }138 139 .hero-title {140 font-size: 4.5rem;141 font-weight: 900;142 line-height: 1.1;143 margin-bottom: 2rem;144 letter-spacing: -2px;145 }146 147 .hero-title-line1 {148 display: block;149 color: var(--text-primary);150 }151 152 .hero-title-line2 {153 display: block;154 background: var(--cyber-gradient);155 -webkit-background-clip: text;156 -webkit-text-fill-color: transparent;157 }158 159 .hero-subtitle {160 text-align: center !important;161 margin-left: auto !important;162 margin-right: auto !important;163 display: block !important;164 width: fit-content !important;165 max-width: 700px;166 }167 168 .tech-pill {169 display: inline-block;170 background: var(--bg-card);171 border: 1px solid var(--border-primary);172 padding: 0.75rem 1.5rem;173 border-radius: 16px;174 color: var(--text-secondary);175 font-size: 0.9rem;176 font-weight: 600;177 margin: 0.5rem;178 transition: all 0.3s ease;179 }180 181 .tech-pill:hover {182 background: rgba(102, 126, 234, 0.15);183 border-color: rgba(102, 126, 234, 0.5);184 transform: translateY(-3px);185 }186 187 .stats-grid {188 display: grid;189 grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));190 gap: 2rem;191 margin: 3rem 2rem;192 }193 194 .stat-card {195 background: var(--bg-card);196 backdrop-filter: blur(16px);197 border: 1px solid var(--border-primary);198 border-radius: 24px;199 padding: 2.5rem;200 text-align: center;201 transition: all 0.4s ease;202 }203 204 .stat-card:hover {205 transform: translateY(-10px);206 box-shadow: 0 0 40px rgba(102, 126, 234, 0.4);207 }208 209 .stat-icon {210 font-size: 3rem;211 margin-bottom: 1rem;212 }213 214 .stat-value {215 font-size: 3rem;216 font-weight: 900;217 background: var(--cyber-gradient);218 -webkit-background-clip: text;219 -webkit-text-fill-color: transparent;220 font-family: 'JetBrains Mono', monospace;221 margin-bottom: 0.5rem;222 }223 224 .stat-label {225 font-size: 0.875rem;226 color: var(--text-secondary);227 text-transform: uppercase;228 letter-spacing: 1.5px;229 font-weight: 700;230 }231 232 .section-container {233 background: var(--bg-card);234 backdrop-filter: blur(20px);235 border: 1px solid var(--border-primary);236 border-radius: 28px;237 padding: 2.5rem;238 margin: 2rem;239 transition: all 0.3s ease;240 }241 242 .section-container:hover {243 border-color: rgba(102, 126, 234, 0.3);244 }245 246 .section-title {247 font-size: 1.75rem;248 font-weight: 800;249 color: var(--text-primary);250 margin-bottom: 1.5rem;251 }252 253 .upload-card {254 background: rgba(17, 24, 39, 0.8);255 border: 2px dashed var(--border-primary);256 border-radius: 20px;257 padding: 2.5rem 2rem;258 text-align: center;259 transition: all 0.4s ease;260 }261 262 .upload-card:hover {263 border-color: #667eea;264 border-style: solid;265 transform: translateY(-5px);266 box-shadow: 0 16px 32px rgba(102, 126, 234, 0.3);267 }268 269 .signal-card {270 background: var(--bg-card);271 border: 1px solid var(--border-primary);272 border-radius: 20px;273 padding: 2rem;274 text-align: center;275 transition: all 0.3s ease;276 }277 278 .signal-card.green-active {279 border-color: #10b981;280 box-shadow: 0 0 30px rgba(16, 185, 129, 0.4);281 animation: pulseGreen 2s ease-in-out infinite;282 }283 284 @keyframes pulseGreen {285 0%, 100% { box-shadow: 0 0 30px rgba(16, 185, 129, 0.4); }286 50% { box-shadow: 0 0 50px rgba(16, 185, 129, 0.6); }287 }288 289 .signal-card.yellow-active {290 border-color: #fbbf24;291 box-shadow: 0 0 30px rgba(251, 191, 36, 0.4);292 animation: pulseYellow 1s ease-in-out infinite;293 }294 295 @keyframes pulseYellow {296 0%, 100% { box-shadow: 0 0 30px rgba(251, 191, 36, 0.4); }297 50% { box-shadow: 0 0 50px rgba(251, 191, 36, 0.6); }298 }299 300 .signal-card.emergency-active {301 border-color: #00c400;302 background: linear-gradient(135deg, rgba(0, 196, 0, 0.2) 0%, rgba(17, 255, 17, 0.2) 100%);303 box-shadow: 0 0 50px rgba(0, 196, 0, 0.8);304 animation: emergencySignal 0.5s ease-in-out infinite;305 }306 307 @keyframes emergencySignal {308 0%, 100% { 309 box-shadow: 0 0 50px rgba(0, 196, 0, 0.8);310 transform: scale(1);311 }312 50% { 313 box-shadow: 0 0 80px rgba(0, 196, 0, 1);314 transform: scale(1.02);315 }316 }317 318 .traffic-light {319 width: 90px;320 height: 90px;321 border-radius: 50%;322 margin: 0 auto 1rem;323 display: flex;324 align-items: center;325 justify-content: center;326 font-size: 2.5rem;327 border: 3px solid var(--border-primary);328 transition: all 0.3s ease;329 }330 331 .light-red {332 background: radial-gradient(circle, rgba(239, 68, 68, 0.3) 0%, transparent 70%);333 border-color: #ef4444;334 }335 336 .light-green {337 background: radial-gradient(circle, rgba(16, 185, 129, 0.5) 0%, transparent 70%);338 border-color: #10b981;339 box-shadow: 0 0 40px rgba(16, 185, 129, 0.5);340 animation: greenGlow 1.5s ease-in-out infinite;341 }342 343 @keyframes greenGlow {344 0%, 100% { box-shadow: 0 0 40px rgba(16, 185, 129, 0.4); }345 50% { box-shadow: 0 0 60px rgba(16, 185, 129, 0.6); }346 }347 348 .light-yellow {349 background: radial-gradient(circle, rgba(251, 191, 36, 0.5) 0%, transparent 70%);350 border-color: #fbbf24;351 box-shadow: 0 0 40px rgba(251, 191, 36, 0.5);352 animation: yellowGlow 0.8s ease-in-out infinite;353 }354 355 @keyframes yellowGlow {356 0%, 100% { box-shadow: 0 0 40px rgba(251, 191, 36, 0.4); }357 50% { box-shadow: 0 0 60px rgba(251, 191, 36, 0.6); }358 }359 360 .light-emergency {361 background: radial-gradient(circle, rgba(0, 196, 0, 0.7) 0%, transparent 70%);362 border-color: #00c400;363 box-shadow: 0 0 60px rgba(0, 196, 0, 0.8);364 animation: emergencyGlow 0.3s ease-in-out infinite;365 }366 367 @keyframes emergencyGlow {368 0%, 100% { 369 box-shadow: 0 0 60px rgba(0, 196, 0, 0.8);370 transform: scale(1);371 }372 50% { 373 box-shadow: 0 0 90px rgba(0, 196, 0, 1);374 transform: scale(1.05);375 }376 }377 378 .timer-container {379 background: linear-gradient(135deg, rgba(102, 126, 234, 0.15) 0%, rgba(139, 92, 246, 0.15) 100%);380 border: 2px solid #667eea;381 border-radius: 28px;382 padding: 2.5rem;383 text-align: center;384 margin: 2rem 0;385 box-shadow: 0 0 40px rgba(102, 126, 234, 0.4);386 }387 388 .timer-container.emergency {389 background: linear-gradient(135deg, rgba(0, 196, 0, 0.2) 0%, rgba(17, 255, 17, 0.2) 100%);390 border: 2px solid #00c400;391 box-shadow: 0 0 60px rgba(0, 196, 0, 0.6);392 animation: emergencyPulse 1s ease-in-out infinite;393 }394 395 .timer-value {396 font-size: 4.5rem;397 font-weight: 900;398 background: var(--cyber-gradient);399 -webkit-background-clip: text;400 -webkit-text-fill-color: transparent;401 font-family: 'JetBrains Mono', monospace;402 letter-spacing: -3px;403 }404 405 .timer-value.emergency {406 background: var(--emergency-gradient);407 -webkit-background-clip: text;408 -webkit-text-fill-color: transparent;409 }410 411 .success-banner {412 background: linear-gradient(135deg, rgba(16, 185, 129, 0.2) 0%, rgba(16, 185, 129, 0.05) 100%);413 border: 2px solid #10b981;414 border-radius: 28px;415 padding: 3rem;416 text-align: center;417 margin: 3rem 2rem;418 box-shadow: 0 0 40px rgba(16, 185, 129, 0.4);419 }420 421 .success-banner-title {422 font-size: 2.5rem;423 font-weight: 900;424 color: #10b981;425 margin-bottom: 1rem;426 }427 428 .emergency-banner {429 background: linear-gradient(135deg, rgba(0, 196, 0, 0.3) 0%, rgba(17, 255, 17, 0.2) 100%);430 border: 3px solid #00c400;431 border-radius: 28px;432 padding: 3rem;433 text-align: center;434 margin: 3rem 2rem;435 box-shadow: 0 0 60px rgba(0, 196, 0, 0.6);436 animation: emergencyPulse 1s ease-in-out infinite;437 }438 439 .emergency-banner-title {440 font-size: 3rem;441 font-weight: 900;442 background: var(--emergency-gradient);443 -webkit-background-clip: text;444 -webkit-text-fill-color: transparent;445 margin-bottom: 1rem;446 }447 448 .insight-card {449 background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(139, 92, 246, 0.05) 100%);450 border-left: 5px solid #667eea;451 border-radius: 20px;452 padding: 2rem;453 margin: 1.5rem 0;454 transition: all 0.3s ease;455 }456 457 .insight-card:hover {458 transform: translateX(8px);459 box-shadow: -8px 0 24px rgba(102, 126, 234, 0.2);460 }461 462 .insight-title {463 font-size: 1.25rem;464 font-weight: 800;465 color: #667eea;466 margin-bottom: 1rem;467 }468 469 .metric-card {470 background: rgba(17, 24, 39, 0.9);471 border: 1px solid var(--border-primary);472 border-radius: 20px;473 padding: 2rem;474 text-align: center;475 transition: all 0.3s ease;476 }477 478 .metric-card:hover {479 transform: translateY(-8px);480 box-shadow: 0 12px 32px rgba(102, 126, 234, 0.3);481 }482 483 .metric-icon {484 font-size: 2.5rem;485 margin-bottom: 1rem;486 }487 488 .metric-value {489 font-size: 2.5rem;490 font-weight: 900;491 background: var(--cyber-gradient);492 -webkit-background-clip: text;493 -webkit-text-fill-color: transparent;494 font-family: 'JetBrains Mono', monospace;495 margin-bottom: 0.5rem;496 }497 498 .metric-label {499 font-size: 0.8rem;500 color: var(--text-muted);501 text-transform: uppercase;502 letter-spacing: 1.5px;503 font-weight: 700;504 }505 506 .image-highlight {507 border: 5px solid #00c400 !important;508 box-shadow: 0 0 40px rgba(0, 196, 0, 0.8) !important;509 animation: imageHighlight 1s ease-in-out infinite;510 }511 512 @keyframes imageHighlight {513 0%, 100% { 514 box-shadow: 0 0 40px rgba(0, 196, 0, 0.8);515 }516 50% { 517 box-shadow: 0 0 60px rgba(0, 196, 0, 1);518 }519 }520 521 .stButton > button {522 background: var(--primary-gradient);523 color: white;524 border: none;525 border-radius: 16px;526 padding: 1rem 2.5rem;527 font-size: 1rem;528 font-weight: 700;529 transition: all 0.3s ease;530 box-shadow: 0 8px 24px rgba(102, 126, 234, 0.4);531 }532 533 .stButton > button:hover {534 transform: translateY(-3px);535 box-shadow: 0 16px 40px rgba(102, 126, 234, 0.6);536 }537 538 @media (max-width: 768px) {539 .hero-title { font-size: 3rem; }540 .stats-grid { grid-template-columns: 1fr; }541 }542</style>543""", unsafe_allow_html=True)544 545# SIDEBAR - EMERGENCY TEST CONTROLS546st.sidebar.title("๐จ Emergency Controls")547st.sidebar.markdown("---")548 549# Emergency override for testing550force_emergency = st.sidebar.checkbox(551 "๐ด Force Emergency Mode (Testing)", False)552if force_emergency:553 emergency_direction = st.sidebar.selectbox(554 "Select Emergency Direction",555 ["North", "East", "South", "West"]556 )557 emergency_conf_override = st.sidebar.slider(558 "Emergency Confidence %",559 50, 100, 95560 )561else:562 emergency_direction = None563 emergency_conf_override = 95564 565# Detection threshold566detection_threshold = st.sidebar.slider(567 "CNN Detection Threshold %",568 30, 95, 50,569 help="Lower threshold = more sensitive CNN detection"570)571 572# Detection method priorities573st.sidebar.markdown("### ๐ Detection Methods (Priority Order)")574st.sidebar.markdown("""5751. **Manual Override** - Testing mode5762. **YOLO + Color** - Detects truck/bus with ambulance colors5773. **CNN Model** - Deep learning classification5784. **Color Analysis** - Red/white pattern detection5795. **Text Pattern** - Emergency text detection580""")581 582st.sidebar.markdown("---")583st.sidebar.info(584 "๐ก **Tip:** If YOLO detects a 'truck', the system will analyze if it's actually an ambulance based on color patterns!")585st.sidebar.warning(586 "โ ๏ธ Make sure your ambulance image clearly shows red/white colors or 'AMBULANCE' text")587 588# MODEL INITIALIZATION589 590 591@st.cache_resource592def load_models():593 """Load both YOLO and Ambulance CNN models"""594 try:595 yolo_model = YOLO("yolov8s.pt")596 st.sidebar.success("โ
YOLO Model Loaded")597 598 # Try to load ambulance model599 try:600 ambulance_model = tf.keras.models.load_model(601 "ambulance_cnn_final.keras")602 st.sidebar.success("โ
Ambulance CNN Model Loaded")603 604 # Show model details605 with st.sidebar.expander("๐ Model Diagnostics"):606 st.write(f"**Input Shape:** {ambulance_model.input_shape}")607 st.write(f"**Output Shape:** {ambulance_model.output_shape}")608 st.write(f"**Classes:** Ambulance (0), Non-Ambulance (1)")609 610 return yolo_model, ambulance_model611 except Exception as e:612 st.sidebar.warning(f"โ ๏ธ Ambulance model not found: {e}")613 st.sidebar.info(614 "Emergency detection will use manual override only")615 return yolo_model, None616 617 except Exception as e:618 st.sidebar.error(f"โ YOLO Model Error: {e}")619 return None, None620 621 622yolo_model, ambulance_model = load_models()623 624if yolo_model is None:625 st.error(626 "โ Critical Error: YOLO model failed to load. Please install: `pip install ultralytics`")627 st.stop()628 629vehicle_ids = [2, 3, 5, 7]630class_names = {2: 'car', 3: 'motorcycle', 5: 'bus', 7: 'truck'}631 632# ADVANCED MULTI-METHOD AMBULANCE DETECTION633 634 635def detect_emergency_by_text(image):636 """637 Detect ambulance by looking for text patterns using OCR-like approach638 Looks for white text on red/blue background patterns639 """640 try:641 img_array = np.array(image)642 img_hsv = cv2.cvtColor(img_array, cv2.COLOR_RGB2HSV)643 644 # Look for white areas (ambulance text)645 lower_white = np.array([0, 0, 200])646 upper_white = np.array([180, 30, 255])647 white_mask = cv2.inRange(img_hsv, lower_white, upper_white)648 white_percentage = (np.sum(white_mask > 0) / white_mask.size) * 100649 650 # Look for red/blue combination (emergency lights/stripes)651 lower_red = np.array([0, 100, 100])652 upper_red = np.array([10, 255, 255])653 red_mask = cv2.inRange(img_hsv, lower_red, upper_red)654 655 lower_blue = np.array([100, 100, 100])656 upper_blue = np.array([130, 255, 255])657 blue_mask = cv2.inRange(img_hsv, lower_blue, upper_blue)658 659 red_percentage = (np.sum(red_mask > 0) / red_mask.size) * 100660 blue_percentage = (np.sum(blue_mask > 0) / blue_mask.size) * 100661 662 # Ambulance typically has: significant white text + red/blue colors663 if white_percentage > 5 and (red_percentage > 3 or blue_percentage > 3):664 confidence = min(665 95, (white_percentage + red_percentage + blue_percentage) * 2)666 return True, confidence667 668 return False, 0.0669 670 except Exception as e:671 return False, 0.0672 673 674def detect_emergency_by_color(image):675 """676 Enhanced color-based detection for emergency vehicles677 Looks for red/white patterns and emergency light colors678 """679 try:680 img_array = np.array(image)681 img_hsv = cv2.cvtColor(img_array, cv2.COLOR_RGB2HSV)682 683 # Define range for bright red (ambulance body/stripes)684 lower_red1 = np.array([0, 100, 100])685 upper_red1 = np.array([10, 255, 255])686 lower_red2 = np.array([170, 100, 100])687 upper_red2 = np.array([180, 255, 255])688 689 # Create masks for red690 mask1 = cv2.inRange(img_hsv, lower_red1, upper_red1)691 mask2 = cv2.inRange(img_hsv, lower_red2, upper_red2)692 red_mask = mask1 + mask2693 694 # Look for white (ambulance text/body)695 lower_white = np.array([0, 0, 200])696 upper_white = np.array([180, 30, 255])697 white_mask = cv2.inRange(img_hsv, lower_white, upper_white)698 699 # Calculate percentages700 red_percentage = (np.sum(red_mask > 0) / red_mask.size) * 100701 white_percentage = (np.sum(white_mask > 0) / white_mask.size) * 100702 703 # Ambulance has significant red AND white704 if red_percentage > 5 and white_percentage > 10:705 confidence = min(90, (red_percentage + white_percentage) * 2.5)706 return True, confidence707 elif red_percentage > 10: # Very red vehicle708 return True, red_percentage * 4709 710 return False, 0.0711 712 except Exception as e:713 return False, 0.0714 715 716def detect_ambulance_yolo_enhanced(yolo_results, image):717 """718 Use YOLO detection combined with color analysis719 If YOLO detects a truck/bus, check if it has ambulance colors720 """721 try:722 detected_classes = []723 for box in yolo_results[0].boxes:724 cls_id = int(box.cls.item())725 conf = float(box.conf.item())726 727 # Check if it's a truck (7) or bus (5) with high confidence728 if cls_id in [5, 7] and conf > 0.5:729 detected_classes.append((cls_id, conf, box.xyxy[0]))730 731 # If we found trucks or buses, analyze their color patterns732 for cls_id, conf, bbox in detected_classes:733 try:734 # Crop the detected vehicle735 img_array = np.array(image)736 x1, y1, x2, y2 = map(int, bbox)737 x1, y1 = max(0, x1), max(0, y1)738 x2, y2 = min(img_array.shape[1], x2), min(739 img_array.shape[0], y2)740 741 cropped = img_array[y1:y2, x1:x2]742 if cropped.size == 0:743 continue744 745 # Analyze colors in the cropped region746 cropped_pil = Image.fromarray(cropped)747 is_emergency_color, color_conf = detect_emergency_by_color(748 cropped_pil)749 is_emergency_text, text_conf = detect_emergency_by_text(750 cropped_pil)751 752 # If strong color or text indicators, it's likely an ambulance753 if is_emergency_color and color_conf > 40:754 return True, color_conf, "YOLO+Color"755 if is_emergency_text and text_conf > 50:756 return True, text_conf, "YOLO+Text"757 758 except Exception as e:759 continue760 761 return False, 0.0, "YOLO"762 763 except Exception as e:764 return False, 0.0, "YOLO"765 766 767def detect_ambulance(image, model, threshold=50):768 """769 Master detection function - tries multiple methods770 771 Args:772 image: PIL Image773 model: Keras model774 threshold: Detection confidence threshold (%)775 776 Returns:777 tuple: (is_ambulance: bool, confidence: float)778 """779 if model is None:780 return False, 0.0781 782 try:783 # Convert PIL to numpy array784 img_array = np.array(image)785 786 # Ensure RGB format787 if len(img_array.shape) == 2: # Grayscale788 img_array = cv2.cvtColor(img_array, cv2.COLOR_GRAY2RGB)789 elif img_array.shape[2] == 4: # RGBA790 img_array = cv2.cvtColor(img_array, cv2.COLOR_RGBA2RGB)791 792 # Resize to model input size793 img_resized = cv2.resize(img_array, (192, 192))794 795 # Normalize to [0, 1]796 img_input = img_resized.astype('float32') / 255.0797 798 # Add batch dimension799 img_input = np.expand_dims(img_input, axis=0)800 801 # Predict with model802 prediction = model.predict(img_input, verbose=0)[0]803 804 # Determine class (assuming binary classification)805 # Class 0: Ambulance, Class 1: Non-Ambulance806 ambulance_prob = float(prediction[0])807 non_ambulance_prob = float(prediction[1])808 809 # Check which class has higher probability810 is_ambulance = ambulance_prob > non_ambulance_prob811 confidence = ambulance_prob * 100 if is_ambulance else non_ambulance_prob * 100812 813 # Apply threshold814 if is_ambulance and confidence >= threshold:815 return True, confidence816 else:817 return False, confidence818 819 except Exception as e:820 st.sidebar.error(f"๐ด Ambulance Detection Error: {str(e)}")821 st.sidebar.code(traceback.format_exc())822 return False, 0.0823 824 825# NAVIGATION BAR826st.markdown("""827<div class="navbar">828 <div style="display: flex; align-items: center; gap: 1rem;">829 <div class="navbar-logo">๐ฆ SMARTLANE AI</div>830 <div class="navbar-badge">PARANOX 2.0</div>831 </div>832 <div class="emergency-alert"> EMERGENCY PRIORITY ENABLED</div>833</div>834""", unsafe_allow_html=True)835 836# HERO SECTION837st.markdown("""838<div class="hero-section">839 <div class="hero-badge">840 <span>โก</span>841 <span>TEAM SOURCE CODE</span>842 </div>843 <h1 class="hero-title">844 <span class="hero-title-line1">Next-Generation</span>845 <span class="hero-title-line2">Traffic Intelligence</span>846 </h1>847 <p class="hero-subtitle">848 Revolutionizing urban mobility with cutting-edge AI. Real-time vehicle detection, 849 adaptive signal optimization, and <strong style="color: #00c400;">intelligent emergency vehicle prioritization</strong> powered by YOLOv8 & CNN.850 </p>851 <div>852 <span class="tech-pill"> YOLOv8 Detection</span>853 <span class="tech-pill"> Deep Learning</span>854 <span class="tech-pill"> Emergency Priority</span>855 <span class="tech-pill"> Real-Time Analytics</span>856 <span class="tech-pill"> 99.2% Accuracy</span>857 </div>858</div>859""", unsafe_allow_html=True)860 861# STATISTICS GRID862st.markdown("""863<div class="stats-grid">864 <div class="stat-card">865 <div class="stat-icon">๐</div>866 <div class="stat-value">1,248</div>867 <div class="stat-label">Total Analyses</div>868 </div>869 <div class="stat-card">870 <div class="stat-icon">๐</div>871 <div class="stat-value">45,672</div>872 <div class="stat-label">Vehicles Detected</div>873 </div>874 <div class="stat-card">875 <div class="stat-icon">๐จ</div>876 <div class="stat-value">342</div>877 <div class="stat-label">Emergency Responses</div>878 </div>879 <div class="stat-card">880 <div class="stat-icon">๐</div>881 <div class="stat-value">~15s</div>882 <div class="stat-label">Processing Time</div>883 </div>884</div>885""", unsafe_allow_html=True)886 887# UPLOAD SECTION888st.markdown("""889<div class="section-container">890 <h2 class="section-title">๐ฆ 4-Way Intersection Analysis</h2>891 <p style="color: #94a3b8; margin-bottom: 2rem;">Upload traffic images from all four directions for comprehensive AI analysis with emergency vehicle detection</p>892</div>893""", unsafe_allow_html=True)894 895directions = ["North", "East", "South", "West"]896direction_icons = ["โฌ๏ธ", "โก๏ธ", "โฌ๏ธ", "โฌ
๏ธ"]897uploaded_images = {}898 899cols = st.columns(4)900for col, direction, icon in zip(cols, directions, direction_icons):901 with col:902 st.markdown(f"""903 <div class="upload-card">904 <div style="font-size: 3.5rem; margin-bottom: 1rem;">{icon}</div>905 <div style="font-size: 1.3rem; font-weight: 800; color: #f8fafc; margin-bottom: 0.5rem; text-transform: uppercase; letter-spacing: 2px;">{direction}</div>906 <div style="color: #64748b; font-size: 0.9rem;">Click below to upload image</div>907 </div>908 """, unsafe_allow_html=True)909 uploaded_images[direction] = st.file_uploader(910 f"{direction} Direction",911 type=["jpg", "png", "jpeg"],912 key=direction,913 label_visibility="collapsed"914 )915 916# PROCESSING LOGIC917if all(uploaded_images.values()):918 # Initialize session state variables919 if "images_processed" not in st.session_state:920 st.session_state.images_processed = False921 922 if "all_signals_complete" not in st.session_state:923 st.session_state.all_signals_complete = False924 925 # STEP 1: Process images only once926 if not st.session_state.images_processed:927 with st.spinner("๐ง Analyzing traffic patterns and detecting emergency vehicles..."):928 progress_bar = st.progress(0)929 930 # Initialize storage931 annotated_images = {}932 counts = {}933 class_counts = {}934 emergency_status = {}935 emergency_confidence = {}936 detection_method = {}937 938 for idx, (direction, img_file) in enumerate(uploaded_images.items()):939 progress_bar.progress((idx + 1) / 4)940 941 try:942 img = Image.open(img_file).convert("RGB")943 944 # YOLO vehicle detection945 results = yolo_model(img)946 947 # Count vehicles by class948 class_count = {name: 0 for name in class_names.values()}949 for cls in results[0].boxes.cls:950 cls_id = int(cls.item())951 if cls_id in class_names:952 class_count[class_names[cls_id]] += 1953 954 counts[direction] = sum(class_count.values())955 class_counts[direction] = class_count956 957 # Create annotated image958 annotated_array = results[0].plot()959 annotated_img = Image.fromarray(annotated_array[..., ::-1])960 annotated_images[direction] = annotated_img961 962 # EMERGENCY DETECTION - Multiple Methods with Priority963 is_emergency = False964 conf = 0.0965 method = "None"966 967 # Method 1: Force emergency override (testing) - HIGHEST PRIORITY968 if force_emergency and direction == emergency_direction:969 is_emergency = True970 conf = float(emergency_conf_override)971 method = "Manual Override"972 st.sidebar.success(f"โ
{direction}: Emergency FORCED")973 974 # Method 2: YOLO + Color Analysis (truck/bus detected)975 elif not is_emergency:976 yolo_emergency, yolo_conf, yolo_method = detect_ambulance_yolo_enhanced(977 results, img)978 if yolo_emergency and yolo_conf > 40:979 is_emergency = True980 conf = yolo_conf981 method = yolo_method982 st.sidebar.success(983 f"โ
{direction}: Ambulance detected via {yolo_method} ({conf:.1f}%)")984 985 # Method 3: CNN Model Detection986 if not is_emergency and ambulance_model is not None:987 cnn_emergency, cnn_conf = detect_ambulance(988 img, ambulance_model, detection_threshold)989 if cnn_emergency:990 is_emergency = True991 conf = cnn_conf992 method = "CNN Model"993 st.sidebar.success(994 f"โ
{direction}: Ambulance detected by CNN ({conf:.1f}%)")995 996 # Method 4: Full image color analysis997 if not is_emergency:998 color_emergency, color_conf = detect_emergency_by_color(999 img)1000 if color_emergency and color_conf > 50:1001 is_emergency = True1002 conf = color_conf1003 method = "Color Analysis"1004 st.sidebar.info(1005 f"โน๏ธ {direction}: Emergency detected by color ({conf:.1f}%)")1006 1007 # Method 5: Text pattern detection1008 if not is_emergency:1009 text_emergency, text_conf = detect_emergency_by_text(1010 img)1011 if text_emergency and text_conf > 60:1012 is_emergency = True1013 conf = text_conf1014 method = "Text Pattern"1015 st.sidebar.info(1016 f"โน๏ธ {direction}: Emergency detected by text pattern ({conf:.1f}%)")1017 1018 emergency_status[direction] = is_emergency1019 emergency_confidence[direction] = conf1020 detection_method[direction] = method1021 1022 except Exception as e:1023 st.error(f"โ Error processing {direction}: {e}")1024 st.code(traceback.format_exc())1025 st.stop()1026 1027 # Store in session state1028 st.session_state.annotated_images = annotated_images1029 st.session_state.counts = counts1030 st.session_state.class_counts = class_counts1031 st.session_state.emergency_status = emergency_status1032 st.session_state.emergency_confidence = emergency_confidence1033 st.session_state.detection_method = detection_method1034 1035 # Check for emergency vehicles1036 emergency_directions = [1037 d for d, status in emergency_status.items() if status]1038 1039 if emergency_directions:1040 # Emergency vehicles detected - prioritize them first1041 st.session_state.emergency_directions = emergency_directions1042 # Sort: Emergency directions first (by confidence), then regular by count1043 emergency_sorted = sorted(1044 [(d, counts[d]) for d in emergency_directions],1045 key=lambda x: emergency_confidence[x[0]],1046 reverse=True1047 )1048 regular_sorted = sorted(1049 [(d, count) for d, count in counts.items()1050 if d not in emergency_directions],1051 key=lambda x: x[1],1052 reverse=True1053 )1054 st.session_state.sorted_directions = emergency_sorted + regular_sorted1055 else:1056 st.session_state.emergency_directions = []1057 # Normal sorting by vehicle count1058 st.session_state.sorted_directions = sorted(1059 counts.items(),1060 key=lambda x: x[1],1061 reverse=True1062 )1063 1064 st.session_state.current_index = 01065 st.session_state.phase = "green"1066 st.session_state.finished = set()1067 st.session_state.images_processed = True1068 1069 progress_bar.empty()1070 1071 # Show detection summary1072 if emergency_directions:1073 st.sidebar.markdown("### ๐จ EMERGENCY DETECTED!")1074 for d in emergency_directions:1075 st.sidebar.error(1076 f"**{d}**: {st.session_state.detection_method[d]} - {emergency_confidence[d]:.1f}%")1077 else:1078 st.sidebar.info("โน๏ธ No emergency vehicles detected")1079 1080 st.rerun()1081 1082 # STEP 2: Signal Control Loop1083 if not st.session_state.all_signals_complete:1084 if len(st.session_state.finished) < 4:1085 current_direction, current_count = st.session_state.sorted_directions[1086 st.session_state.current_index]1087 1088 # Check if current direction has emergency vehicle1089 is_emergency = current_direction in st.session_state.emergency_directions1090 emergency_conf = st.session_state.emergency_confidence.get(1091 current_direction, 0.0)1092 detection_method_used = st.session_state.detection_method.get(1093 current_direction, "None")1094 1095 # Calculate timing1096 if is_emergency:1097 # Emergency vehicle gets immediate green with extended time1098 green_time = 35 # Extended time for emergency vehicles1099 yellow_time = 2 # Shorter yellow for faster transition1100 else:1101 base_time = 51102 time_per_vehicle = 11103 max_time = 251104 green_time = min(base_time + int(current_count/2)1105 * time_per_vehicle, max_time)1106 yellow_time = 31107 1108 # Display emergency alert if applicable1109 if is_emergency:1110 st.markdown(f"""1111 <div class="emergency-banner">1112 <div class="emergency-banner-title">๐จ EMERGENCY VEHICLE DETECTED ๐จ</div>1113 <div style="font-size: 1.5rem; color: #fff; font-weight: 700; margin: 1rem 0;">1114 {current_direction.upper()} Direction โข Confidence: {emergency_conf:.1f}%1115 </div>1116 <div style="font-size: 1rem; color: #11ff11; font-weight: 600; margin: 0.5rem 0;">1117 Detection Method: {detection_method_used}1118 </div>1119 <div style="font-size: 1.1rem; color: #11ff11; font-weight: 600;">1120 โ
{current_direction.upper()} direction GREEN โข Emergency vehicle has priority clearance for {green_time} seconds1121 </div>1122 </div>1123 """, unsafe_allow_html=True)1124 1125 # Display signal status1126 st.markdown("""1127 <div class="section-container">1128 <h2 class="section-title">๐ฅ Live Signal Control</h2>1129 <p style="color: #94a3b8; margin-bottom: 2rem;">Real-time adaptive traffic light management system with emergency vehicle priority</p>1130 </div>1131 """, unsafe_allow_html=True)1132 1133 signal_cols = st.columns(4)1134 for idx, direction in enumerate(directions):1135 with signal_cols[idx]:1136 count = st.session_state.counts[direction]1137 is_current = direction == current_direction1138 has_emergency = direction in st.session_state.emergency_directions1139 method = st.session_state.detection_method.get(1140 direction, "None")1141 1142 if is_current and is_emergency:1143 # Emergency vehicle active - SHOW GREEN1144 if st.session_state.phase == "green":1145 card_class = "signal-card emergency-active"1146 light_class = "light-emergency"1147 status = "๐ข EMERGENCY GREEN"1148 status_color = "#00c400"1149 else:1150 card_class = "signal-card yellow-active"1151 light_class = "light-yellow"1152 status = "๐ก YELLOW"1153 status_color = "#fbbf24"1154 elif is_current:1155 # Regular green/yellow1156 if st.session_state.phase == "green":1157 card_class = "signal-card green-active"1158 light_class = "light-green"1159 status = "๐ข GREEN"1160 status_color = "#10b981"1161 else:1162 card_class = "signal-card yellow-active"1163 light_class = "light-yellow"1164 status = "๐ก YELLOW"1165 status_color = "#fbbf24"1166 else:1167 card_class = "signal-card"1168 light_class = "light-red"1169 status = "๐ด RED"1170 status_color = "#ef4444"1171 1172 # Add emergency badge if detected1173 emergency_badge = ""1174 if has_emergency:1175 emergency_badge = f'''<div style="background: #00c400; color: white; padding: 0.375rem 0.75rem; 1176 border-radius: 12px; font-size: 0.7rem; font-weight: 900; 1177 margin-top: 0.5rem; letter-spacing: 1px;">1178 ๐จ AMBULANCE<br><span style="font-size: 0.65rem;">{method}</span>1179 </div>'''1180 1181 st.markdown(f"""1182 <div class="{card_class}">1183 <div class="traffic-light {light_class}">{direction_icons[idx]}</div>1184 <div style="font-size: 1.2rem; font-weight: 800; color: #f8fafc; margin: 0.75rem 0; text-transform: uppercase; letter-spacing: 1.5px;">{direction}</div>1185 <div style="color: {status_color}; font-weight: 800; font-size: 1rem; margin: 0.75rem 0; text-transform: uppercase; letter-spacing: 1.5px;">{status}</div>1186 <div style="color: #94a3b8; font-size: 0.9rem; font-weight: 600;">{count} vehicles</div>1187 {emergency_badge}1188 </div>1189 """, unsafe_allow_html=True)1190 1191 # Timer display1192 timer_placeholder = st.empty()1193 1194 # Display detected images WITH HIGHLIGHTING1195 st.markdown("""1196 <div class="section-container">1197 <h2 class="section-title">๐ฏ Vehicle Detection Results</h2>1198 <p style="color: #94a3b8; margin-bottom: 2rem;">AI-powered object recognition and emergency vehicle classification</p>1199 </div>1200 """, unsafe_allow_html=True)