Spaces:
Sleeping
Sleeping
| import os | |
| import tempfile | |
| import json | |
| import streamlit as st | |
| from PIL import Image | |
| import pandas as pd | |
| try: | |
| from gradio_client import Client, handle_file | |
| except ImportError: # pragma: no cover - optional dependency | |
| Client = None | |
| SPACE_ID = "BARATH0070/plate-detector" | |
| # Try common Gradio API endpoint names | |
| COMMON_API_NAMES = [ | |
| "/detect_and_save", # Function name | |
| "/query_database", # Function name | |
| "/predict", # Default Gradio names | |
| "/predict_0", | |
| "/predict_1", | |
| "/run", # Run endpoint | |
| "/run_0", | |
| "/run_1", | |
| ] | |
| # Initialize session state for API names | |
| if "detect_api" not in st.session_state: | |
| st.session_state.detect_api = "/predict_0" | |
| if "query_api" not in st.session_state: | |
| st.session_state.query_api = "/predict_1" | |
| if "query_input" not in st.session_state: | |
| st.session_state.query_input = "" | |
| # Example queries for testing | |
| EXAMPLE_QUERIES = [ | |
| "Show TN vehicles", | |
| "How many cars detected?", | |
| "Show all trucks", | |
| "Count bikes in database", | |
| "Show latest 10 detections", | |
| "Vehicles from adyar", | |
| "Top detected plates", | |
| "Vehicle type distribution", | |
| "Show vehicles with high confidence", | |
| "Traffic by hour" | |
| ] | |
| def find_api_endpoints(): | |
| """Try to find available API endpoints""" | |
| if Client is None: | |
| return [] | |
| try: | |
| client = Client(SPACE_ID) | |
| # Try to get API info | |
| available = [] | |
| for api_name in COMMON_API_NAMES: | |
| try: | |
| # Just check if the endpoint exists by attempting a view | |
| available.append(api_name) | |
| except: | |
| pass | |
| return available | |
| except Exception as e: | |
| print(f"Error finding APIs: {e}") | |
| return [] | |
| def get_available_apis(): | |
| """Get list of available API functions from the Space""" | |
| try: | |
| if Client is None: | |
| return None | |
| client = Client(SPACE_ID) | |
| # Try to view API | |
| info = client.view_api() | |
| return info | |
| except Exception as e: | |
| return None | |
| def call_space(pil_image): | |
| if Client is None: | |
| raise RuntimeError("gradio_client is not installed.") | |
| client = Client(SPACE_ID) | |
| with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp: | |
| pil_image.save(tmp.name) | |
| tmp_path = tmp.name | |
| try: | |
| image_input = handle_file(tmp_path) | |
| # Try the configured API | |
| try: | |
| print(f"Trying detection API: {st.session_state.detect_api}") | |
| return client.predict(image_input, api_name=st.session_state.detect_api) | |
| except Exception as e: | |
| error_msg = str(e) | |
| print(f"Error with {st.session_state.detect_api}: {error_msg}") | |
| # Try other common names | |
| for api_name in ["/predict_0", "/predict", "/run"]: | |
| try: | |
| print(f"Trying {api_name}...") | |
| result = client.predict(image_input, api_name=api_name) | |
| st.session_state.detect_api = api_name | |
| st.success(f"β Found working endpoint: {api_name}") | |
| return result | |
| except: | |
| continue | |
| raise RuntimeError(f"Could not find working detection endpoint.\n\nTried: {COMMON_API_NAMES}") | |
| finally: | |
| if os.path.exists(tmp_path): | |
| os.remove(tmp_path) | |
| def query_space(user_query): | |
| """Call the NLP-to-SQL query function from the Space""" | |
| if Client is None: | |
| raise RuntimeError("gradio_client is not installed.") | |
| client = Client(SPACE_ID) | |
| try: | |
| print(f"Trying query API: {st.session_state.query_api}") | |
| result = client.predict(user_query, api_name=st.session_state.query_api) | |
| return result | |
| except Exception as e: | |
| error_msg = str(e) | |
| print(f"Error with {st.session_state.query_api}: {error_msg}") | |
| # Try other common names | |
| for api_name in ["/predict_1", "/predict", "/run"]: | |
| try: | |
| print(f"Trying {api_name}...") | |
| result = client.predict(user_query, api_name=api_name) | |
| st.session_state.query_api = api_name | |
| st.success(f"β Found working endpoint: {api_name}") | |
| return result | |
| except: | |
| continue | |
| return {"error": f"Could not find working query endpoint.\n\nTried: {COMMON_API_NAMES}"} | |
| # Page configuration | |
| st.set_page_config( | |
| page_title="Vehicle Intelligence System", | |
| page_icon="π", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| # Custom CSS for better styling | |
| st.markdown(""" | |
| <style> | |
| .main { | |
| background-color: #f8f9fa; | |
| } | |
| .stTabs [data-baseweb="tab-list"] { | |
| gap: 2px; | |
| } | |
| .stTabs [data-baseweb="tab"] { | |
| height: 50px; | |
| white-space: pre-wrap; | |
| background-color: #e0e0e0; | |
| border-radius: 4px 4px 0 0; | |
| } | |
| .stTabs [aria-selected="true"] { | |
| background-color: #1f77b4; | |
| color: white; | |
| } | |
| .result-card { | |
| background-color: white; | |
| padding: 20px; | |
| border-radius: 10px; | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
| margin: 10px 0; | |
| } | |
| .success-card { | |
| background-color: #d4edda; | |
| border-left: 5px solid #28a745; | |
| padding: 15px; | |
| border-radius: 5px; | |
| } | |
| .error-card { | |
| background-color: #f8d7da; | |
| border-left: 5px solid #dc3545; | |
| padding: 15px; | |
| border-radius: 5px; | |
| } | |
| .info-card { | |
| background-color: #d1ecf1; | |
| border-left: 5px solid #17a2b8; | |
| padding: 15px; | |
| border-radius: 5px; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Header | |
| st.markdown("# π Vehicle Intelligence System") | |
| st.markdown("### Advanced License Plate Detection & NLP Database Query") | |
| st.markdown("---") | |
| # Sidebar | |
| with st.sidebar: | |
| st.markdown("## βοΈ Configuration") | |
| api_status = st.checkbox("Show API Status", value=True) | |
| if api_status: | |
| st.markdown("### π‘ API Status") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.metric("Space ID", SPACE_ID.split("/")[1]) | |
| with col2: | |
| if Client is not None: | |
| st.success("β Client Ready") | |
| else: | |
| st.error("β Client Error") | |
| st.markdown("### π API Names (auto-discovering)") | |
| st.info(f""" | |
| **Current API Names (auto-discovering):** | |
| - Detection: `{st.session_state.detect_api}` | |
| - Query: `{st.session_state.query_api}` | |
| If you see API errors, the app will automatically try other endpoints! | |
| """) | |
| # Show available APIs | |
| if st.button("π Show Available APIs"): | |
| try: | |
| apis = get_available_apis() | |
| if apis: | |
| st.json(apis) | |
| else: | |
| st.warning("Could not retrieve API list") | |
| except Exception as e: | |
| st.error(f"Error: {e}") | |
| st.markdown("---") | |
| st.markdown("### π Quick Links") | |
| st.markdown(""" | |
| - [HF Spaces](https://huggingface.co/spaces) | |
| - [Documentation](#) | |
| - [Report Issue](#) | |
| """) | |
| # Main content area | |
| tab1, tab2, tab3 = st.tabs(["π₯ Detection", "π Database Query", "π Analytics"]) | |
| # ============= TAB 1: DETECTION ============= | |
| with tab1: | |
| st.markdown("## License Plate Detection") | |
| st.markdown("Upload a vehicle image to detect license plates and classify vehicle type.") | |
| col_upload, col_preview = st.columns([1, 1]) | |
| with col_upload: | |
| st.markdown("### π€ Upload Image") | |
| uploaded = st.file_uploader( | |
| "Choose an image file", | |
| type=["jpg", "jpeg", "png"], | |
| key="detection_upload" | |
| ) | |
| if uploaded is None: | |
| st.info("π Upload a vehicle image to get started") | |
| else: | |
| st.success(f"β File loaded: {uploaded.name}") | |
| with col_preview: | |
| if uploaded is not None: | |
| pil_image = Image.open(uploaded).convert("RGB") | |
| st.markdown("### πΈ Preview") | |
| st.image(pil_image, use_container_width=True) | |
| # Detection button and results | |
| if uploaded is not None: | |
| if Client is None: | |
| st.error("β gradio_client is not installed. Run: pip install gradio_client") | |
| else: | |
| col_detect, col_clear = st.columns([3, 1]) | |
| with col_detect: | |
| detect_clicked = st.button( | |
| "π Detect License Plate", | |
| use_container_width=True, | |
| key="detect_btn" | |
| ) | |
| with col_clear: | |
| if st.button("π Clear", use_container_width=True): | |
| st.rerun() | |
| if detect_clicked: | |
| with st.spinner("π Detecting license plate..."): | |
| try: | |
| result = call_space(pil_image) | |
| if isinstance(result, (list, tuple)): | |
| text_output = result[0] if len(result) > 0 else "" | |
| json_output = result[1] if len(result) > 1 else {} | |
| else: | |
| text_output = str(result) | |
| json_output = {} | |
| # Display results in columns | |
| col_text, col_json = st.columns([1, 1]) | |
| with col_text: | |
| st.markdown("### π Detection Result") | |
| st.markdown('<div class="success-card">', unsafe_allow_html=True) | |
| st.text(text_output) | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| with col_json: | |
| st.markdown("### π Structured Data") | |
| st.markdown('<div class="result-card">', unsafe_allow_html=True) | |
| st.json(json_output) | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # Store in session state for reference | |
| st.session_state.last_detection = { | |
| "text": text_output, | |
| "json": json_output | |
| } | |
| st.success("β Detection completed successfully!") | |
| except Exception as exc: | |
| st.error(f"β Detection failed: {exc}") | |
| st.markdown('<div class="error-card">', unsafe_allow_html=True) | |
| st.code(str(exc)) | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # ============= TAB 2: DATABASE QUERY ============= | |
| with tab2: | |
| st.markdown("## π Query Database with Natural Language") | |
| st.markdown("Ask questions about detected vehicles in natural language. The AI converts your query to SQL automatically.") | |
| st.markdown("---") | |
| # Two column layout | |
| col_examples, col_input = st.columns([1, 1]) | |
| with col_examples: | |
| st.markdown("### π‘ Quick Examples") | |
| st.markdown('<div class="info-card">', unsafe_allow_html=True) | |
| cols = st.columns(1) | |
| for idx, query in enumerate(EXAMPLE_QUERIES): | |
| if st.button( | |
| f"π {query}", | |
| use_container_width=True, | |
| key=f"example_{idx}" | |
| ): | |
| st.session_state.query_input = query | |
| st.rerun() | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| with col_input: | |
| st.markdown("### π― Custom Query") | |
| st.markdown('<div class="result-card">', unsafe_allow_html=True) | |
| user_query = st.text_area( | |
| "Enter your question about the vehicle database:", | |
| value=st.session_state.query_input, | |
| placeholder="e.g., How many cars were detected today?", | |
| height=150, | |
| key="query_input_field" | |
| ) | |
| col_search, col_clear = st.columns([3, 1]) | |
| with col_search: | |
| search_clicked = st.button( | |
| "π Search Database", | |
| use_container_width=True, | |
| key="search_btn" | |
| ) | |
| with col_clear: | |
| if st.button("ποΈ Clear", use_container_width=True): | |
| st.session_state.query_input = "" | |
| st.rerun() | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # Query results section | |
| if search_clicked: | |
| if not user_query.strip(): | |
| st.warning("β οΈ Please enter a query") | |
| else: | |
| with st.spinner("β³ Processing query..."): | |
| try: | |
| result = query_space(user_query) | |
| # Check for errors | |
| if isinstance(result, dict) and result.get("error"): | |
| st.error(f"β Query Error: {result['error']}") | |
| else: | |
| st.success("β Query executed successfully!") | |
| # Display results in tabs | |
| result_tab1, result_tab2, result_tab3 = st.tabs([ | |
| "π SQL Query", | |
| "π Results Table", | |
| "π Full Response" | |
| ]) | |
| with result_tab1: | |
| st.markdown("### Generated SQL") | |
| if isinstance(result, dict): | |
| sql_query = result.get("sql", "N/A") | |
| st.code(sql_query, language="sql") | |
| with result_tab2: | |
| st.markdown("### Query Results") | |
| if isinstance(result, dict): | |
| query_result = result.get("result", []) | |
| if query_result: | |
| # Convert to DataFrame for better display | |
| try: | |
| df = pd.DataFrame(query_result) | |
| st.dataframe( | |
| df, | |
| use_container_width=True, | |
| height=400 | |
| ) | |
| # Display summary | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.metric("π Total Records", len(df)) | |
| with col2: | |
| st.metric("π Columns", len(df.columns)) | |
| with col3: | |
| st.metric("πΎ Size", f"{df.memory_usage(deep=True).sum() / 1024:.1f} KB") | |
| except Exception as e: | |
| st.write(query_result) | |
| else: | |
| st.info("βΉοΈ No results found for this query") | |
| with result_tab3: | |
| st.markdown("### Full API Response") | |
| st.json(result) | |
| except Exception as exc: | |
| st.error(f"β Query failed: {exc}") | |
| with st.expander("Show error details"): | |
| st.code(str(exc)) | |
| # ============= TAB 3: ANALYTICS ============= | |
| with tab3: | |
| st.markdown("## π Analytics Dashboard") | |
| st.markdown("View comprehensive analytics about vehicle detections.") | |
| st.markdown("---") | |
| st.info(""" | |
| π **This dashboard displays analytics from the connected Hugging Face Space.** | |
| Make sure the Space has processed some vehicle detections for data to appear here. | |
| """) | |
| col_refresh, col_export = st.columns([3, 1]) | |
| with col_refresh: | |
| if st.button( | |
| "π Refresh Analytics", | |
| use_container_width=True, | |
| key="refresh_analytics" | |
| ): | |
| st.rerun() | |
| with col_export: | |
| st.markdown("### πΎ Export") | |
| if st.button("π₯ Download Stats", use_container_width=True): | |
| st.info("Export feature coming soon!") | |
| # Analytics placeholders | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.metric( | |
| "π Total Detections", | |
| "20,626", | |
| "+145 today" | |
| ) | |
| with col2: | |
| st.metric( | |
| "π Unique Locations", | |
| "14", | |
| "+2 new" | |
| ) | |
| with col3: | |
| st.metric( | |
| "π Unique Plates", | |
| "8,432", | |
| "+23 today" | |
| ) | |
| st.markdown("---") | |
| tab_state, tab_hourly, tab_type = st.tabs([ | |
| "πΊοΈ By State", | |
| "β° By Hour", | |
| "π By Vehicle Type" | |
| ]) | |
| with tab_state: | |
| st.markdown("### Vehicles Detected by State") | |
| st.info("Data from database - shows vehicle distribution across Indian states") | |
| # Placeholder for state analytics | |
| placeholder_state = pd.DataFrame({ | |
| "State": ["TN", "KA", "KL", "AP", "TS"], | |
| "Count": [8500, 5200, 3100, 2400, 1426] | |
| }) | |
| st.bar_chart(placeholder_state.set_index("State")) | |
| with tab_hourly: | |
| st.markdown("### Traffic by Hour of Day") | |
| st.info("Shows peak detection hours") | |
| # Placeholder for hourly analytics | |
| placeholder_hourly = pd.DataFrame({ | |
| "Hour": list(range(24)), | |
| "Traffic": [100 + i*20 for i in range(24)] | |
| }) | |
| st.line_chart(placeholder_hourly.set_index("Hour")) | |
| with tab_type: | |
| st.markdown("### Vehicle Type Distribution") | |
| st.info("Shows breakdown of detected vehicle types") | |
| # Placeholder for vehicle type analytics | |
| placeholder_type = pd.DataFrame({ | |
| "Type": ["Car", "Truck", "Bus", "Bike", "Auto", "Others"], | |
| "Count": [12000, 4500, 2100, 1200, 600, 226] | |
| }) | |
| st.bar_chart(placeholder_type.set_index("Type")) | |
| # Footer | |
| st.markdown("---") | |
| st.markdown(""" | |
| <div style='text-align: center; color: #666;'> | |
| <small>π Vehicle Intelligence System | Powered by Hugging Face Spaces & Streamlit</small> | |
| <br> | |
| <small>Last updated: 2026-05-14</small> | |
| </div> | |
| """, unsafe_allow_html=True) | |