jableable commited on
Commit
fa2e65b
·
verified ·
1 Parent(s): 3fc877a

Update new_app.py

Browse files
Files changed (1) hide show
  1. new_app.py +107 -73
new_app.py CHANGED
@@ -2,99 +2,133 @@ import streamlit as st
2
  import keras
3
  import numpy as np
4
  from PIL import Image
5
- import io, os, urllib.request
6
 
7
  st.set_page_config(layout="wide")
8
 
9
- # ---------- Caching & helpers ----------
10
- @st.cache_data(show_spinner=False, ttl=3600)
11
- def fetch_satellite_tile(lat, lng, zoom=16, size=(640, 640), api_key=""):
12
  if not api_key:
13
- raise RuntimeError("Google Static Maps API key is missing.")
14
- size_str = f"{size[0]}x{size[1]}"
15
  url = (
16
- "https://maps.googleapis.com/maps/api/staticmap?"
17
- f"center={lat},{lng}&zoom={zoom}&size={size_str}&maptype=satellite&scale=2&key={api_key}"
18
  )
19
- req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
20
- with urllib.request.urlopen(req, timeout=10) as resp:
21
- buffer = io.BytesIO(resp.read())
22
  return Image.open(buffer).convert("RGB")
23
 
 
24
  @st.cache_resource
25
  def get_model():
 
26
  return keras.models.load_model("0.0008-0.92.keras", compile=False)
27
 
28
- def preprocess(img: Image.Image, size=(640, 640)) -> np.ndarray:
29
- arr = np.asarray(img, dtype=np.float32) # no /255.0, no resize
30
- return np.expand_dims(arr, axis=0)
31
 
32
- def status_text(pct: float) -> str:
33
- if pct >= 90: return "extremely likely"
34
- if pct >= 60: return "likely"
35
- if pct >= 40: return "a coin toss whether"
36
- if pct >= 10: return "unlikely"
37
- return "extremely unlikely"
38
-
39
- # ---------- Styling ----------
40
  st.markdown("""
41
- <style>
42
- .block-container { padding-top: 1rem; padding-bottom: 0rem; padding-left: 5rem; padding-right: 5rem; }
43
- </style>
44
- """, unsafe_allow_html=True)
45
-
46
- # ---------- Header row (two columns) ----------
47
- h1, h2 = st.columns([1,1], gap="large")
48
- with h1:
49
- st.header("Overpass Identifier")
50
- with h2:
51
- st.image("overpass.png")
 
 
 
 
 
 
 
 
 
52
 
53
  st.write("---")
54
 
55
- # Defaults
56
- img_size = (640, 640)
57
- model = get_model()
58
- lat = st.session_state.get("lat", 39.11)
59
- lng = st.session_state.get("lng", -86.56)
60
-
61
- # ---------- Main content row (three columns: Pred | Image | Inputs) ----------
62
- pred_col, img_col, form_col = st.columns([1,1,1], gap="large")
63
-
64
- # Right: inputs (form to avoid mid-typing reruns)
65
- with form_col:
66
- st.subheader("Enter latitude/longitude coordinates:")
67
- with st.form("coords"):
68
- c1, c2 = st.columns(2)
69
- with c1:
70
- lat = st.number_input("Latitude", value=float(lat), min_value=-90.0, max_value=90.0, step=0.01, format="%.4f")
71
- with c2:
72
- lng = st.number_input("Longitude", value=float(lng), min_value=-180.0, max_value=180.0, step=0.01, format="%.4f")
73
- submitted = st.form_submit_button("Get Image and Prediction")
74
-
75
- # Center: image
76
- img = None
77
- if submitted:
78
- st.session_state.lat, st.session_state.lng = lat, lng
 
79
  try:
80
- with st.spinner("Fetching satellite tile..."):
81
- img = fetch_satellite_tile(lat, lng, size=img_size, api_key=os.getenv("goog_api", ""))
82
  except Exception as e:
83
- st.error(f"Error fetching image: {e}")
84
 
85
- with img_col:
86
- if img is not None:
87
- st.image(img, caption=f"{lat:.4f}, {lng:.4f}", use_column_width=True)
88
 
89
- # Left: prediction
90
- with pred_col:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  st.subheader("Prediction")
92
- if img is not None:
 
 
 
93
  with st.spinner("Running inference..."):
94
- x = preprocess(img, size=img_size)
95
- y = model(x, training=False).numpy() # adjust index if your model differs
96
- crossing_chance = float(y[0][1] * 100.0)
97
- st.markdown(f"**It’s {status_text(crossing_chance)} that there’s an overpass here.**")
98
- st.write(f"Estimated probability: **{crossing_chance:.2f}%**.")
99
- else:
100
- st.caption("Submit coordinates to see the satellite image and prediction.")
 
 
 
 
 
 
 
 
 
 
 
2
  import keras
3
  import numpy as np
4
  from PIL import Image
5
+ import io, urllib.request, os
6
 
7
  st.set_page_config(layout="wide")
8
 
9
+
10
+ @st.cache_data(show_spinner=False, ttl=600)
11
+ def fetch_satellite_tile(lat, lng, zoom=16, size="640x640", api_key=""):
12
  if not api_key:
13
+ raise RuntimeError("Missing Google Static Maps API key in env var 'goog_api'.")
 
14
  url = (
15
+ f"https://maps.googleapis.com/maps/api/staticmap?"
16
+ f"center={lat},{lng}&zoom={zoom}&size={size}&maptype=satellite&key={api_key}"
17
  )
18
+ buffer = io.BytesIO(urllib.request.urlopen(url, timeout=10).read())
 
 
19
  return Image.open(buffer).convert("RGB")
20
 
21
+
22
  @st.cache_resource
23
  def get_model():
24
+ # compile=False skips optimizer/state rebuild, which saves time
25
  return keras.models.load_model("0.0008-0.92.keras", compile=False)
26
 
 
 
 
27
 
 
 
 
 
 
 
 
 
28
  st.markdown("""
29
+ <style>
30
+ .block-container {
31
+ padding-top: 1rem;
32
+ padding-bottom: 0rem;
33
+ padding-left: 5rem;
34
+ padding-right: 5rem;
35
+ }
36
+ </style>
37
+ """, unsafe_allow_html=True)
38
+
39
+ #title
40
+ col1, col2 = st.columns(2)
41
+ with col1:
42
+ _, col = st.columns(2)
43
+ with col:
44
+ st.header('Overpass Identifier')
45
+ with col2:
46
+ _, col, _ = st.columns(3)
47
+ with col:
48
+ st.image('overpass.png')
49
 
50
  st.write("---")
51
 
52
+ #load model and initialize image size required by model. uploaded images are resized to indicated size
53
+ img_height = 640
54
+ img_width = 640
55
+
56
+ state = st.session_state
57
+ state.loaded_model = get_model()
58
+
59
+ #if "loaded_model" not in state:
60
+ # with st.spinner('Loading model. This may take a few seconds...'):
61
+ # state.loaded_model = keras.models.load_model("0.0008-0.92.keras")
62
+
63
+ if "lat" not in state:
64
+ state.lat = 39.11
65
+
66
+ if "lng" not in state:
67
+ state.lng = -86.56
68
+
69
+ if "coords_submitted" not in state:
70
+ state.coords_submitted = False
71
+
72
+ if "img" not in state:
73
+ state.img = None
74
+
75
+ # Preload default image once
76
+ if state.img is None:
77
  try:
78
+ api_key = os.getenv("goog_api", "")
79
+ state.img = fetch_satellite_tile(state.lat, state.lng, api_key=api_key)
80
  except Exception as e:
81
+ st.info(f"Couldn’t fetch default tile: {e}")
82
 
83
+ col1, col2, col3 = st.columns(3)
 
 
84
 
85
+ with col3:
86
+ #header
87
+ st.subheader('Enter latitude/longitude coordinates:')
88
+ coll, colr= st.columns(2)
89
+ with coll:
90
+ state.lat = st.number_input('Latitude', value=39.11, min_value=-90., max_value=90., step=.01)
91
+ st.write('The current lat/long are:')
92
+ with colr:
93
+ state.lng = st.number_input('Longitude', value=-86.56, min_value=-180., max_value=180., step=.01)
94
+ st.write(str(state.lat)+', '+str(state.lng))
95
+ with st.form("my_form"):
96
+ submit_button = st.form_submit_button(
97
+ label="Get Image and Prediction", on_click=lambda: state.update(coords_submitted=True))
98
+
99
+ with col2:
100
+ if state.coords_submitted:
101
+ state.coords_submitted = False
102
+ try:
103
+ api_key = os.getenv("goog_api", "")
104
+ state.img = fetch_satellite_tile(state.lat, state.lng, api_key=api_key)
105
+ except Exception as e:
106
+ st.error(f"Error fetching image: {e}")
107
+
108
+ if state.img is not None:
109
+ st.image(state.img, use_container_width = True)
110
+
111
+ with col1:
112
  st.subheader("Prediction")
113
+ if state.img is not None:
114
+ img_array = np.array(state.img)
115
+ batch_size = 1
116
+ img_array = np.reshape(img_array,[batch_size,img_height,img_width,3])
117
  with st.spinner("Running inference..."):
118
+ result = state.loaded_model.predict(img_array)
119
+ crossing_chance = result[0][1]*100
120
+ status = None
121
+ if crossing_chance >= 90:
122
+ status = "extremely likely"
123
+ elif crossing_chance >= 60:
124
+ status = "likely"
125
+ elif crossing_chance >= 40:
126
+ status = "a coin toss whether"
127
+ elif crossing_chance >= 10:
128
+ status = "unlikely"
129
+ elif crossing_chance >= 0:
130
+ status = "extremely unlikely"
131
+
132
+ st.write(f"It's {status} there's an overpass here.")
133
+ st.write("")
134
+ st.write(f"In fact, the likelihood of at least one overpass is {np.round(crossing_chance,decimals=2)}%.")