hornet-bicho/streamlitApp
0
1import streamlit as st2import numpy as np3import os4import io5from PIL import Image6import tensorflow.lite as tflite7 8# Config must be the first streamlit command called9st.set_page_config(10 page_title="METEO // VISION", 11 layout="wide", 12 initial_sidebar_state="collapsed"13)14 15# Custom inject CSS for minimalist typography layout (no icons)16st.markdown("""17 <style>18 /* Global styles */19 html, body, [data-testid="stAppViewContainer"] {20 background-color: #fafafa;21 font-family: monospace;22 }23 h1, h2, h3 {24 font-family: monospace !important;25 font-weight: 700 !important;26 letter-spacing: -0.05em;27 }28 /* Style progress bars to match minimal look */29 .stProgress > div > div > div > div {30 background-color: #111111;31 border-radius: 0px;32 }33 /* Flatten buttons */34 div.stButton > button {35 border-radius: 0px !important;36 border: 1px solid #111111 !important;37 background-color: transparent;38 color: #111111;39 }40 div.stButton > button:hover {41 background-color: #111111 !important;42 color: white !important;43 }44 </style>45""", unsafe_allow_html=True)46 47# ==========================================48# 1. TFLITE MODEL LOADING & INFERENCE49# ==========================================50@st.cache_resource51def load_tflite_model(model_path):52 interpreter = tflite.Interpreter(model_path=model_path)53 interpreter.allocate_tensors()54 return interpreter55 56def predict_weather(image_bytes, interpreter):57 try:58 # Get model configurations59 input_details = interpreter.get_input_details()60 output_details = interpreter.get_output_details()61 62 input_shape = input_details[0]['shape'] 63 h, w = input_shape[1], input_shape[2]64 65 # Safely open image from raw bytes66 img = Image.open(io.BytesIO(image_bytes)).convert('RGB')67 img = img.resize((w, h))68 69 # Process arrays safely70 img_array = np.array(img, dtype=np.float32) / 255.071 img_tensor = np.expand_dims(img_array, axis=0)72 73 # Run execution engine74 interpreter.set_tensor(input_details[0]['index'], img_tensor)75 interpreter.invoke()76 77 # Extract predictions78 output_data = interpreter.get_tensor(output_details[0]['index'])[0]79 80 # Dynamically map output shape to avoid mismatch errors81 classes = ["Clear Sky", "Overcast / Cloudy", "Rainy / Stormy", "Foggy / Misty"]82 predictions = {}83 for i in range(len(output_data)):84 class_name = classes[i] if i < len(classes) else f"Class Variant {i}"85 predictions[class_name] = float(output_data[i])86 87 return predictions, None88 89 except Exception as e:90 return None, str(e)91 92# Find and dynamically bind the local file path inside the src folder environment93try:94 base_dir = os.path.dirname(os.path.abspath(__file__))95 model_path = os.path.join(base_dir, "weather_cnn.tflite")96 97 interpreter = load_tflite_model(model_path)98 model_loaded = True99except Exception as e:100 model_loaded = False101 model_error_msg = str(e)102 103# ==========================================104# 2. STYLED STREAMLIT FRONTEND105# ==========================================106 107st.title("METEO // VISION")108st.caption("Predicting localized atmospheric conditions via deep learning convolution models.")109st.write("---")110 111if not model_loaded:112 st.error(f"Failed to bind `weather_cnn.tflite` interpreter. Verification string: {model_error_msg}")113else:114 col1, col2 = st.columns(2, gap="large")115 116 with col1:117 st.subheader("VISUAL INTAKE")118 # Remove the radio buttons entirely and stick to a clean file upload box119 target_file = st.file_uploader(120 "Drop sky capture frame or photo", 121 type=["jpg", "png", "jpeg"], 122 label_visibility="collapsed"123 )124 125 with col2:126 st.subheader("METRIC DIAGNOSTICS")127 128 if target_file is not None:129 # 1. Read bytes completely upfront to stop file-pointer leakage crashes130 try:131 file_bytes = target_file.read()132 read_success = True133 except Exception as read_err:134 st.error(f"File buffer read crash: {str(read_err)}")135 read_success = False136 137 if read_success:138 with st.spinner("Processing framework matrices..."):139 predictions, error_message = predict_weather(file_bytes, interpreter)140 141 if error_message:142 st.error(f"Inference Failure: {error_message}")143 elif predictions:144 # Fetch dominant feature state145 top_condition = max(predictions, key=predictions.get)146 confidence = predictions[top_condition] * 100147 148 # Display structural text summary149 st.markdown(f"## {top_condition.upper()}")150 st.markdown(f"Confirmed with **{confidence:.1f}%** model confidence.")151 st.write("---")152 153 # Output sleek probability distributions154 for condition, score in predictions.items():155 st.text(f"{condition:<25} {score*100:>5.1f}%")156 st.progress(max(0.0, min(1.0, score))) # Keep between 0 and 1 bounds157 else:158 st.info("AWAITING DATA. Upload or take an environment photo to pass vectors to the CNN network layer.")