Skip to content
Snippets Groups Projects
Commit 5c4bf644 authored by Raphael Sturgis's avatar Raphael Sturgis
Browse files

Merge branch '27-add-link-interpolation' into 'develop'

Resolve "Add link interpolation"

Closes #27

See merge request !22
parents cf60707b 1a1c63d9
Branches
No related tags found
2 merge requests!22Resolve "Add link interpolation",!13Draft: Develop
This commit is part of merge request !13. Comments created here will be created in the context of that merge request.
import numbers import numbers
import random import random
from copy import copy
import pandas as pd import pandas as pd
import numpy as np import numpy as np
...@@ -8,7 +9,7 @@ from scipy.interpolate import interp1d ...@@ -8,7 +9,7 @@ from scipy.interpolate import interp1d
from skais.utils.geography import great_circle, position_from_distance, get_coord from skais.utils.geography import great_circle, position_from_distance, get_coord
from skais.ais.ais_points import AISPoints from skais.ais.ais_points import AISPoints
from skais.utils.geometry import bresenham from skais.utils.geometry import bresenham, dist_on_grid
@jit(nopython=True) @jit(nopython=True)
...@@ -130,22 +131,9 @@ def generate_points(data, positions, height, width, node_size, lower_lat, upper_ ...@@ -130,22 +131,9 @@ def generate_points(data, positions, height, width, node_size, lower_lat, upper_
data[x, y] = [1] data[x, y] = [1]
@jit(nopython=True)
def generate_links(data, positions, height, width, lower_lat, upper_lat, lower_lon, upper_lon):
lon, lat = positions[0, 0], positions[0, 1]
for longitude, latitude in positions[1:]:
x_prv, y_prev = get_coord(lat, lon, height, width, lower_lat, upper_lat, lower_lon, upper_lon)
x_nxt, y_nxt = get_coord(latitude, longitude, height, width, lower_lat, upper_lat, lower_lon,
upper_lon)
lon, lat = longitude, latitude
for x, y in bresenham(x_prv, y_prev, x_nxt, y_nxt):
data[x, y] = [1]
@jit(nopython=True) @jit(nopython=True)
def generate_points_with_features(data, positions, features_vectors, bounds, node_size, height, width, def generate_points_with_features(data, positions, features_vectors, bounds, node_size, height, width,
lower_lat, upper_lat, lower_lon, upper_lon, link): lower_lat, upper_lat, lower_lon, upper_lon):
for pos, f in zip(positions, features_vectors): for pos, f in zip(positions, features_vectors):
latitude = pos[1] latitude = pos[1]
longitude = pos[0] longitude = pos[0]
...@@ -162,21 +150,46 @@ def generate_points_with_features(data, positions, features_vectors, bounds, nod ...@@ -162,21 +150,46 @@ def generate_points_with_features(data, positions, features_vectors, bounds, nod
for y in range(y_lower_bound, y_upper_bound + 1): for y in range(y_lower_bound, y_upper_bound + 1):
for i, v in enumerate(value): for i, v in enumerate(value):
data[x, y, i] = v data[x, y, i] = v
if link:
@jit(nopython=True)
def generate_links(data, positions, height, width, lower_lat, upper_lat, lower_lon, upper_lon, values, interpolate=None):
lon, lat = positions[0, 0], positions[0, 1] lon, lat = positions[0, 0], positions[0, 1]
value = __get_image_value__(features_vectors[0], bounds) current_value = values[0]
for pos, f in zip(positions[1:], features_vectors[1:]): for pos, nxt_value in zip(positions[1:], values[1:]):
latitude = pos[1] latitude = pos[1]
longitude = pos[0] longitude = pos[0]
x_prv, y_prev = get_coord(lat, lon, height, width, lower_lat, upper_lat, lower_lon, upper_lon) x_prv, y_prev = get_coord(lat, lon, height, width, lower_lat, upper_lat, lower_lon, upper_lon)
x_nxt, y_nxt = get_coord(latitude, longitude, height, width, lower_lat, upper_lat, lower_lon, x_nxt, y_nxt = get_coord(latitude, longitude, height, width, lower_lat, upper_lat, lower_lon,
upper_lon) upper_lon)
lon, lat = longitude, latitude lon, lat = longitude, latitude
if interpolate is not None and nxt_value != current_value:
dist = dist_on_grid(x_prv, y_prev, x_nxt, y_nxt)
for x, y in bresenham(x_prv, y_prev, x_nxt, y_nxt): for x, y in bresenham(x_prv, y_prev, x_nxt, y_nxt):
for i, v in enumerate(value): dist_prev = dist_on_grid(x_prv, y_prev, x, y)
data[x, y, i] = v dist_next = dist_on_grid(x, y, x_nxt, y_nxt)
value = __get_image_value__(f, bounds)
pixel_color = current_value * (1-dist_prev/dist) + nxt_value * (1-dist_next/dist)
for i in range(len(pixel_color)):
data[x, y, i] = pixel_color[i]
else:
for x, y in bresenham(x_prv, y_prev, x_nxt, y_nxt):
for i in range(len(current_value)):
data[x, y, i] = current_value[i]
current_value = nxt_value
@jit(nopython=True)
def generate_values(features_vectors, bounds):
result = np.zeros(features_vectors.shape)
for i in range(len(features_vectors)):
features = features_vectors[i]
value = __get_image_value__(features, bounds)
for j in range(len(value)):
v = value[j]
result[i, j] = v
return result
class AISTrajectory(AISPoints): class AISTrajectory(AISPoints):
...@@ -346,7 +359,7 @@ class AISTrajectory(AISPoints): ...@@ -346,7 +359,7 @@ class AISTrajectory(AISPoints):
return result return result
def generate_array_from_positions(self, height=256, width=256, link=True, bounding_box='fit', ref_index=-1, def generate_array_from_positions(self, height=256, width=256, link=True, bounding_box='fit', ref_index=-1,
features=None, node_size=0): features=None, node_size=0, interpolation=None):
positions = self.df[['longitude', 'latitude']].to_numpy() positions = self.df[['longitude', 'latitude']].to_numpy()
...@@ -371,18 +384,23 @@ class AISTrajectory(AISPoints): ...@@ -371,18 +384,23 @@ class AISTrajectory(AISPoints):
if features_vectors is not None: if features_vectors is not None:
nb_channels = len(features_vectors.T) nb_channels = len(features_vectors.T)
bounds = np.array(bounds)
else: else:
nb_channels = 1 nb_channels = 1
data = np.zeros((height, width, nb_channels), dtype=np.float) data = np.zeros((height, width, nb_channels), dtype=float)
if features_vectors is None: if features_vectors is None:
generate_points(data, positions, height, width, node_size, lower_lat, upper_lat, lower_lon, upper_lon) generate_points(data, positions, height, width, node_size, lower_lat, upper_lat, lower_lon, upper_lon)
if link: if link:
generate_links(data, positions, height, width, lower_lat, upper_lat, lower_lon, upper_lon) generate_links(data, positions, height, width, lower_lat, upper_lat, lower_lon, upper_lon,
np.ones((len(positions), 1)))
else: else:
generate_points_with_features(data, positions, features_vectors, np.array(bounds), node_size, height, width, generate_points_with_features(data, positions, features_vectors, np.array(bounds), node_size, height, width,
lower_lat, upper_lat, lower_lon, upper_lon, link) lower_lat, upper_lat, lower_lon, upper_lon, )
if link:
generate_links(data, positions, height, width, lower_lat, upper_lat, lower_lon, upper_lon,
generate_values(features_vectors, bounds), interpolation)
return data return data
...@@ -652,3 +652,31 @@ class TestAISTrajectoryImageGeneration(unittest.TestCase): ...@@ -652,3 +652,31 @@ class TestAISTrajectoryImageGeneration(unittest.TestCase):
[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0.25, 0.5], [0.5, 0.25]]]) [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0.25, 0.5], [0.5, 0.25]]])
np.testing.assert_array_equal(result, expected) np.testing.assert_array_equal(result, expected)
def test_generate_array_interpolate_links(self):
trajectory = AISTrajectory(
pd.DataFrame(
{
"latitude": [0, 10, 0, 20],
"longitude": [0, 10, 20, 20],
"ts_sec": [i for i in range(4)],
"sog": [10, 10, 20, 40]
}
)
)
result = trajectory.generate_array_from_positions(height=9, width=18, link=True, bounding_box='fit',
features={"sog": (0, 80)}, node_size=0,
interpolation='linear').reshape((9, 18))
print(result)
expected = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.46875],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.4375],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.40625],
[0, 0, 0, 0, 0, 0, 0, 0.125, 0.125, 0.13526987, 0, 0, 0, 0, 0, 0, 0, 0.375],
[0, 0, 0, 0, 0, 0.125, 0.125, 0, 0, 0, 0.15330406, 0.16458619, 0, 0, 0, 0, 0, 0.34375],
[0, 0, 0, 0.125, 0.125, 0, 0, 0, 0, 0, 0, 0, 0.18154526, 0.19313327, 0, 0, 0, 0.3125],
[0, 0.125, 0.125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.20959047, 0.22158235, 0, 0.28125],
[0.125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.23609719, 0.25]])
np.testing.assert_array_almost_equal(result, expected)
import numpy as np
from numba import jit from numba import jit
@jit(nopython=True)
def dist_on_grid(x1, y1, x2, y2):
dx = int(x2 - x1)
dy = int(y2 - y1)
return np.sqrt(dx ** 2 + dy ** 2)
@jit(nopython=True) @jit(nopython=True)
def bresenham(x1, y1, x2, y2): def bresenham(x1, y1, x2, y2):
...@@ -12,7 +19,6 @@ def bresenham(x1, y1, x2, y2): ...@@ -12,7 +19,6 @@ def bresenham(x1, y1, x2, y2):
if dy < 0: if dy < 0:
sy = -1 sy = -1
pixels = [] pixels = []
if abs(dx) > abs(dy): # slope < 1 if abs(dx) > abs(dy): # slope < 1
if x1 > x2: if x1 > x2:
...@@ -59,4 +65,3 @@ def bresenham(x1, y1, x2, y2): ...@@ -59,4 +65,3 @@ def bresenham(x1, y1, x2, y2):
pixels.append((x, y)) pixels.append((x, y))
return pixels return pixels
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment