Skip to content

Commit

Permalink
Merge pull request #5 from prime-slam/google-images-crop
Browse files Browse the repository at this point in the history
Crop for satellite images
  • Loading branch information
vnmsklnk authored Nov 22, 2023
2 parents 6ad527c + 053886d commit a26e22c
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 47 deletions.
22 changes: 11 additions & 11 deletions aero_vloc/geo_referencers/google_maps_referencer.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import cv2
import math

from typing import Tuple

from aero_vloc.geo_referencers.geo_referencer import GeoReferencer
from aero_vloc.primitives import MapTile
from aero_vloc.utils import get_new_size


class GoogleMapsReferencer(GeoReferencer):
def __init__(self, zoom):
self.zoom = zoom

# Magic constants
self.map_width = 256
self.map_height = 256
self.map_size = 256
self.img_size = 640
self.scale = math.pow(2, self.zoom) / (self.img_size / self.map_size)

def __lat_lon_to_world(self, lat, lon):
x = (lon + 180) * (self.map_width / 360)
x = (lon + 180) * (self.map_size / 360)
y = (
(
1
Expand All @@ -25,14 +28,14 @@ def __lat_lon_to_world(self, lat, lon):
/ math.pi
)
/ 2
) * self.map_height
) * self.map_size

return x, y

def __world_to_lat_lon(self, x, y):
lon = x / self.map_width * 360 - 180
lon = x / self.map_size * 360 - 180

n = math.pi - 2 * math.pi * y / self.map_height
n = math.pi - 2 * math.pi * y / self.map_size
lat = 180 / math.pi * math.atan(0.5 * (math.exp(n) - math.exp(-n)))

return lat, lon
Expand All @@ -44,11 +47,8 @@ def get_lat_lon(
map_tile.top_left_lat, map_tile.top_left_lon
)

x_scale = math.pow(2, self.zoom) / (resize / self.map_width)
y_scale = math.pow(2, self.zoom) / (resize / self.map_width)

desired_x = top_left_x + (self.map_width * abs(pixel[0]) / resize) / x_scale
desired_y = top_left_y + (self.map_height * abs(pixel[1]) / resize) / y_scale
desired_x = top_left_x + (self.map_size * abs(pixel[0]) / resize) / self.scale
desired_y = top_left_y + (self.map_size * abs(pixel[1]) / resize) / self.scale

lat, lon = self.__world_to_lat_lon(desired_x, desired_y)
return lat, lon
10 changes: 8 additions & 2 deletions aero_vloc/geo_referencers/linear_referencer.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import cv2

from typing import Tuple

from aero_vloc.geo_referencers.geo_referencer import GeoReferencer
from aero_vloc.primitives import MapTile
from aero_vloc.utils import get_new_size


class LinearReferencer(GeoReferencer):
def get_lat_lon(
self, map_tile: MapTile, pixel: Tuple[int, int], resize: int
) -> Tuple[float, float]:
lat = map_tile.top_left_lat + (abs(pixel[1]) / resize) * (
map_image = cv2.imread(str(map_tile.path))
h_new, w_new = get_new_size(*map_image.shape[:2], resize)

lat = map_tile.top_left_lat + (abs(pixel[1]) / h_new) * (
map_tile.bottom_right_lat - map_tile.top_left_lat
)
lon = map_tile.top_left_lon + (abs(pixel[0]) / resize) * (
lon = map_tile.top_left_lon + (abs(pixel[0]) / w_new) * (
map_tile.bottom_right_lon - map_tile.top_left_lon
)
return lat, lon
4 changes: 1 addition & 3 deletions aero_vloc/homography_estimator/homography_estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

from typing import Optional, Tuple

from aero_vloc.primitives import MapTile, UAVImage
from aero_vloc.primitives import UAVImage
from aero_vloc.utils import get_new_size


Expand All @@ -26,7 +26,6 @@ def __call__(
matched_kpts_query: list,
matched_kpts_reference: list,
query_image: UAVImage,
sat_image: MapTile,
resize_param: int,
) -> Optional[Tuple[int, int]]:
"""
Expand All @@ -39,7 +38,6 @@ def __call__(
:param matched_kpts_query: Keypoints of the query image
:param matched_kpts_reference: Keypoints of the satellite image
:param query_image: UAV image
:param sat_image: Satellite map tile
:param resize_param: The image resize parameter that was used in keypoint matching
:return: Pixel coordinates of the center of query image. None if the location cannot be determined
"""
Expand Down
1 change: 0 additions & 1 deletion aero_vloc/localization_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ def __call__(
matched_kpts_query,
matched_kpts_reference,
query_image,
chosen_sat_image,
self.retrieval_system.feature_matcher.resize,
)
if estimator_result is None:
Expand Down
51 changes: 31 additions & 20 deletions aero_vloc/map_downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import cv2
import math
import requests

Expand Down Expand Up @@ -54,19 +55,20 @@ def __init__(
self.folder_to_save = folder_to_save

# Maximum allowed shape and scale
self.img_height = 640
self.img_width = 640
self.scale = 2
self.img_size = 640
self.img_scale = 2
self.map_type = "satellite"

# The number of pixels from the bottom to be cropped to remove the watermark
self.bottom_crop = 50
self.crop_scale = self.bottom_crop / (self.img_size * self.img_scale)

# Magic constants
self.map_height = 256
self.map_width = 256
self.x_scale = math.pow(2, zoom) / (self.img_width / self.map_width)
self.y_scale = math.pow(2, zoom) / (self.img_height / self.map_width)
self.map_size = 256
self.map_scale = math.pow(2, zoom) / (self.img_size / self.map_size)

def __lat_lon_to_point(self, lat, lon):
x = (lon + 180) * (self.map_width / 360)
x = (lon + 180) * (self.map_size / 360)
y = (
(
1
Expand All @@ -76,37 +78,42 @@ def __lat_lon_to_point(self, lat, lon):
/ math.pi
)
/ 2
) * self.map_height
) * self.map_size

return x, y

def __point_to_lat_lon(self, x, y):
lon = x / self.map_width * 360 - 180
lon = x / self.map_size * 360 - 180

n = math.pi - 2 * math.pi * y / self.map_height
n = math.pi - 2 * math.pi * y / self.map_size
lat = 180 / math.pi * math.atan(0.5 * (math.exp(n) - math.exp(-n)))

return lat, lon

def __get_image_bounds(self, lat, lon):
centre_x, centre_y = self.__lat_lon_to_point(lat, lon)

south_east_x = centre_x + (self.map_width / 2) / self.x_scale
south_east_y = centre_y + (self.map_height / 2) / self.y_scale
south_east_x = centre_x + (self.map_size / 2) / self.map_scale
south_east_y = (
centre_y
+ (self.map_size / 2 - self.map_size * self.crop_scale) / self.map_scale
)
bottom_right_lat, bottom_right_lon = self.__point_to_lat_lon(
south_east_x, south_east_y
)

north_west_x = centre_x - (self.map_width / 2) / self.x_scale
north_east_y = centre_y - (self.map_height / 2) / self.y_scale
north_west_x = centre_x - (self.map_size / 2) / self.map_scale
north_east_y = centre_y - (self.map_size / 2) / self.map_scale
top_left_lat, top_left_lon = self.__point_to_lat_lon(north_west_x, north_east_y)

return top_left_lat, top_left_lon, bottom_right_lat, bottom_right_lon

def __get_lat_step(self, lat, lon):
point_x, point_y = self.__lat_lon_to_point(lat, lon)

stepped_point_y = point_y - (self.map_height / self.y_scale)
stepped_point_y = point_y - (
(self.map_size - self.map_size * self.crop_scale) / self.map_scale
)
new_lat, _ = self.__point_to_lat_lon(point_x, stepped_point_y)

lat_step = lat - new_lat
Expand All @@ -121,15 +128,15 @@ def __request_image(self, lat, lon):
+ "&zoom="
+ str(self.zoom)
+ "&size="
+ str(self.img_width)
+ str(self.img_size)
+ "x"
+ str(self.img_height)
+ str(self.img_size)
+ "&key="
+ self.api_key
+ "&maptype="
+ self.map_type
+ "&scale="
+ str(self.scale)
+ str(self.img_scale)
)
return requests.get(url).content

Expand All @@ -151,8 +158,12 @@ def download_map(self):
while lon <= self.south_east_lon:
image = self.__request_image(lat, lon)
filename = f"{str(index).zfill(4)}.png"
with open(self.folder_to_save / filename, "wb") as image_file:
path_to_image = str(self.folder_to_save / filename)
with open(path_to_image, "wb") as image_file:
image_file.write(image)
image = cv2.imread(path_to_image)
image = image[: -self.bottom_crop]
cv2.imwrite(path_to_image, image)
(
top_left_lat,
top_left_lon,
Expand Down
21 changes: 11 additions & 10 deletions aero_vloc/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,23 @@ def load_image_for_sp(image_path: Path, resize: int):


def visualize_matches(
matched_kpts_query, matched_kpts_reference, sat_image, drone_img, resize
matched_kpts_query, matched_kpts_reference, sat_image, drone_image, resize
):
drone_img = cv2.imread(str(drone_img.path))
h_new, w_new = get_new_size(*drone_img.shape[:2], resize)
drone_img = cv2.resize(drone_img, (w_new, h_new))
sat_img = cv2.resize(
cv2.imread(str(sat_image.path)),
(resize, resize),
)
drone_image = cv2.imread(str(drone_image.path))
h_new, w_new = get_new_size(*drone_image.shape[:2], resize)
drone_image = cv2.resize(drone_image, (w_new, h_new))

sat_image = cv2.imread(str(sat_image.path))
h_new, w_new = get_new_size(*sat_image.shape[:2], resize)
sat_image = cv2.resize(sat_image, (w_new, h_new))

matches = [cv2.DMatch(i, i, 1) for i in range(len(matched_kpts_query))]
matched_kpts_query = [cv2.KeyPoint(x, y, 1) for x, y in matched_kpts_query]
matched_kpts_reference = [cv2.KeyPoint(x, y, 1) for x, y in matched_kpts_reference]
img = cv2.drawMatches(
drone_img,
drone_image,
matched_kpts_query,
sat_img,
sat_image,
matched_kpts_reference,
matches,
None,
Expand Down

0 comments on commit a26e22c

Please sign in to comment.