Skip to content
Snippets Groups Projects
Commit 61b098c1 authored by Raphael's avatar Raphael
Browse files

data augmentation

parent 9487015c
No related branches found
No related tags found
1 merge request!13Draft: Develop
This commit is part of merge request !13. Comments created here will be created in the context of that merge request.
import random
from copy import deepcopy
import numpy as np
from skais.utils.geometry import vectorize_angle, local_ref, transpose_matrix, \
quaternion_multiply, angleize_vector, rotation_quaternions, spherical_to_carthesian, carthesian_to_spherical, \
rotate_vector_by_quaternion
base_ref = np.array(
[
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]
]
)
def shift_positions(aisPositions, axis_lat, axis_long, angle):
copy = deepcopy(aisPositions)
rotation_quaternion, inverse_rotation_quaternion = rotation_quaternions(axis_lat, axis_long, angle)
latitudes = np.radians(aisPositions.df['latitude'].to_numpy())
longitudes = np.radians(aisPositions.df['longitude'].to_numpy())
cogs = np.radians(aisPositions.df['cog'].to_numpy())
headings = np.radians(aisPositions.df['heading'].to_numpy())
for i in range(len(latitudes)):
lat = latitudes[i]
long = longitudes[i]
v_cog = vectorize_angle(cogs[i])
v_heading = vectorize_angle(headings[i])
new_position = rotate_vector_by_quaternion(spherical_to_carthesian(lat, long), rotation_quaternion, inverse_rotation_quaternion)
new_lat, new_long = carthesian_to_spherical(new_position)
origin_ref = local_ref(lat, long)
target_ref = local_ref(new_lat, new_long)
matrix_ob = transpose_matrix(origin_ref, base_ref)
matrix_bt = transpose_matrix(base_ref, target_ref)
# transpose vectors to base referential
v_cog = np.matmul(matrix_ob, v_cog)
v_heading = np.matmul(matrix_ob, v_heading)
# rotate vector
v_cog = rotate_vector_by_quaternion(v_cog, rotation_quaternion, inverse_rotation_quaternion)
v_heading = rotate_vector_by_quaternion(v_heading, rotation_quaternion, inverse_rotation_quaternion)
# transpose vector back to local referential of the new position
v_cog = np.matmul(matrix_bt, v_cog)
v_heading = np.matmul(matrix_bt, v_heading)
latitudes[i] = new_lat
longitudes[i] = new_long
cogs[i] = angleize_vector(v_cog)
headings[i] = angleize_vector(v_heading)
copy.df['latitude'] = np.degrees(latitudes)
copy.df['longitude'] = np.degrees(longitudes)
copy.df['cog'] = np.degrees(cogs)
copy.df['heading'] = np.degrees(headings)
return copy
import random
import numpy as np
from skais.learn.data_augmentation import shift_positions
class RandomAxisRotationEngine:
def __init__(self, shifts_per_trajectory=1):
self.shifts_per_trajectory = shifts_per_trajectory
def apply(self, trajectories, shuffle=True):
new_trajectories = []
for trajectory in trajectories:
for _ in range(self.shifts_per_trajectory):
new_trajectories.append(shift_positions(trajectory, random.uniform(0, 1)*np.pi - np.pi/2,
2*(random.uniform(0, 1)*np.pi) - np.pi,
2*(random.uniform(0, 1)*np.pi) - np.pi))
if not shuffle:
return new_trajectories
else:
return random.shuffle(new_trajectories)
import unittest
from skais.ais.ais_trajectory import AISTrajectory
from skais.learn.data_augmentation import *
import pandas as pd
class data_augmentation(unittest.TestCase):
def test_shift(self):
trajectory = AISTrajectory(
pd.DataFrame(
{
'ts_sec': [i for i in range(10)],
'latitude': [0 for _ in range(5)] + [45 for _ in range(5)],
'longitude': [0 for _ in range(10)],
'cog': [0 for _ in range(10)],
'heading': [90 for _ in range(10)]
}
)
)
shifted = shift_positions(trajectory, 0, 0, np.pi / 2)
self.assertTrue(True)
def test_shift_2(self):
trajectory = AISTrajectory(
pd.DataFrame(
{
'ts_sec': [i for i in range(10)],
'latitude': [0 for _ in range(10)],
'longitude': [-150, -120, -60, -30, 0, 30, 60, 120, 150, 180],
'cog': [0 for _ in range(10)],
'heading': [90 for _ in range(10)]
}
)
)
shifted = shift_positions(trajectory, 0, 0, np.pi / 2)
self.assertTrue(True)
def test_shift_3(self):
trajectory = AISTrajectory(
pd.DataFrame(
{
'ts_sec': [0],
'latitude': [-45],
'longitude': [45],
'cog': [45],
'heading': [120]
}
)
)
shifted = shift_positions(trajectory, np.pi/2, 0, np.pi / 2)
self.assertTrue(True)
import unittest import unittest
from skais.utils.geometry import bresenham import numpy as np
from skais.process.geography import PI
from skais.utils.geometry import bresenham, vectorize_angle, transpose_matrix, vector_rotation, local_ref
class TestGeometry(unittest.TestCase): class TestGeometry(unittest.TestCase):
...@@ -18,7 +21,6 @@ class TestGeometry(unittest.TestCase): ...@@ -18,7 +21,6 @@ class TestGeometry(unittest.TestCase):
self.assertListEqual(result, expected) self.assertListEqual(result, expected)
def test_bresenham_inverted_2(self): def test_bresenham_inverted_2(self):
result = bresenham(16, 4, 3, 9) result = bresenham(16, 4, 3, 9)
expected = [(3, 9), (4, 9), (5, 8), (6, 8), (7, 7), (8, 7), (9, 7), (10, 6), (11, 6), (12, 6), (13, 5), (14, 5), expected = [(3, 9), (4, 9), (5, 8), (6, 8), (7, 7), (8, 7), (9, 7), (10, 6), (11, 6), (12, 6), (13, 5), (14, 5),
...@@ -37,6 +39,74 @@ class TestGeometry(unittest.TestCase): ...@@ -37,6 +39,74 @@ class TestGeometry(unittest.TestCase):
self.assertListEqual(result, expected) self.assertListEqual(result, expected)
def test_vectorize_angle_0(self):
vectorized_angle = vectorize_angle(0)
np.testing.assert_almost_equal(vectorized_angle, np.array([1, 0, 0]))
def test_vectorize_angle_half_PI(self):
vectorized_angle = vectorize_angle(PI / 2)
np.testing.assert_almost_equal(vectorized_angle, np.array([0, 1, 0]))
def test_vectorize_angle_PI(self):
vectorized_angle = vectorize_angle(PI)
np.testing.assert_almost_equal(vectorized_angle, np.array([-1, 0, 0]))
def test_transpose_matrix_1(self):
origin = np.array(
[[1, 0, 0],
[0, 1, 0],
[0, 0, 1]]
)
target = np.array(
[[1, 0, 0],
[0, 1, 0],
[0, 0, 1]]
)
result = transpose_matrix(origin, target)
expected = np.array(
[[1, 0, 0],
[0, 1, 0],
[0, 0, 1]]
)
np.testing.assert_almost_equal(result, expected)
def test_transpose_matrix_2(self):
origin = np.array(
[[1, 0, 0],
[0, 1, 0],
[0, 0, 1]]
)
target = np.array(
[[0, 1, 0],
[1, 0, 0],
[0, 0, 1]]
)
result = transpose_matrix(origin, target)
expected = np.array(
[[0, 1, 0],
[1, 0, 0],
[0, 0, 1]]
)
np.testing.assert_almost_equal(result, expected)
def test_rotate_vector(self):
result = vector_rotation(np.array([0, 0, 1]), 0, 0, np.pi / 2)
np.testing.assert_almost_equal(result, np.array([0, -1, 0]))
def test_local_ref_0(self):
result = local_ref(0, 0)
np.testing.assert_almost_equal(result, np.array([[0, 0, -1],
[0, 1, 0],
[1, 0, 0]]))
def test_local_ref_1(self):
result = local_ref(np.pi/2, 0)
np.testing.assert_almost_equal(result, np.array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]]))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -4,7 +4,7 @@ from numba import jit ...@@ -4,7 +4,7 @@ from numba import jit
R = 6371000 R = 6371000
@jit(nopython=True) @jit(nopython=True, fastmath=True)
def great_circle(lat1, lat2, long1, long2): def great_circle(lat1, lat2, long1, long2):
x1 = np.radians(lat1) x1 = np.radians(lat1)
y1 = np.radians(long1) y1 = np.radians(long1)
......
import numpy as np import numpy as np
from numba import jit from numba import jit
import math as m
@jit(nopython=True) @jit(nopython=True)
def dist_on_grid(x1, y1, x2, y2): def dist_on_grid(x1, y1, x2, y2):
...@@ -65,3 +67,101 @@ def bresenham(x1, y1, x2, y2): ...@@ -65,3 +67,101 @@ def bresenham(x1, y1, x2, y2):
pixels.append((x, y)) pixels.append((x, y))
return pixels return pixels
@jit(nopython=True, cache=True)
def vectorize_angle(angle):
return np.array([-np.cos(angle), np.sin(angle), 0])
@jit(nopython=True, cache=True)
def angleize_vector(vector):
if vector[2] > 0.0001:
raise ValueError
return np.arctan2(vector[1], -vector[0])
@jit(nopython=True, cache=True)
def local_ref(lat, long):
theta = (np.pi / 2) - lat
phi = long
return np.array(
[
[np.cos(theta) * np.cos(phi), np.cos(theta) * np.sin(phi), -np.sin(theta)],
[-np.sin(phi), np.cos(phi), 0],
[np.sin(theta) * np.cos(phi), np.sin(theta) * np.sin(phi), np.cos(theta)]
]
)
# @jit(nopython=True, cache=True)
def transpose_matrix(origin_ref, target_ref):
i1 = origin_ref[0, :]
j1 = origin_ref[1, :]
k1 = origin_ref[2, :]
i2 = target_ref[0, :]
j2 = target_ref[1, :]
k2 = target_ref[2, :]
return np.array(
[
[i1.dot(i2), j1.dot( i2), k1.dot(i2)],
[i1.dot(j2), j1.dot(j2), k1.dot(j2)],
[i1.dot(k2), j1.dot(k2), k1.dot(k2)]
]
)
# return np.matmul(origin_ref, target_ref)
@jit(nopython=True, cache=True)
def rotation_quaternions(lat, long, angle):
theta = (np.pi / 2) - lat
phi = long
vx = np.cos(phi) * np.sin(theta)
vy = np.sin(phi) * np.sin(theta)
vz = np.cos(theta)
return (np.array([np.cos(angle / 2), vx * np.sin(angle / 2), vy * np.sin(angle / 2), vz * np.sin(angle / 2)]),
np.array([np.cos(angle / 2), -vx * np.sin(angle / 2), -vy * np.sin(angle / 2), -vz * np.sin(angle / 2)]))
@jit(nopython=True, cache=True)
def quaternion_multiply(quaternion0, quaternion1):
w0, x0, y0, z0 = quaternion0
w1, x1, y1, z1 = quaternion1
return np.array([(w0 * w1) - (x0 * x1) - (y0 * y1) - (z0 * z1),
(w0 * x1) + (x0 * w1) + (y0 * z1) - (z0 * y1),
(w0 * y1) - (x0 * z1) + (y0 * w1) + (z0 * x1),
(w0 * z1) + (x0 * y1) - (y0 * x1) + (z0 * w1)])
@jit(nopython=True, cache=True)
def vector_rotation(vect, lat, long, angle):
q, q_conjugate = rotation_quaternions(lat, long, angle)
v = np.insert(vect, 0, 0)
return quaternion_multiply(quaternion_multiply(q, v), q_conjugate)[1:]
@jit(nopython=True, cache=True)
def spherical_to_carthesian(lat, long):
theta = (np.pi / 2) - lat
phi = long
return np.array([np.cos(phi) * np.sin(theta), np.sin(phi) * np.sin(theta), np.cos(theta)])
@jit(nopython=True, cache=True)
def carthesian_to_spherical(vect):
x = vect[0]
y = vect[1]
z = vect[2]
XsqPlusYsq = x ** 2 + y ** 2
return m.atan2(z, m.sqrt(XsqPlusYsq)), m.atan2(y, x)
@jit(nopython=True, cache=True)
def rotate_vector_by_quaternion(vector, quaternion, inverse_quaternion):
vect = np.zeros(4)
vect[1:] = vector
return quaternion_multiply(quaternion_multiply(quaternion, vect), inverse_quaternion)[1:]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment