Spaces:
Running
Running
File size: 4,163 Bytes
749787c 56ed549 d6091f9 610e7e5 749787c 56ed549 1e99778 56ed549 d6091f9 610e7e5 d6091f9 56ed549 610e7e5 d6091f9 610e7e5 56ed549 d6091f9 56ed549 d6091f9 56ed549 d6091f9 56ed549 d6091f9 56ed549 d6091f9 56ed549 0259dad d6091f9 56ed549 0259dad |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
import streamlit as st
import base64
import requests
import json
import io
from PIL import Image
st.set_page_config(page_title="Solar Rooftop Analyzer", layout="centered")
st.title("\U0001F31E Solar Rooftop Analysis")
st.markdown("Upload a rooftop image and provide your location and budget. The system will analyze the rooftop and estimate potential solar installation ROI.")
OPENROUTER_API_KEY = "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"
VISION_MODEL_NAME = "opengvlab/internvl3-14b:free"
def analyze_image_with_openrouter(image_file):
# Read and convert image to JPEG bytes
img = Image.open(image_file).convert("RGB")
buffer = io.BytesIO()
img.save(buffer, format="JPEG")
jpeg_bytes = buffer.getvalue()
# Base64 encode with content-type prefix
encoded_image = "data:image/jpeg;base64," + base64.b64encode(jpeg_bytes).decode("utf-8")
prompt = (
"Analyze the rooftop in this image. Output JSON with: [Roof area (sqm), "
"Sunlight availability (%), Shading (Yes/No), Recommended solar panel type, "
"Estimated capacity (kW)]."
)
headers = {
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
"Content-Type": "application/json"
}
payload = {
"model": VISION_MODEL_NAME,
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{"type": "image_url", "image_url": {"url": encoded_image}}
]
}
]
}
response = requests.post("https://openrouter.ai/api/v1/chat/completions", json=payload, headers=headers)
if response.status_code == 200:
return response.json()
return {"error": f"Failed to analyze image. Status code: {response.status_code}, Response: {response.text}"}
def estimate_roi(roof_area, capacity_kw, budget):
cost_per_kw = 65000 # INR/kW
estimated_cost = capacity_kw * cost_per_kw
incentives = estimated_cost * 0.30
net_cost = estimated_cost - incentives
annual_savings = capacity_kw * 1500 * 7
payback_years = round(net_cost / annual_savings, 2)
return {
"estimated_cost": estimated_cost,
"incentives": incentives,
"net_cost": net_cost,
"annual_savings": annual_savings,
"payback_years": payback_years,
"within_budget": budget >= net_cost
}
with st.form("solar_form"):
uploaded_file = st.file_uploader("Upload Rooftop Image", type=["jpg", "jpeg", "png"])
location = st.text_input("Location")
budget = st.number_input("Budget (INR)", min_value=10000.0, step=1000.0)
submitted = st.form_submit_button("Analyze")
if submitted:
if uploaded_file and location and budget:
st.image(uploaded_file, caption="Uploaded Rooftop Image", use_column_width=True)
with st.spinner("Analyzing rooftop image..."):
ai_response = analyze_image_with_openrouter(uploaded_file)
if "choices" in ai_response:
try:
choice = ai_response["choices"][0]
# Some models may return content as a string, others as a dict
content = choice.get("message", {}).get("content", "")
content_json = json.loads(content)
st.success("Analysis complete!")
st.subheader("Rooftop Analysis")
st.json(content_json)
if "Roof area (sqm)" in content_json and "Estimated capacity (kW)" in content_json:
roi = estimate_roi(
roof_area=content_json["Roof area (sqm)"],
capacity_kw=content_json["Estimated capacity (kW)"],
budget=budget
)
st.subheader("ROI Estimation")
st.json(roi)
except Exception as e:
st.error(f"Error parsing analysis content: {e}")
st.json(ai_response)
else:
st.error("Failed to analyze the image. Please try again.")
else:
st.warning("Please upload an image and fill all fields.")
|