Skip to content

Commit

Permalink
Merge pull request #2 from daniel-jakob/feature/lat-long-mapping
Browse files Browse the repository at this point in the history
Add functionality for the longitude and latitude mapping between the x- and y-coordinates of the centres of the hole cutouts and their real-life corresponding geographic coordinates. The new two_dim_interp module has options for visualisations if/when needed.
  • Loading branch information
daniel-jakob authored Dec 22, 2023
2 parents 1b14453 + 92c93a7 commit 04f15d2
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 10 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Python application

on:
push:
branches: [ "**" ]
pull_request:
branches: [ "**" ]

permissions:
contents: read

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest
8 changes: 8 additions & 0 deletions germany_beer_map/data/mapping/mapping.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
x_coordinate,y_coordinate,latitude,longitude
1398, -318, 54.39353009993681, 11.11644665583267
1870, -296, 54.437232366238604, 13.026542320542504
2300, -1782, 50.82158548797283, 14.766711498389775
1857, -3053, 47.463708419024705, 13.003253221506123
541, -3028, 47.536038222206784, 7.673516697684008
90, -1694, 51.051837116277255, 5.865762865196948
788, -102, 54.899500515516216, 8.635282242118539
117 changes: 117 additions & 0 deletions germany_beer_map/src/algorithms/two_dim_interp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import numpy as np
from scipy.interpolate import griddata
from scipy.spatial import ConvexHull
import matplotlib.pyplot as plt
import random

def two_dim_interp(centres_of_holes, plotting=False, ref_contour=None, mapping="germany_beer_map/data/mapping/mapping.csv"):

if plotting and ref_contour is None:
raise ValueError("centres_of_holes must be provided when plotting is True")

mapping = np.loadtxt(mapping, delimiter=',', skiprows=1)

centres_of_holes = np.array(centres_of_holes)
centres_of_holes_x = centres_of_holes[:, 0]
# Convert to signed int16 to avoid errors when negating y-values
centres_of_holes_y = centres_of_holes[:, 1].astype(np.int16)

print(centres_of_holes_x)
print(centres_of_holes_y)

distinctive_points_x = mapping[:, 0]
distinctive_points_y = mapping[:, 1]
distinctive_points_longitude = mapping[:, 3]
distinctive_points_latitude = mapping[:, 2]

circles_interp_longitude = griddata(
(distinctive_points_x, distinctive_points_y),
distinctive_points_longitude,
(centres_of_holes_x, -centres_of_holes_y),
method='cubic'
)

circles_interp_latitude = griddata(
(distinctive_points_x, distinctive_points_y),
distinctive_points_latitude,
(centres_of_holes_x, -centres_of_holes_y),
method='cubic'
)

print(circles_interp_latitude)

if plotting:
reference_contour_x = ref_contour[:, 0]
reference_contour_y = -ref_contour[:, 1]

hull = ConvexHull(np.column_stack((distinctive_points_x, distinctive_points_y)))


contour_interp_longitude = griddata(
(distinctive_points_x, distinctive_points_y),
distinctive_points_longitude,
(reference_contour_x, reference_contour_y),
method='cubic'
)

contour_interp_latitude = griddata(
(distinctive_points_x, distinctive_points_y),
distinctive_points_latitude,
(reference_contour_x, reference_contour_y),
method='cubic'
)

fig, axs = plt.subplots(1, 2, figsize=(20, 10))

axs[0].plot(reference_contour_x, reference_contour_y, 'b-', label='Contour')

for i, simplex in enumerate(hull.simplices):
if i == 0:
axs[0].plot(distinctive_points_x[simplex], distinctive_points_y[simplex], 'k-', label='Convex Hull')
else:
axs[0].plot(distinctive_points_x[simplex], distinctive_points_y[simplex], 'k-')

axs[0].set_xlabel('x-coordinate')
axs[0].set_ylabel('y-coordinate')
axs[0].legend()

axs[1].scatter(distinctive_points_longitude, distinctive_points_latitude, color='red', label='Distinctive Points')
for i in range(len(distinctive_points_longitude)):
axs[1].text(distinctive_points_longitude[i], distinctive_points_latitude[i], f'({distinctive_points_x[i]}, {distinctive_points_y[i]}, {i+1})', fontsize=8)
axs[1].plot(contour_interp_longitude, contour_interp_latitude, 'b-', label='Interpolated Contour')

for i in range(0, len(contour_interp_longitude), 50):
if not np.isnan(contour_interp_longitude[i]) and not np.isnan(contour_interp_latitude[i]):
rounded_contour_longitude = round(contour_interp_longitude[i], 3)
rounded_contour_latitude = round(contour_interp_latitude[i], 3)
axs[1].scatter(rounded_contour_longitude, rounded_contour_latitude, color='green')
axs[1].text(rounded_contour_longitude, rounded_contour_latitude, f'({rounded_contour_longitude}, {rounded_contour_latitude})', fontsize=8)

holes_hull = ConvexHull(np.column_stack((centres_of_holes_x, -centres_of_holes_y)))

axs[0].scatter(centres_of_holes_x, -centres_of_holes_y, color='purple', label='Centres of Holes')

for i in range(0, len(circles_interp_latitude)):
rounded_circles_longitude = round(circles_interp_longitude[i], 3)
rounded_circles_latitude = round(circles_interp_latitude[i], 3)
if i ==0:
axs[1].scatter(rounded_circles_longitude, rounded_circles_latitude, color='purple', label='Centres of Holes')
axs[1].text(rounded_circles_longitude, rounded_circles_latitude, f'({rounded_circles_longitude}, {rounded_circles_latitude})', fontsize=8)
else:
axs[1].scatter(rounded_circles_longitude, rounded_circles_latitude, color='purple')
axs[1].text(rounded_circles_longitude, rounded_circles_latitude, f'({rounded_circles_longitude}, {rounded_circles_latitude})', fontsize=8)

for i, simplex in enumerate(holes_hull.simplices):
if i == 0:
axs[0].plot(centres_of_holes_x[simplex], -centres_of_holes_y[simplex], 'g-', label='Convex Hull of Circle Centres')
else:
axs[0].plot(centres_of_holes_x[simplex], -centres_of_holes_y[simplex], 'g-')


axs[1].set_xlabel('Longitude')
axs[1].set_ylabel('Latitude')
axs[1].legend()

plt.show()

return circles_interp_longitude, circles_interp_latitude
17 changes: 11 additions & 6 deletions germany_beer_map/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from image_processing.map_outline_detection import detect_outline
from algorithms.scaling import *
from algorithms.tps_transform import *
from algorithms.two_dim_interp import *
from user_interface.draw_contours import *

# Create a single instance of ImageProcessor
Expand Down Expand Up @@ -39,20 +40,24 @@



rotation_angle = find_optimal_rotation(contour, ref_contour_scaled_aligned)
rotation_angle = find_optimal_rotation(ref_contour_scaled_aligned, contour)
# print(rotation_angle*180/3.16259)

ref_contour_scaled_aligned_rotated = rotate_contour_around_centroid(ref_contour_scaled_aligned, rotation_angle)
contour_rotated = rotate_contour_around_centroid(contour, -rotation_angle)

two_dim_interp(circles, True, ref_contour_scaled_aligned)

exit(0)

# draw_contours(ref_contour_scaled_aligned)

contour_grid_points = grid_gen(contour)
contour_refined_grid = adaptive_grid(contour_grid_points, contour)
ref_contour_grid_points = grid_gen(ref_contour_scaled_aligned_rotated)
ref_contour_refined_grid = adaptive_grid(ref_contour_grid_points, ref_contour_scaled_aligned_rotated)
tps_transform(contour_refined_grid, ref_contour_refined_grid, contour, ref_contour_scaled_aligned_rotated)
ref_contour_grid_points = grid_gen(contour_rotated)
ref_contour_refined_grid = adaptive_grid(ref_contour_grid_points, contour_rotated)
#tps_transform(contour_refined_grid, ref_contour_refined_grid, contour, contour_rotated)


draw_contours(ref_contour_scaled_aligned_rotated, ref_contour_scaled_aligned, contour)
draw_contours(contour_rotated, ref_contour_scaled_aligned, contour)


2 changes: 1 addition & 1 deletion germany_beer_map/src/user_interface/draw_contours.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import cv2
import numpy as np

def draw_contours(*contours, img_read='data/images/map.jpg'):
def draw_contours(*contours, img_read='germany_beer_map/data/images/map.jpg'):
# Read the image
img = cv2.imread(img_read, cv2.IMREAD_COLOR)

Expand Down
7 changes: 4 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
matplotlib==3.8.0
numpy==1.26.2
opencv==4.8.1
matplotlib
numpy
opencv-python
SciPy

0 comments on commit 04f15d2

Please sign in to comment.