muk42 commited on
Commit
030dcfe
·
1 Parent(s): ba2e7fd

check georef overlay

Browse files
Files changed (1) hide show
  1. map_tab/map_setup.py +87 -50
map_tab/map_setup.py CHANGED
@@ -8,11 +8,36 @@ import numpy as np
8
  from matplotlib import cm, colors
9
  import pandas as pd
10
  import pyproj
 
11
  from config import OUTPUT_DIR
12
  from branca.colormap import linear
13
 
14
  CELL_SIZE_M = 100 # meters
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  def make_map(city, show_grid, show_georef):
17
  city = city.strip()
18
  if not city:
@@ -29,26 +54,39 @@ def make_map(city, show_grid, show_georef):
29
  if not os.path.exists(raster_path):
30
  return "Georeferenced raster not found"
31
 
32
- # Raster bounds and CRS
33
  with rasterio.open(raster_path) as src:
34
  bounds = src.bounds
35
  crs = src.crs
36
 
37
  xmin, ymin, xmax, ymax = bounds
38
- transformer = pyproj.Transformer.from_crs("EPSG:3857", "EPSG:4326", always_xy=True)
 
 
 
 
 
 
 
 
39
 
40
  # Show georeferenced raster if requested
41
  if show_georef:
42
  raster_img_path = os.path.join(OUTPUT_DIR, "georeferenced_rgba.png")
43
- if os.path.exists(raster_img_path):
44
- lon0, lat0 = transformer.transform(xmin, ymin)
45
- lon1, lat1 = transformer.transform(xmax, ymax)
46
- ImageOverlay(
47
- image=raster_img_path,
48
- bounds=[[lat0, lon0], [lat1, lon1]],
49
- opacity=0.7,
50
- interactive=True
51
- ).add_to(m)
 
 
 
 
 
 
52
 
53
  # Grid overlay
54
  if show_grid:
@@ -59,7 +97,6 @@ def make_map(city, show_grid, show_georef):
59
  if df.empty:
60
  continue
61
 
62
- # Tile bounds
63
  tile_xmin, tile_xmax = df['x'].min(), df['x'].max()
64
  tile_ymin, tile_ymax = df['y'].min(), df['y'].max()
65
  n_cols = int(np.ceil((tile_xmax - tile_xmin) / CELL_SIZE_M))
@@ -76,49 +113,49 @@ def make_map(city, show_grid, show_georef):
76
  counts[row_idx, col] += 1
77
 
78
  mask = counts > 0
79
- grid[mask] /= counts[mask] # average OSM match score
80
  grid_values.append((grid, tile_xmin, tile_ymin, n_rows, n_cols))
81
 
82
- # Flatten all grid values for global min/max
83
- all_scores = np.concatenate([g[0].flatten() for g in grid_values])
84
- min_val, max_val = all_scores.min(), all_scores.max()
85
- if min_val == max_val:
86
- max_val = min_val + 1e-6
87
-
88
- cmap = cm.get_cmap('Reds')
89
-
90
- # Create a linear colormap for legend
91
- colormap = linear.Reds_09.scale(min_val, max_val)
92
- colormap.caption = 'Average OSM Match Score'
93
- colormap.add_to(m)
94
-
95
- # Draw grid cells
96
- for grid, tile_xmin, tile_ymin, n_rows, n_cols in grid_values:
97
- for r in range(n_rows):
98
- for c in range(n_cols):
99
- val = grid[r, c]
100
- if val <= 0:
101
- continue
102
- norm_val = (val - min_val) / (max_val - min_val)
103
- color = colors.to_hex(cmap(norm_val))
104
- x0 = tile_xmin + c * CELL_SIZE_M
105
- y0 = tile_ymin + r * CELL_SIZE_M
106
- x1 = x0 + CELL_SIZE_M
107
- y1 = y0 + CELL_SIZE_M
108
- lon0, lat0 = transformer.transform(x0, y0)
109
- lon1, lat1 = transformer.transform(x1, y1)
110
- folium.Rectangle(
111
- bounds=[[lat0, lon0], [lat1, lon1]],
112
- color=None, # no border
113
- weight=0,
114
- fill=True,
115
- fill_color=color,
116
- fill_opacity=0.7,
117
- popup=f"{val:.2f}" # only the value
118
- ).add_to(m)
119
 
120
  return m._repr_html_()
121
 
 
122
  def get_map_widgets(city_component):
123
  map_output = gr.HTML(value="Map will appear here once you type a city", elem_id="map-widget")
124
  show_grid = gr.Checkbox(label="Draw Grid", value=False)
 
8
  from matplotlib import cm, colors
9
  import pandas as pd
10
  import pyproj
11
+ import matplotlib.pyplot as plt
12
  from config import OUTPUT_DIR
13
  from branca.colormap import linear
14
 
15
  CELL_SIZE_M = 100 # meters
16
 
17
+
18
+ def export_georeferenced_png(raster_path, png_path):
19
+ """
20
+ Export the raster to a georeferenced PNG
21
+ that aligns with Folium ImageOverlay.
22
+ """
23
+ with rasterio.open(raster_path) as src:
24
+ # Read all bands (or just 1 if grayscale)
25
+ arr = src.read()
26
+
27
+ # Handle RGB or single-band case
28
+ if arr.shape[0] >= 3:
29
+ img = arr[:3].transpose(1, 2, 0) # (H, W, RGB)
30
+ else:
31
+ img = arr[0]
32
+
33
+ bounds = src.bounds
34
+
35
+ plt.imshow(img, extent=[bounds.left, bounds.right, bounds.bottom, bounds.top])
36
+ plt.axis("off")
37
+ plt.savefig(png_path, bbox_inches="tight", pad_inches=0, transparent=True)
38
+ plt.close()
39
+
40
+
41
  def make_map(city, show_grid, show_georef):
42
  city = city.strip()
43
  if not city:
 
54
  if not os.path.exists(raster_path):
55
  return "Georeferenced raster not found"
56
 
 
57
  with rasterio.open(raster_path) as src:
58
  bounds = src.bounds
59
  crs = src.crs
60
 
61
  xmin, ymin, xmax, ymax = bounds
62
+ transformer = pyproj.Transformer.from_crs(crs, "EPSG:4326", always_xy=True)
63
+
64
+ # Convert raster bounds to lat/lon
65
+ lon0, lat0 = transformer.transform(xmin, ymin)
66
+ lon1, lat1 = transformer.transform(xmax, ymax)
67
+
68
+ # Enforce correct ordering for Folium
69
+ lat_min, lat_max = sorted([lat0, lat1])
70
+ lon_min, lon_max = sorted([lon0, lon1])
71
 
72
  # Show georeferenced raster if requested
73
  if show_georef:
74
  raster_img_path = os.path.join(OUTPUT_DIR, "georeferenced_rgba.png")
75
+ if not os.path.exists(raster_img_path):
76
+ export_georeferenced_png(raster_path, raster_img_path)
77
+
78
+ ImageOverlay(
79
+ image=raster_img_path,
80
+ bounds=[[lat_min, lon_min], [lat_max, lon_max]],
81
+ opacity=0.7,
82
+ interactive=True,
83
+ ).add_to(m)
84
+
85
+ # Debug markers (optional, helps see alignment)
86
+ folium.Marker([loc.latitude, loc.longitude], tooltip="City center").add_to(m)
87
+ cx, cy = (xmin + xmax) / 2, (ymin + ymax) / 2
88
+ clon, clat = transformer.transform(cx, cy)
89
+ folium.Marker([clat, clon], tooltip="Raster center").add_to(m)
90
 
91
  # Grid overlay
92
  if show_grid:
 
97
  if df.empty:
98
  continue
99
 
 
100
  tile_xmin, tile_xmax = df['x'].min(), df['x'].max()
101
  tile_ymin, tile_ymax = df['y'].min(), df['y'].max()
102
  n_cols = int(np.ceil((tile_xmax - tile_xmin) / CELL_SIZE_M))
 
113
  counts[row_idx, col] += 1
114
 
115
  mask = counts > 0
116
+ grid[mask] /= counts[mask]
117
  grid_values.append((grid, tile_xmin, tile_ymin, n_rows, n_cols))
118
 
119
+ if grid_values:
120
+ all_scores = np.concatenate([g[0].flatten() for g in grid_values])
121
+ min_val, max_val = all_scores.min(), all_scores.max()
122
+ if min_val == max_val:
123
+ max_val = min_val + 1e-6
124
+
125
+ cmap = cm.get_cmap("Reds")
126
+ colormap = linear.Reds_09.scale(min_val, max_val)
127
+ colormap.caption = "Average OSM Match Score"
128
+ colormap.add_to(m)
129
+
130
+ for grid, tile_xmin, tile_ymin, n_rows, n_cols in grid_values:
131
+ for r in range(n_rows):
132
+ for c in range(n_cols):
133
+ val = grid[r, c]
134
+ if val <= 0:
135
+ continue
136
+ norm_val = (val - min_val) / (max_val - min_val)
137
+ color = colors.to_hex(cmap(norm_val))
138
+ x0 = tile_xmin + c * CELL_SIZE_M
139
+ y0 = tile_ymin + r * CELL_SIZE_M
140
+ x1 = x0 + CELL_SIZE_M
141
+ y1 = y0 + CELL_SIZE_M
142
+ lon0, lat0 = transformer.transform(x0, y0)
143
+ lon1, lat1 = transformer.transform(x1, y1)
144
+ lat_min, lat_max = sorted([lat0, lat1])
145
+ lon_min, lon_max = sorted([lon0, lon1])
146
+ folium.Rectangle(
147
+ bounds=[[lat_min, lon_min], [lat_max, lon_max]],
148
+ color=None,
149
+ weight=0,
150
+ fill=True,
151
+ fill_color=color,
152
+ fill_opacity=0.7,
153
+ popup=f"{val:.2f}",
154
+ ).add_to(m)
 
155
 
156
  return m._repr_html_()
157
 
158
+
159
  def get_map_widgets(city_component):
160
  map_output = gr.HTML(value="Map will appear here once you type a city", elem_id="map-widget")
161
  show_grid = gr.Checkbox(label="Draw Grid", value=False)