dilithjay commited on
Commit
760889f
·
1 Parent(s): 5a1ff44

Add dependencies

Browse files
Files changed (4) hide show
  1. app.py +1 -5
  2. geo_tools.py +105 -0
  3. grid_optim.py +113 -0
  4. requirements.txt +2 -0
app.py CHANGED
@@ -1,12 +1,8 @@
1
- import json
2
  import os
3
  import gradio as gr
4
  import plotly.graph_objects as go
5
 
6
- import sys
7
-
8
- sys.path.append(os.path.join(os.path.dirname(__file__), "..", "SatSeg"))
9
- from satseg.geo_tools import (
10
  shapefile_to_latlong,
11
  shapefile_to_grid_indices,
12
  points_to_shapefile,
 
 
1
  import os
2
  import gradio as gr
3
  import plotly.graph_objects as go
4
 
5
+ from geo_tools import (
 
 
 
6
  shapefile_to_latlong,
7
  shapefile_to_grid_indices,
8
  points_to_shapefile,
geo_tools.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import fiona
3
+ from pyproj import Transformer
4
+
5
+ import numpy as np
6
+ from tqdm import tqdm
7
+
8
+ from grid_optim import get_optimal_grid
9
+
10
+
11
+ def shapefile_to_latlong(file_path: str):
12
+ c = fiona.open(file_path)
13
+ contours = []
14
+
15
+ transformer = Transformer.from_crs(c.crs, 4326, always_xy=True)
16
+
17
+ for poly in c:
18
+ coords = poly["geometry"].coordinates
19
+ for coord_set in coords:
20
+ contours.append(
21
+ np.array(
22
+ list(
23
+ transformer.itransform(
24
+ coord_set[0] if len(coord_set) == 1 else coord_set
25
+ )
26
+ )
27
+ )
28
+ )
29
+
30
+ return contours
31
+
32
+
33
+ def shapefile_to_grid_indices(
34
+ file_path: str, side_len_m: float = 100, meters_per_px: float = 10
35
+ ):
36
+ c = fiona.open(file_path, "r")
37
+ all_indices = []
38
+ side_len = side_len_m / meters_per_px
39
+
40
+ for poly in c:
41
+ coords = poly["geometry"].coordinates
42
+ for coord_set in tqdm(coords):
43
+ contour = np.array(coord_set[0] if len(coord_set) == 1 else coord_set)
44
+
45
+ cmin = contour.min(axis=0)
46
+ contour -= cmin
47
+ cmax = int(contour.max() / meters_per_px)
48
+ contour = contour // meters_per_px
49
+
50
+ if cmax < side_len:
51
+ continue
52
+
53
+ mask = np.zeros((cmax, cmax), dtype="uint8")
54
+ mask = cv2.drawContours(
55
+ mask,
56
+ [contour.reshape((-1, 1, 2)).astype(np.int32)],
57
+ -1,
58
+ (255),
59
+ thickness=cv2.FILLED,
60
+ )
61
+
62
+ indices = np.array(get_optimal_grid(mask, side_len=side_len)[0])
63
+ indices = indices * meters_per_px + cmin
64
+
65
+ all_indices += indices.tolist()
66
+
67
+ transformer = Transformer.from_crs(c.crs, 4326, always_xy=True)
68
+ all_indices = list(transformer.itransform(all_indices))
69
+
70
+ return np.array(all_indices)
71
+
72
+
73
+ def points_to_shapefile(points: np.ndarray, file_path: str):
74
+ schema = {"geometry": "Point", "properties": [("ID", "int")]}
75
+
76
+ # open a fiona object
77
+ pointShp = fiona.open(
78
+ file_path,
79
+ mode="w",
80
+ driver="ESRI Shapefile",
81
+ schema=schema,
82
+ crs="EPSG:4326",
83
+ )
84
+ # iterate over each row in the dataframe and save record
85
+ for i, (x, y) in enumerate(points):
86
+ rowDict = {
87
+ "geometry": {"type": "Point", "coordinates": (x, y)},
88
+ "properties": {"ID": i},
89
+ }
90
+ pointShp.write(rowDict)
91
+ # close fiona object
92
+ pointShp.close()
93
+
94
+
95
+ def get_cached_grid_indices(file_path: str):
96
+ c = fiona.open(file_path, "r")
97
+ all_indices = []
98
+ all_labels = []
99
+
100
+ for poly in c:
101
+ all_indices.append(poly["geometry"].coordinates)
102
+ if "Name" in poly["properties"]:
103
+ all_labels.append(poly["properties"]["Name"])
104
+
105
+ return np.array(all_indices), all_labels
grid_optim.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import math
3
+ from tqdm import tqdm
4
+
5
+
6
+ def meters_to_latitude(m_dist: float):
7
+ return 0.00001 / 1.11 * m_dist
8
+
9
+
10
+ def degrees_to_radians(angle_deg: float):
11
+ return angle_deg / 180 * math.pi
12
+
13
+
14
+ def radians_to_degrees(angle_deg: float):
15
+ return angle_deg / math.pi * 180
16
+
17
+
18
+ def plot_line(offset: tuple, start: tuple, indices: list, size: tuple):
19
+ while (start[0] < 0 or start[1] < 0) and (
20
+ start[0] < size[0] and start[1] < size[1]
21
+ ):
22
+ start = (round(start[0] + offset[0]), round(start[1] + offset[1]))
23
+ cur_h = start
24
+
25
+ while cur_h[0] < size[0] and cur_h[1] < size[1]:
26
+ indices.append(cur_h)
27
+ cur_h = (round(cur_h[0] + offset[0]), round(cur_h[1] + offset[1]))
28
+ return start
29
+
30
+
31
+ def get_grid_score(
32
+ angle: float, side_len: float, seg_result: np.ndarray, threshold: float = 0.5
33
+ ):
34
+ h, w = seg_result.shape
35
+
36
+ offset = (int(side_len * math.sin(angle)), int(side_len * math.cos(angle)))
37
+ s_offset_1 = (
38
+ int(side_len * math.sin(math.pi / 3 + angle)),
39
+ int(side_len * math.cos(math.pi / 3 + angle)),
40
+ )
41
+ s_offset_2 = (
42
+ int(side_len * math.sin(math.pi / 3 - angle)),
43
+ -int(side_len * math.cos(math.pi / 3 - angle)),
44
+ )
45
+
46
+ cur = (0, 0)
47
+ i = 0
48
+ indices = []
49
+
50
+ # Lower triangle
51
+ while cur[0] < h and cur[1] < w:
52
+ cur = plot_line(offset, cur, indices, (h, w))
53
+ s_offset = s_offset_1 if i % 2 else s_offset_2
54
+ cur = (round(cur[0] + s_offset[0]), round(cur[1] + s_offset[1]))
55
+ i += 1
56
+
57
+ # Upper triangle
58
+ cur = (0, 0)
59
+ for j in range(i + 3):
60
+ cur = plot_line(offset, cur, indices, (h, w))
61
+ s_offset = s_offset_1 if j % 2 else s_offset_2
62
+ cur = (round(cur[0] - s_offset[0]), round(cur[1] - s_offset[1]))
63
+ j += 1
64
+
65
+ indices = np.array(indices)
66
+ seg_result = (seg_result > threshold) * seg_result
67
+
68
+ max_score = 0
69
+ best_start = tuple()
70
+ best_indices = None
71
+ for s_1 in np.arange(0, side_len, side_len // 5):
72
+ for s_2 in np.arange(0, side_len, side_len // 5):
73
+ indices_new = indices + np.array([s_1, s_2])
74
+ indices_new = indices_new[
75
+ np.logical_and(indices_new[:, 0] < h, indices_new[:, 1] < w)
76
+ ].astype(int)
77
+
78
+ result = np.zeros((h, w))
79
+ result[indices_new[:, 0], indices_new[:, 1]] = seg_result[
80
+ indices_new[:, 0], indices_new[:, 1]
81
+ ]
82
+
83
+ score = result.sum()
84
+ if score > max_score:
85
+ max_score = score
86
+ best_start = (s_1, s_2)
87
+ x, y = np.where(result > threshold)
88
+ best_indices = np.array([x, y]).T
89
+
90
+ # plt.imshow(grid)
91
+ # plt.show()
92
+ # plt.imshow(result)
93
+ # plt.show()
94
+ return max_score, best_start, np.array([best_indices[:, 1], best_indices[:, 0]]).T
95
+
96
+
97
+ def get_optimal_grid(mask: np.ndarray, side_len: float, display_progress: bool = False):
98
+ angle_range = (0, degrees_to_radians(60))
99
+ angle_res = degrees_to_radians(10)
100
+
101
+ max_score = 0
102
+ max_config = tuple()
103
+ best_indices = None
104
+ for angle in tqdm(
105
+ np.arange(angle_range[0], angle_range[1], angle_res), disable=True
106
+ ):
107
+ score, start, indices = get_grid_score(angle, side_len, mask, 0.8)
108
+ if score > max_score:
109
+ max_score = score
110
+ max_config = (angle, side_len, start)
111
+ best_indices = indices
112
+
113
+ return best_indices, max_config
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ plotly==5.13.1
2
+ pyproj==3.5.0