compvis / test /geometry /test_conversions.py
Dexter's picture
Upload folder using huggingface_hub
36c95ba verified
Raw
History Blame Contribute Delete
67.4 kB
from functools import partial
import numpy as np
import pytest
import torch
from torch.autograd import gradcheck
import kornia
from kornia.geometry.conversions import QuaternionCoeffOrder
from kornia.testing import assert_close, create_eye_batch, tensor_to_gradcheck_var
@pytest.fixture
def atol(device, dtype):
"""Lower tolerance for cuda-float16 only."""
if 'cuda' in device.type and dtype == torch.float16:
return 1.0e-3
return 1.0e-4
@pytest.fixture
def rtol(device, dtype):
"""Lower tolerance for cuda-float16 only."""
if 'cuda' in device.type and dtype == torch.float16:
return 1.0e-3
return 1.0e-4
# based on:
# https://github.com/ceres-solver/ceres-solver/blob/master/internal/ceres/rotation_test.cc#L271
class TestAngleAxisToQuaternion:
def test_smoke_xyzw(self, device, dtype):
angle_axis = torch.zeros(3, dtype=dtype, device=device)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(
angle_axis, order=QuaternionCoeffOrder.XYZW
)
assert quaternion.shape == (4,)
def test_smoke(self, device, dtype):
angle_axis = torch.zeros(3, dtype=dtype, device=device)
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(angle_axis, order=QuaternionCoeffOrder.WXYZ)
assert quaternion.shape == (4,)
@pytest.mark.parametrize("batch_size", (1, 3, 8))
def test_smoke_batch_xyzw(self, batch_size, device, dtype):
angle_axis = torch.zeros(batch_size, 3, device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(
angle_axis, order=QuaternionCoeffOrder.XYZW
)
assert quaternion.shape == (batch_size, 4)
@pytest.mark.parametrize("batch_size", (1, 3, 8))
def test_smoke_batch(self, batch_size, device, dtype):
angle_axis = torch.zeros(batch_size, 3, device=device, dtype=dtype)
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(angle_axis, order=QuaternionCoeffOrder.WXYZ)
assert quaternion.shape == (batch_size, 4)
def test_zero_angle_xyzw(self, device, dtype, atol, rtol):
angle_axis = torch.tensor((0.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, 0.0, 1.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(
angle_axis, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_zero_angle(self, device, dtype, atol, rtol):
angle_axis = torch.tensor((0.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((1.0, 0.0, 0.0, 0.0), device=device, dtype=dtype)
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(angle_axis, order=QuaternionCoeffOrder.WXYZ)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_small_angle_x_xyzw(self, device, dtype, atol, rtol):
theta = 1.0e-2
angle_axis = torch.tensor((theta, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((np.sin(theta / 2.0), 0.0, 0.0, np.cos(theta / 2.0)), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(
angle_axis, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_small_angle_x(self, device, dtype, atol, rtol):
theta = 1.0e-2
angle_axis = torch.tensor((theta, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((np.cos(theta / 2.0), np.sin(theta / 2.0), 0.0, 0.0), device=device, dtype=dtype)
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(angle_axis, order=QuaternionCoeffOrder.WXYZ)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_small_angle_y_xyzw(self, device, dtype, atol, rtol):
theta = 1.0e-2
angle_axis = torch.tensor((0.0, theta, 0.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, np.sin(theta / 2.0), 0.0, np.cos(theta / 2.0)), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(
angle_axis, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_small_angle_y(self, device, dtype, atol, rtol):
theta = 1.0e-2
angle_axis = torch.tensor((0.0, theta, 0.0), device=device, dtype=dtype)
expected = torch.tensor((np.cos(theta / 2.0), 0.0, np.sin(theta / 2.0), 0.0), device=device, dtype=dtype)
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(angle_axis, order=QuaternionCoeffOrder.WXYZ)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_small_angle_z_xyzw(self, device, dtype, atol, rtol):
theta = 1.0e-2
angle_axis = torch.tensor((0.0, 0.0, theta), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, np.sin(theta / 2.0), np.cos(theta / 2.0)), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(
angle_axis, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_small_angle_z(self, device, dtype, atol, rtol):
theta = 1.0e-2
angle_axis = torch.tensor((0.0, 0.0, theta), device=device, dtype=dtype)
expected = torch.tensor((np.cos(theta / 2.0), 0.0, 0.0, np.sin(theta / 2.0)), device=device, dtype=dtype)
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(angle_axis, order=QuaternionCoeffOrder.WXYZ)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_x_rotation_xyzw(self, device, dtype, atol, rtol):
half_sqrt2 = 0.5 * np.sqrt(2.0)
angle_axis = torch.tensor((kornia.pi / 2.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((half_sqrt2, 0.0, 0.0, half_sqrt2), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(
angle_axis, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_x_rotation(self, device, dtype, atol, rtol):
half_sqrt2 = 0.5 * np.sqrt(2.0)
angle_axis = torch.tensor((kornia.pi / 2.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((half_sqrt2, half_sqrt2, 0.0, 0.0), device=device, dtype=dtype)
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(angle_axis, order=QuaternionCoeffOrder.WXYZ)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_y_rotation_xyzw(self, device, dtype, atol, rtol):
half_sqrt2 = 0.5 * np.sqrt(2.0)
angle_axis = torch.tensor((0.0, kornia.pi / 2.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, half_sqrt2, 0.0, half_sqrt2), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(
angle_axis, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_y_rotation(self, device, dtype, atol, rtol):
half_sqrt2 = 0.5 * np.sqrt(2.0)
angle_axis = torch.tensor((0.0, kornia.pi / 2.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((half_sqrt2, 0.0, half_sqrt2, 0.0), device=device, dtype=dtype)
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(angle_axis, order=QuaternionCoeffOrder.WXYZ)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_z_rotation_xyzw(self, device, dtype, atol, rtol):
half_sqrt2 = 0.5 * np.sqrt(2.0)
angle_axis = torch.tensor((0.0, 0.0, kornia.pi / 2.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, half_sqrt2, half_sqrt2), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(
angle_axis, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_z_rotation(self, device, dtype, atol, rtol):
half_sqrt2 = 0.5 * np.sqrt(2.0)
angle_axis = torch.tensor((0.0, 0.0, kornia.pi / 2.0), device=device, dtype=dtype)
expected = torch.tensor((half_sqrt2, 0.0, 0.0, half_sqrt2), device=device, dtype=dtype)
quaternion = kornia.geometry.conversions.angle_axis_to_quaternion(angle_axis, order=QuaternionCoeffOrder.WXYZ)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_gradcheck_xyzw(self, device, dtype):
eps = torch.finfo(dtype).eps
angle_axis = torch.tensor((0.0, 0.0, 0.0), device=device, dtype=dtype) + eps
angle_axis = tensor_to_gradcheck_var(angle_axis)
# evaluate function gradient
with pytest.warns(UserWarning):
assert gradcheck(
partial(kornia.geometry.conversions.angle_axis_to_quaternion, order=QuaternionCoeffOrder.XYZW),
(angle_axis,),
raise_exception=True,
)
def test_gradcheck(self, device, dtype):
eps = torch.finfo(dtype).eps
angle_axis = torch.tensor((0.0, 0.0, 0.0), device=device, dtype=dtype) + eps
angle_axis = tensor_to_gradcheck_var(angle_axis)
# evaluate function gradient
assert gradcheck(
partial(kornia.geometry.conversions.angle_axis_to_quaternion, order=QuaternionCoeffOrder.WXYZ),
(angle_axis,),
raise_exception=True,
)
class TestQuaternionToAngleAxis:
def test_smoke_xyzw(self, device, dtype):
quaternion = torch.zeros(4, device=device, dtype=dtype)
with pytest.warns(UserWarning):
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert angle_axis.shape == (3,)
def test_smoke(self, device, dtype):
quaternion = torch.zeros(4, device=device, dtype=dtype)
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert angle_axis.shape == (3,)
@pytest.mark.parametrize("batch_size", (1, 3, 8))
def test_smoke_batch_xyzw(self, batch_size, device, dtype):
quaternion = torch.zeros(batch_size, 4, device=device, dtype=dtype)
with pytest.warns(UserWarning):
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert angle_axis.shape == (batch_size, 3)
@pytest.mark.parametrize("batch_size", (1, 3, 8))
def test_smoke_batch(self, batch_size, device, dtype):
quaternion = torch.zeros(batch_size, 4, device=device, dtype=dtype)
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert angle_axis.shape == (batch_size, 3)
def test_unit_quaternion_xyzw(self, device, dtype, atol, rtol):
quaternion = torch.tensor((0.0, 0.0, 0.0, 1.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, 0.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_unit_quaternion(self, device, dtype, atol, rtol):
quaternion = torch.tensor((1.0, 0.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, 0.0), device=device, dtype=dtype)
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_x_rotation_xyzw(self, device, dtype, atol, rtol):
quaternion = torch.tensor((1.0, 0.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((kornia.pi, 0.0, 0.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_x_rotation(self, device, dtype, atol, rtol):
quaternion = torch.tensor((0.0, 1.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((kornia.pi, 0.0, 0.0), device=device, dtype=dtype)
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_y_rotation_xyzw(self, device, dtype, atol, rtol):
quaternion = torch.tensor((0.0, 1.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, kornia.pi, 0.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_y_rotation(self, device, dtype, atol, rtol):
quaternion = torch.tensor((0.0, 0.0, 1.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, kornia.pi, 0.0), device=device, dtype=dtype)
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_z_rotation_xyzw(self, device, dtype, atol, rtol):
quaternion = torch.tensor((0.0, 0.0, 0.5, np.sqrt(3.0) / 2.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, kornia.pi / 3.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_z_rotation(self, device, dtype, atol, rtol):
quaternion = torch.tensor((np.sqrt(3.0) / 2.0, 0.0, 0.0, 0.5), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, kornia.pi / 3.0), device=device, dtype=dtype)
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_small_angle_x_xyzw(self, device, dtype, atol, rtol):
theta = 1.0e-2
quaternion = torch.tensor((np.sin(theta / 2.0), 0.0, 0.0, np.cos(theta / 2.0)), device=device, dtype=dtype)
expected = torch.tensor((theta, 0.0, 0.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_small_angle_x(self, device, dtype, atol, rtol):
theta = 1.0e-2
quaternion = torch.tensor((np.cos(theta / 2.0), np.sin(theta / 2.0), 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((theta, 0.0, 0.0), device=device, dtype=dtype)
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_small_angle_y_xyzw(self, device, dtype, atol, rtol):
theta = 1.0e-2
quaternion = torch.tensor((0.0, np.sin(theta / 2), 0.0, np.cos(theta / 2)), device=device, dtype=dtype)
expected = torch.tensor((0.0, theta, 0.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_small_angle_y(self, device, dtype, atol, rtol):
theta = 1.0e-2
quaternion = torch.tensor((np.cos(theta / 2), 0.0, np.sin(theta / 2), 0.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, theta, 0.0), device=device, dtype=dtype)
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_small_angle_z_xyzw(self, device, dtype, atol, rtol):
theta = 1.0e-2
quaternion = torch.tensor((0.0, 0.0, np.sin(theta / 2), np.cos(theta / 2)), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, theta), device=device, dtype=dtype)
with pytest.warns(UserWarning):
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_small_angle_z(self, device, dtype, atol, rtol):
theta = 1.0e-2
quaternion = torch.tensor((np.cos(theta / 2), 0.0, 0.0, np.sin(theta / 2)), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, theta), device=device, dtype=dtype)
angle_axis = kornia.geometry.conversions.quaternion_to_angle_axis(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert_close(angle_axis, expected, atol=atol, rtol=rtol)
def test_gradcheck_xyzw(self, device, dtype):
eps = torch.finfo(dtype).eps
quaternion = torch.tensor((0.0, 0.0, 0.0, 1.0), device=device, dtype=dtype) + eps
quaternion = tensor_to_gradcheck_var(quaternion)
# evaluate function gradient
with pytest.warns(UserWarning):
assert gradcheck(
partial(kornia.geometry.conversions.quaternion_to_angle_axis, order=QuaternionCoeffOrder.XYZW),
(quaternion,),
raise_exception=True,
)
def test_gradcheck(self, device, dtype):
eps = torch.finfo(dtype).eps
quaternion = torch.tensor((1.0, 0.0, 0.0, 0.0), device=device, dtype=dtype) + eps
quaternion = tensor_to_gradcheck_var(quaternion)
# evaluate function gradient
assert gradcheck(
partial(kornia.geometry.conversions.quaternion_to_angle_axis, order=QuaternionCoeffOrder.WXYZ),
(quaternion,),
raise_exception=True,
)
class TestRotationMatrixToQuaternion:
@pytest.mark.parametrize("batch_size", (1, 3, 8))
def test_smoke_batch_xyzw(self, batch_size, device, dtype):
matrix = torch.zeros(batch_size, 3, 3, device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.rotation_matrix_to_quaternion(
matrix, order=QuaternionCoeffOrder.XYZW
)
assert quaternion.shape == (batch_size, 4)
@pytest.mark.parametrize("batch_size", (1, 3, 8))
def test_smoke_batch(self, batch_size, device, dtype):
matrix = torch.zeros(batch_size, 3, 3, device=device, dtype=dtype)
quaternion = kornia.geometry.conversions.rotation_matrix_to_quaternion(matrix, order=QuaternionCoeffOrder.WXYZ)
assert quaternion.shape == (batch_size, 4)
def test_identity_xyzw(self, device, dtype, atol, rtol):
matrix = torch.tensor(((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, 0.0, 1.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.rotation_matrix_to_quaternion(
matrix, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_identity(self, device, dtype, atol, rtol):
matrix = torch.tensor(((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)), device=device, dtype=dtype)
expected = torch.tensor((1.0, 0.0, 0.0, 0.0), device=device, dtype=dtype)
quaternion = kornia.geometry.conversions.rotation_matrix_to_quaternion(matrix, order=QuaternionCoeffOrder.WXYZ)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_rot_x_45_xyzw(self, device, dtype, atol, rtol):
matrix = torch.tensor(((1.0, 0.0, 0.0), (0.0, 0.0, -1.0), (0.0, 1.0, 0.0)), device=device, dtype=dtype)
pi_half2 = torch.cos(kornia.pi / 4.0).to(device=device, dtype=dtype)
expected = torch.tensor((pi_half2, 0.0, 0.0, pi_half2), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.rotation_matrix_to_quaternion(
matrix, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_rot_x_45(self, device, dtype, atol, rtol):
matrix = torch.tensor(((1.0, 0.0, 0.0), (0.0, 0.0, -1.0), (0.0, 1.0, 0.0)), device=device, dtype=dtype)
pi_half2 = torch.cos(kornia.pi / 4.0).to(device=device, dtype=dtype)
expected = torch.tensor((pi_half2, pi_half2, 0.0, 0.0), device=device, dtype=dtype)
quaternion = kornia.geometry.conversions.rotation_matrix_to_quaternion(matrix, order=QuaternionCoeffOrder.WXYZ)
assert_close(quaternion, expected, atol=atol, rtol=rtol)
def test_back_and_forth_xyzw(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
matrix = torch.tensor(((1.0, 0.0, 0.0), (0.0, 0.0, -1.0), (0.0, 1.0, 0.0)), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.rotation_matrix_to_quaternion(
matrix, eps=eps, order=QuaternionCoeffOrder.XYZW
)
matrix_hat = kornia.geometry.conversions.quaternion_to_rotation_matrix(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert_close(matrix, matrix_hat, atol=atol, rtol=rtol)
def test_back_and_forth(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
matrix = torch.tensor(((1.0, 0.0, 0.0), (0.0, 0.0, -1.0), (0.0, 1.0, 0.0)), device=device, dtype=dtype)
quaternion = kornia.geometry.conversions.rotation_matrix_to_quaternion(
matrix, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
matrix_hat = kornia.geometry.conversions.quaternion_to_rotation_matrix(
quaternion, order=QuaternionCoeffOrder.WXYZ
)
assert_close(matrix, matrix_hat, atol=atol, rtol=rtol)
def test_corner_case_xyzw(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
matrix = torch.tensor(
(
(-0.7799533010, -0.5432914495, 0.3106555045),
(0.0492402576, -0.5481169224, -0.8349509239),
(0.6238971353, -0.6359263659, 0.4542570710),
),
device=device,
dtype=dtype,
)
quaternion_true = torch.tensor(
(0.280136495828629, -0.440902262926102, 0.834015488624573, 0.177614107728004), device=device, dtype=dtype
)
with pytest.warns(UserWarning):
quaternion = kornia.geometry.conversions.rotation_matrix_to_quaternion(
matrix, eps=eps, order=QuaternionCoeffOrder.XYZW
)
torch.set_printoptions(precision=10)
assert_close(quaternion_true, quaternion, atol=atol, rtol=rtol)
def test_corner_case(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
matrix = torch.tensor(
(
(-0.7799533010, -0.5432914495, 0.3106555045),
(0.0492402576, -0.5481169224, -0.8349509239),
(0.6238971353, -0.6359263659, 0.4542570710),
),
device=device,
dtype=dtype,
)
quaternion_true = torch.tensor(
(0.177614107728004, 0.280136495828629, -0.440902262926102, 0.834015488624573), device=device, dtype=dtype
)
quaternion = kornia.geometry.conversions.rotation_matrix_to_quaternion(
matrix, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
torch.set_printoptions(precision=10)
assert_close(quaternion_true, quaternion, atol=atol, rtol=rtol)
def test_gradcheck_xyzw(self, device, dtype):
eps = torch.finfo(dtype).eps
matrix = torch.eye(3, device=device, dtype=dtype)
matrix = tensor_to_gradcheck_var(matrix)
# evaluate function gradient
with pytest.warns(UserWarning):
assert gradcheck(
partial(
kornia.geometry.conversions.rotation_matrix_to_quaternion, eps=eps, order=QuaternionCoeffOrder.XYZW
),
(matrix,),
raise_exception=True,
)
def test_gradcheck(self, device, dtype):
eps = torch.finfo(dtype).eps
matrix = torch.eye(3, device=device, dtype=dtype)
matrix = tensor_to_gradcheck_var(matrix)
# evaluate function gradient
assert gradcheck(
partial(
kornia.geometry.conversions.rotation_matrix_to_quaternion, eps=eps, order=QuaternionCoeffOrder.WXYZ
),
(matrix,),
raise_exception=True,
)
@pytest.mark.skipif(torch.__version__.startswith('1.6'), reason='JIT Enum not handled.')
def test_jit_xyzw(self, device, dtype):
op = kornia.geometry.conversions.quaternion_log_to_exp
op_script = torch.jit.script(op)
quaternion = torch.tensor((0.0, 0.0, 1.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
actual = op_script(quaternion)
with pytest.warns(UserWarning):
expected = op(quaternion)
assert_close(actual, expected)
@pytest.mark.skipif(torch.__version__.startswith('1.6'), reason='JIT Enum not handled.')
def test_jit(self, device, dtype):
eps = torch.finfo(dtype).eps
op = kornia.geometry.conversions.quaternion_log_to_exp
op_script = torch.jit.script(op)
quaternion = torch.tensor((0.0, 0.0, 1.0), device=device, dtype=dtype)
actual = op_script(quaternion, eps=eps, order=QuaternionCoeffOrder.WXYZ)
expected = op(quaternion, eps=eps, order=QuaternionCoeffOrder.WXYZ)
assert_close(actual, expected)
class TestQuaternionToRotationMatrix:
@pytest.mark.parametrize("batch_size", (1, 3, 8))
def test_smoke_batch_xyzw(self, batch_size, device, dtype):
quaternion = torch.zeros(batch_size, 4, device=device, dtype=dtype)
with pytest.warns(UserWarning):
matrix = kornia.geometry.conversions.quaternion_to_rotation_matrix(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert matrix.shape == (batch_size, 3, 3)
@pytest.mark.parametrize("batch_size", (1, 3, 8))
def test_smoke_batch(self, batch_size, device, dtype):
quaternion = torch.zeros(batch_size, 4, device=device, dtype=dtype)
matrix = kornia.geometry.conversions.quaternion_to_rotation_matrix(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert matrix.shape == (batch_size, 3, 3)
def test_unit_quaternion_xyzw(self, device, dtype, atol, rtol):
quaternion = torch.tensor((0.0, 0.0, 0.0, 1.0), device=device, dtype=dtype)
expected = torch.tensor(((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)), device=device, dtype=dtype)
with pytest.warns(UserWarning):
matrix = kornia.geometry.conversions.quaternion_to_rotation_matrix(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert_close(matrix, expected, atol=atol, rtol=rtol)
def test_unit_quaternion(self, device, dtype, atol, rtol):
quaternion = torch.tensor((1.0, 0.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor(((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)), device=device, dtype=dtype)
matrix = kornia.geometry.conversions.quaternion_to_rotation_matrix(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert_close(matrix, expected, atol=atol, rtol=rtol)
def test_x_rotation_xyzw(self, device, dtype, atol, rtol):
quaternion = torch.tensor((1.0, 0.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor(((1.0, 0.0, 0.0), (0.0, -1.0, 0.0), (0.0, 0.0, -1.0)), device=device, dtype=dtype)
with pytest.warns(UserWarning):
matrix = kornia.geometry.conversions.quaternion_to_rotation_matrix(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert_close(matrix, expected, atol=atol, rtol=rtol)
def test_x_rotation(self, device, dtype, atol, rtol):
quaternion = torch.tensor((0.0, 1.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor(((1.0, 0.0, 0.0), (0.0, -1.0, 0.0), (0.0, 0.0, -1.0)), device=device, dtype=dtype)
matrix = kornia.geometry.conversions.quaternion_to_rotation_matrix(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert_close(matrix, expected, atol=atol, rtol=rtol)
def test_y_rotation_xyzw(self, device, dtype, atol, rtol):
quaternion = torch.tensor((0.0, 1.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor(((-1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, -1.0)), device=device, dtype=dtype)
with pytest.warns(UserWarning):
matrix = kornia.geometry.conversions.quaternion_to_rotation_matrix(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert_close(matrix, expected, atol=atol, rtol=rtol)
def test_y_rotation(self, device, dtype, atol, rtol):
quaternion = torch.tensor((0.0, 0.0, 1.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor(((-1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, -1.0)), device=device, dtype=dtype)
matrix = kornia.geometry.conversions.quaternion_to_rotation_matrix(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert_close(matrix, expected, atol=atol, rtol=rtol)
def test_z_rotation_xyzw(self, device, dtype, atol, rtol):
quaternion = torch.tensor((0.0, 0.0, 1.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor(((-1.0, 0.0, 0.0), (0.0, -1.0, 0.0), (0.0, 0.0, 1.0)), device=device, dtype=dtype)
with pytest.warns(UserWarning):
matrix = kornia.geometry.conversions.quaternion_to_rotation_matrix(
quaternion, order=QuaternionCoeffOrder.XYZW
)
assert_close(matrix, expected, atol=atol, rtol=rtol)
def test_z_rotation(self, device, dtype, atol, rtol):
quaternion = torch.tensor((0.0, 0.0, 0.0, 1.0), device=device, dtype=dtype)
expected = torch.tensor(((-1.0, 0.0, 0.0), (0.0, -1.0, 0.0), (0.0, 0.0, 1.0)), device=device, dtype=dtype)
matrix = kornia.geometry.conversions.quaternion_to_rotation_matrix(quaternion, order=QuaternionCoeffOrder.WXYZ)
assert_close(matrix, expected, atol=atol, rtol=rtol)
def test_gradcheck_xyzw(self, device, dtype):
quaternion = torch.tensor((0.0, 0.0, 0.0, 1.0), device=device, dtype=dtype)
quaternion = tensor_to_gradcheck_var(quaternion)
# evaluate function gradient
with pytest.warns(UserWarning):
assert gradcheck(
partial(kornia.geometry.conversions.quaternion_to_rotation_matrix, order=QuaternionCoeffOrder.XYZW),
(quaternion,),
raise_exception=True,
)
def test_gradcheck(self, device, dtype):
quaternion = torch.tensor((0.0, 0.0, 0.0, 1.0), device=device, dtype=dtype)
quaternion = tensor_to_gradcheck_var(quaternion)
# evaluate function gradient
assert gradcheck(
partial(kornia.geometry.conversions.quaternion_to_rotation_matrix, order=QuaternionCoeffOrder.WXYZ),
(quaternion,),
raise_exception=True,
)
@pytest.mark.skipif(torch.__version__.startswith('1.6'), reason='JIT Enum not handled.')
def test_jit_xyzw(self, device, dtype):
op = kornia.geometry.conversions.quaternion_to_rotation_matrix
op_jit = torch.jit.script(op)
quaternion = torch.tensor((0.0, 0.0, 1.0, 0.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
assert_close(op(quaternion), op_jit(quaternion))
@pytest.mark.skipif(torch.__version__.startswith('1.6'), reason='JIT Enum not handled.')
def test_jit(self, device, dtype):
op = kornia.geometry.conversions.quaternion_to_rotation_matrix
op_jit = torch.jit.script(op)
quaternion = torch.tensor((0.0, 0.0, 0.0, 1.0), device=device, dtype=dtype)
assert_close(
op(quaternion, order=QuaternionCoeffOrder.WXYZ), op_jit(quaternion, order=QuaternionCoeffOrder.WXYZ)
)
class TestQuaternionLogToExp:
@pytest.mark.parametrize("batch_size", (1, 3, 8))
def test_smoke_batch_xyzw(self, batch_size, device, dtype):
quaternion_log = torch.zeros(batch_size, 3, device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion_exp = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, order=QuaternionCoeffOrder.XYZW
)
assert quaternion_exp.shape == (batch_size, 4)
@pytest.mark.parametrize("batch_size", (1, 3, 8))
def test_smoke_batch(self, batch_size, device, dtype):
quaternion_log = torch.zeros(batch_size, 3, device=device, dtype=dtype)
quaternion_exp = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, order=QuaternionCoeffOrder.WXYZ
)
assert quaternion_exp.shape == (batch_size, 4)
def test_unit_quaternion_xyzw(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_log = torch.tensor((0.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, 0.0, 1.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion_exp = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, eps=eps, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion_exp, expected, atol=atol, rtol=rtol)
def test_unit_quaternion(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_log = torch.tensor((0.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((1.0, 0.0, 0.0, 0.0), device=device, dtype=dtype)
quaternion_exp = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
assert_close(quaternion_exp, expected, atol=atol, rtol=rtol)
def test_pi_quaternion_x_xyzw(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
one = torch.tensor(1.0, device=device, dtype=dtype)
quaternion_log = torch.tensor((1.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((torch.sin(one), 0.0, 0.0, torch.cos(one)), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion_exp = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, eps=eps, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion_exp, expected, atol=atol, rtol=rtol)
def test_pi_quaternion_x(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
one = torch.tensor(1.0, device=device, dtype=dtype)
quaternion_log = torch.tensor((1.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((torch.cos(one), torch.sin(one), 0.0, 0.0), device=device, dtype=dtype)
quaternion_exp = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
assert_close(quaternion_exp, expected, atol=atol, rtol=rtol)
def test_pi_quaternion_y_xyzw(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
one = torch.tensor(1.0, device=device, dtype=dtype)
quaternion_log = torch.tensor((0.0, 1.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, torch.sin(one), 0.0, torch.cos(one)), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion_exp = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, eps=eps, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion_exp, expected, atol=atol, rtol=rtol)
def test_pi_quaternion_y(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
one = torch.tensor(1.0, device=device, dtype=dtype)
quaternion_log = torch.tensor((0.0, 1.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((torch.cos(one), 0.0, torch.sin(one), 0.0), device=device, dtype=dtype)
quaternion_exp = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
assert_close(quaternion_exp, expected, atol=atol, rtol=rtol)
def test_pi_quaternion_z_xyzw(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
one = torch.tensor(1.0, device=device, dtype=dtype)
quaternion_log = torch.tensor((0.0, 0.0, 1.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, torch.sin(one), torch.cos(one)), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion_exp = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, eps=eps, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion_exp, expected, atol=atol, rtol=rtol)
def test_pi_quaternion_z(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
one = torch.tensor(1.0, device=device, dtype=dtype)
quaternion_log = torch.tensor((0.0, 0.0, 1.0), device=device, dtype=dtype)
expected = torch.tensor((torch.cos(one), 0.0, 0.0, torch.sin(one)), device=device, dtype=dtype)
quaternion_exp = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
assert_close(quaternion_exp, expected, atol=atol, rtol=rtol)
def test_back_and_forth_xyzw(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_log = torch.tensor((1.0, 0.0, 0.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion_exp = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, eps=eps, order=QuaternionCoeffOrder.XYZW
)
with pytest.warns(UserWarning):
quaternion_log_hat = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion_log, quaternion_log_hat, atol=atol, rtol=rtol)
def test_back_and_forth(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_log = torch.tensor((1.0, 0.0, 0.0), device=device, dtype=dtype)
quaternion_exp = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
quaternion_log_hat = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
assert_close(quaternion_log, quaternion_log_hat, atol=atol, rtol=rtol)
def test_gradcheck_xyzw(self, device, dtype):
eps = torch.finfo(dtype).eps
quaternion = torch.tensor((0.0, 0.0, 1.0), device=device, dtype=dtype)
quaternion = tensor_to_gradcheck_var(quaternion)
# evaluate function gradient
with pytest.warns(UserWarning):
assert gradcheck(
partial(kornia.geometry.conversions.quaternion_log_to_exp, eps=eps, order=QuaternionCoeffOrder.XYZW),
(quaternion,),
raise_exception=True,
)
def test_gradcheck(self, device, dtype):
eps = torch.finfo(dtype).eps
quaternion = torch.tensor((0.0, 0.0, 1.0), device=device, dtype=dtype)
quaternion = tensor_to_gradcheck_var(quaternion)
# evaluate function gradient
assert gradcheck(
partial(kornia.geometry.conversions.quaternion_log_to_exp, eps=eps, order=QuaternionCoeffOrder.WXYZ),
(quaternion,),
raise_exception=True,
)
@pytest.mark.skipif(torch.__version__.startswith('1.6'), reason='JIT Enum not handled.')
def test_jit_xyzw(self, device, dtype):
op = kornia.geometry.conversions.quaternion_log_to_exp
op_jit = torch.jit.script(op)
quaternion = torch.tensor((0.0, 0.0, 1.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
assert_close(
op(quaternion, order=QuaternionCoeffOrder.XYZW), op_jit(quaternion, order=QuaternionCoeffOrder.XYZW)
)
@pytest.mark.skipif(torch.__version__.startswith('1.6'), reason='JIT Enum not handled.')
def test_jit(self, device, dtype):
op = kornia.geometry.conversions.quaternion_log_to_exp
op_jit = torch.jit.script(op)
quaternion = torch.tensor((0.0, 0.0, 1.0), device=device, dtype=dtype)
assert_close(
op(quaternion, order=QuaternionCoeffOrder.WXYZ), op_jit(quaternion, order=QuaternionCoeffOrder.WXYZ)
)
class TestQuaternionExpToLog:
@pytest.mark.parametrize("batch_size", (1, 3, 8))
def test_smoke_batch_xyzw(self, batch_size, device, dtype):
eps = torch.finfo(dtype).eps
quaternion_exp = torch.zeros(batch_size, 4, device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion_log = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.XYZW
)
assert quaternion_log.shape == (batch_size, 3)
@pytest.mark.parametrize("batch_size", (1, 3, 8))
def test_smoke_batch(self, batch_size, device, dtype):
eps = torch.finfo(dtype).eps
quaternion_exp = torch.zeros(batch_size, 4, device=device, dtype=dtype)
quaternion_log = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
assert quaternion_log.shape == (batch_size, 3)
def test_unit_quaternion_xyzw(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_exp = torch.tensor((0.0, 0.0, 0.0, 1.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, 0.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion_log = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion_log, expected, atol=atol, rtol=rtol)
def test_unit_quaternion(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_exp = torch.tensor((1.0, 0.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, 0.0), device=device, dtype=dtype)
quaternion_log = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
assert_close(quaternion_log, expected, atol=atol, rtol=rtol)
def test_pi_quaternion_x_xyzw(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_exp = torch.tensor((1.0, 0.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((kornia.pi / 2.0, 0.0, 0.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion_log = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion_log, expected, atol=atol, rtol=rtol)
def test_pi_quaternion_x(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_exp = torch.tensor((0.0, 1.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((kornia.pi / 2.0, 0.0, 0.0), device=device, dtype=dtype)
quaternion_log = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
assert_close(quaternion_log, expected, atol=atol, rtol=rtol)
def test_pi_quaternion_y_xyzw(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_exp = torch.tensor((0.0, 1.0, 0.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, kornia.pi / 2.0, 0.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion_log = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion_log, expected, atol=atol, rtol=rtol)
def test_pi_quaternion_y(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_exp = torch.tensor((0.0, 0.0, 1.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, kornia.pi / 2.0, 0.0), device=device, dtype=dtype)
quaternion_log = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
assert_close(quaternion_log, expected, atol=atol, rtol=rtol)
def test_pi_quaternion_z_xyzw(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_exp = torch.tensor((0.0, 0.0, 1.0, 0.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, kornia.pi / 2.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion_log = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion_log, expected, atol=atol, rtol=rtol)
def test_pi_quaternion_z(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_exp = torch.tensor((0.0, 0.0, 0.0, 1.0), device=device, dtype=dtype)
expected = torch.tensor((0.0, 0.0, kornia.pi / 2.0), device=device, dtype=dtype)
quaternion_log = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
assert_close(quaternion_log, expected, atol=atol, rtol=rtol)
def test_back_and_forth_xyzw(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_exp = torch.tensor((1.0, 0.0, 0.0, 0.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
quaternion_log = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.XYZW
)
with pytest.warns(UserWarning):
quaternion_exp_hat = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, eps=eps, order=QuaternionCoeffOrder.XYZW
)
assert_close(quaternion_exp, quaternion_exp_hat, atol=atol, rtol=rtol)
def test_back_and_forth(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
quaternion_exp = torch.tensor((0.0, 1.0, 0.0, 0.0), device=device, dtype=dtype)
quaternion_log = kornia.geometry.conversions.quaternion_exp_to_log(
quaternion_exp, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
quaternion_exp_hat = kornia.geometry.conversions.quaternion_log_to_exp(
quaternion_log, eps=eps, order=QuaternionCoeffOrder.WXYZ
)
assert_close(quaternion_exp, quaternion_exp_hat, atol=atol, rtol=rtol)
def test_gradcheck_xyzw(self, device, dtype):
eps = torch.finfo(dtype).eps
quaternion = torch.tensor((1.0, 0.0, 0.0, 0.0), device=device, dtype=dtype)
quaternion = tensor_to_gradcheck_var(quaternion)
# evaluate function gradient
with pytest.warns(UserWarning):
assert gradcheck(
partial(kornia.geometry.conversions.quaternion_exp_to_log, eps=eps, order=QuaternionCoeffOrder.XYZW),
(quaternion,),
raise_exception=True,
)
def test_gradcheck(self, device, dtype):
eps = torch.finfo(dtype).eps
quaternion = torch.tensor((0.0, 1.0, 0.0, 0.0), device=device, dtype=dtype)
quaternion = tensor_to_gradcheck_var(quaternion)
# evaluate function gradient
assert gradcheck(
partial(kornia.geometry.conversions.quaternion_exp_to_log, eps=eps, order=QuaternionCoeffOrder.WXYZ),
(quaternion,),
raise_exception=True,
)
@pytest.mark.skipif(torch.__version__.startswith('1.6'), reason='JIT Enum not handled.')
def test_jit_xyzw(self, device, dtype, atol, rtol):
op = kornia.geometry.conversions.quaternion_exp_to_log
op_jit = torch.jit.script(op)
quaternion = torch.tensor((0.0, 0.0, 1.0, 0.0), device=device, dtype=dtype)
with pytest.warns(UserWarning):
assert_close(op(quaternion), op_jit(quaternion), atol=atol, rtol=rtol)
@pytest.mark.skipif(torch.__version__.startswith('1.6'), reason='JIT Enum not handled.')
def test_jit(self, device, dtype, atol, rtol):
op = kornia.geometry.conversions.quaternion_exp_to_log
op_script = torch.jit.script(op)
quaternion = torch.tensor((0.0, 0.0, 0.0, 1.0), device=device, dtype=dtype)
actual = op_script(quaternion, eps=torch.finfo(dtype).eps, order=QuaternionCoeffOrder.WXYZ)
expected = op(quaternion, eps=torch.finfo(dtype).eps, order=QuaternionCoeffOrder.WXYZ)
assert_close(actual, expected, atol=atol, rtol=rtol)
class TestAngleAxisToRotationMatrix:
@pytest.mark.parametrize("batch_size", (1, 2, 5))
def test_rand_angle_axis_gradcheck(self, batch_size, device, dtype, atol, rtol):
# generate input data
angle_axis = torch.rand(batch_size, 3, device=device, dtype=dtype)
eye_batch = create_eye_batch(batch_size, 3, device=device, dtype=dtype)
# apply transform
rotation_matrix = kornia.geometry.conversions.angle_axis_to_rotation_matrix(angle_axis)
rotation_matrix_eye = torch.matmul(rotation_matrix, rotation_matrix.transpose(-2, -1))
assert_close(rotation_matrix_eye, eye_batch, atol=atol, rtol=rtol)
# evaluate function gradient
angle_axis = tensor_to_gradcheck_var(angle_axis) # to var
assert gradcheck(kornia.geometry.conversions.angle_axis_to_rotation_matrix, (angle_axis,), raise_exception=True)
def test_angle_axis_to_rotation_matrix(self, device, dtype, atol, rtol):
rmat_1 = torch.tensor(
(
(-0.30382753, -0.95095137, -0.05814062),
(-0.71581715, 0.26812278, -0.64476041),
(0.62872461, -0.15427791, -0.76217038),
),
device=device,
dtype=dtype,
)
rvec_1 = torch.tensor((1.50485376, -2.10737739, 0.7214174), device=device, dtype=dtype)
rmat_2 = torch.tensor(
(
(0.6027768, -0.79275544, -0.09054801),
(-0.67915707, -0.56931658, 0.46327563),
(-0.41881476, -0.21775548, -0.88157628),
),
device=device,
dtype=dtype,
)
rvec_2 = torch.tensor((-2.44916812, 1.18053411, 0.4085298), device=device, dtype=dtype)
rmat = torch.stack((rmat_2, rmat_1), dim=0)
rvec = torch.stack((rvec_2, rvec_1), dim=0)
assert_close(kornia.geometry.conversions.angle_axis_to_rotation_matrix(rvec), rmat, atol=atol, rtol=rtol)
class TestRotationMatrixToAngleAxis:
@pytest.mark.parametrize("batch_size", (1, 2, 5))
def test_rand_quaternion_gradcheck(self, batch_size, device, dtype, atol, rtol):
# generate input data
quaternion = torch.rand(batch_size, 4, device=device, dtype=dtype)
quaternion = kornia.geometry.conversions.normalize_quaternion(quaternion + 1e-6)
rotation_matrix = kornia.geometry.conversions.quaternion_to_rotation_matrix(
quaternion=quaternion, order=QuaternionCoeffOrder.WXYZ
)
eye_batch = create_eye_batch(batch_size, 3, device=device, dtype=dtype)
rotation_matrix_eye = torch.matmul(rotation_matrix, rotation_matrix.transpose(-2, -1))
# This didn't pass with atol=0.001, rtol=0.001 for float16 Cuda 11.2 GeForce 1080 Ti
assert_close(rotation_matrix_eye, eye_batch, atol=atol * 10.0, rtol=rtol * 10.0)
# evaluate function gradient
rotation_matrix = tensor_to_gradcheck_var(rotation_matrix) # to var
assert gradcheck(
kornia.geometry.conversions.rotation_matrix_to_angle_axis, (rotation_matrix,), raise_exception=True
)
def test_rotation_matrix_to_angle_axis(self, device, dtype, atol, rtol):
rmat_1 = torch.tensor(
(
(-0.30382753, -0.95095137, -0.05814062),
(-0.71581715, 0.26812278, -0.64476041),
(0.62872461, -0.15427791, -0.76217038),
),
device=device,
dtype=dtype,
)
rvec_1 = torch.tensor((1.50485376, -2.10737739, 0.7214174), device=device, dtype=dtype)
rmat_2 = torch.tensor(
(
(0.6027768, -0.79275544, -0.09054801),
(-0.67915707, -0.56931658, 0.46327563),
(-0.41881476, -0.21775548, -0.88157628),
),
device=device,
dtype=dtype,
)
rvec_2 = torch.tensor((-2.44916812, 1.18053411, 0.4085298), device=device, dtype=dtype)
rmat = torch.stack((rmat_2, rmat_1), dim=0)
rvec = torch.stack((rvec_2, rvec_1), dim=0)
assert_close(kornia.geometry.conversions.rotation_matrix_to_angle_axis(rmat), rvec, atol=atol, rtol=rtol)
def test_pi():
assert_close(kornia.constants.pi.item(), 3.141592)
@pytest.mark.parametrize("batch_shape", [(2, 3), (1, 2, 3), (2, 3, 3), (5, 5, 3)])
def test_rad2deg(batch_shape, device, dtype):
# generate input data
x_rad = kornia.constants.pi * torch.rand(batch_shape, device=device, dtype=dtype)
# convert radians/degrees
x_deg = kornia.geometry.conversions.rad2deg(x_rad)
x_deg_to_rad = kornia.geometry.conversions.deg2rad(x_deg)
# compute error
assert_close(x_rad, x_deg_to_rad)
# evaluate function gradient
assert gradcheck(kornia.geometry.conversions.rad2deg, (tensor_to_gradcheck_var(x_rad),), raise_exception=True)
@pytest.mark.parametrize("batch_shape", [(2, 3), (1, 2, 3), (2, 3, 3), (5, 5, 3)])
def test_deg2rad(batch_shape, device, dtype, atol, rtol):
# generate input data
x_deg = 180.0 * torch.rand(batch_shape, device=device, dtype=dtype)
# convert radians/degrees
x_rad = kornia.geometry.conversions.deg2rad(x_deg)
x_rad_to_deg = kornia.geometry.conversions.rad2deg(x_rad)
assert_close(x_deg, x_rad_to_deg, atol=atol, rtol=rtol)
assert gradcheck(kornia.geometry.conversions.deg2rad, (tensor_to_gradcheck_var(x_deg),), raise_exception=True)
class TestPolCartConversions:
def test_smoke(self, device, dtype):
x = torch.ones(1, 1, 1, 1, device=device, dtype=dtype)
assert kornia.geometry.conversions.pol2cart(x, x) is not None
assert kornia.geometry.conversions.cart2pol(x, x) is not None
@pytest.mark.parametrize("batch_shape", [(2, 3), (1, 2, 3), (2, 3, 3), (5, 5, 3)])
def test_pol2cart(self, batch_shape, device, dtype):
# generate input data
rho = torch.rand(batch_shape, dtype=dtype)
phi = kornia.constants.pi * torch.rand(batch_shape, dtype=dtype)
rho = rho.to(device)
phi = phi.to(device)
# convert pol/cart
x_pol2cart, y_pol2cart = kornia.geometry.conversions.pol2cart(rho, phi)
rho_pol2cart, phi_pol2cart = kornia.geometry.conversions.cart2pol(x_pol2cart, y_pol2cart, 0)
assert_close(rho, rho_pol2cart)
assert_close(phi, phi_pol2cart)
assert gradcheck(
kornia.geometry.conversions.pol2cart,
(tensor_to_gradcheck_var(rho), tensor_to_gradcheck_var(phi)),
raise_exception=True,
)
@pytest.mark.parametrize("batch_shape", [(2, 3), (1, 2, 3), (2, 3, 3), (5, 5, 3)])
def test_cart2pol(self, batch_shape, device, dtype):
# generate input data
x = torch.rand(batch_shape, dtype=dtype)
y = torch.rand(batch_shape, dtype=dtype)
x = x.to(device)
y = y.to(device)
# convert cart/pol
rho_cart2pol, phi_cart2pol = kornia.geometry.conversions.cart2pol(x, y, 0)
x_cart2pol, y_cart2pol = kornia.geometry.conversions.pol2cart(rho_cart2pol, phi_cart2pol)
assert_close(x, x_cart2pol)
assert_close(y, y_cart2pol)
assert gradcheck(
kornia.geometry.conversions.cart2pol,
(tensor_to_gradcheck_var(x), tensor_to_gradcheck_var(y)),
raise_exception=True,
)
class TestConvertPointsToHomogeneous:
def test_convert_points(self, device, dtype):
# generate input data
points_h = torch.tensor(
[[1.0, 2.0, 1.0], [0.0, 1.0, 2.0], [2.0, 1.0, 0.0], [-1.0, -2.0, -1.0], [0.0, 1.0, -2.0]],
device=device,
dtype=dtype,
)
expected = torch.tensor(
[
[1.0, 2.0, 1.0, 1.0],
[0.0, 1.0, 2.0, 1.0],
[2.0, 1.0, 0.0, 1.0],
[-1.0, -2.0, -1.0, 1.0],
[0.0, 1.0, -2.0, 1.0],
],
device=device,
dtype=dtype,
)
# to euclidean
points = kornia.geometry.conversions.convert_points_to_homogeneous(points_h)
assert_close(points, expected, atol=1e-4, rtol=1e-4)
def test_convert_points_batch(self, device, dtype):
# generate input data
points_h = torch.tensor([[[2.0, 1.0, 0.0]], [[0.0, 1.0, 2.0]], [[0.0, 1.0, -2.0]]], device=device, dtype=dtype)
expected = torch.tensor(
[[[2.0, 1.0, 0.0, 1.0]], [[0.0, 1.0, 2.0, 1.0]], [[0.0, 1.0, -2.0, 1.0]]], device=device, dtype=dtype
)
# to euclidean
points = kornia.geometry.conversions.convert_points_to_homogeneous(points_h)
assert_close(points, expected, atol=1e-4, rtol=1e-4)
@pytest.mark.parametrize("batch_shape", [(2, 3), (1, 2, 3), (2, 3, 3), (5, 5, 3)])
def test_gradcheck(self, batch_shape, device, dtype):
points_h = torch.rand(batch_shape, device=device, dtype=dtype)
# evaluate function gradient
points_h = tensor_to_gradcheck_var(points_h) # to var
assert gradcheck(kornia.geometry.conversions.convert_points_to_homogeneous, (points_h,), raise_exception=True)
def test_jit(self, device, dtype):
op = kornia.geometry.conversions.convert_points_to_homogeneous
op_jit = torch.jit.script(op)
points_h = torch.zeros(1, 2, 3, device=device, dtype=dtype)
assert_close(op(points_h), op_jit(points_h))
class TestConvertAtoH:
def test_convert_points(self, device, dtype):
# generate input data
A = torch.tensor([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], device=device, dtype=dtype).view(1, 2, 3)
expected = torch.tensor([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], device=device, dtype=dtype).view(
1, 3, 3
)
# to euclidean
H = kornia.geometry.conversions.convert_affinematrix_to_homography(A)
assert_close(H, expected)
@pytest.mark.parametrize("batch_shape", [(10, 2, 3), (16, 2, 3)])
def test_gradcheck(self, batch_shape, device, dtype):
points_h = torch.rand(batch_shape, device=device, dtype=dtype)
# evaluate function gradient
points_h = tensor_to_gradcheck_var(points_h) # to var
assert gradcheck(
kornia.geometry.conversions.convert_affinematrix_to_homography, (points_h,), raise_exception=True
)
def test_jit(self, device, dtype):
op = kornia.geometry.conversions.convert_affinematrix_to_homography
op_jit = torch.jit.script(op)
points_h = torch.zeros(1, 2, 3, device=device, dtype=dtype)
assert_close(op(points_h), op_jit(points_h))
class TestConvertPointsFromHomogeneous:
@pytest.mark.parametrize("batch_shape", [(2, 3), (1, 2, 3), (2, 3, 3), (5, 5, 3)])
def test_cardinality(self, device, dtype, batch_shape):
points_h = torch.rand(batch_shape, device=device, dtype=dtype)
points = kornia.geometry.conversions.convert_points_from_homogeneous(points_h)
assert points.shape == points.shape[:-1] + (2,)
def test_points(self, device, dtype):
# generate input data
points_h = torch.tensor(
[[1.0, 2.0, 1.0], [0.0, 1.0, 2.0], [2.0, 1.0, 0.0], [-1.0, -2.0, -1.0], [0.0, 1.0, -2.0]],
device=device,
dtype=dtype,
)
expected = torch.tensor(
[[1.0, 2.0], [0.0, 0.5], [2.0, 1.0], [1.0, 2.0], [0.0, -0.5]], device=device, dtype=dtype
)
# to euclidean
points = kornia.geometry.conversions.convert_points_from_homogeneous(points_h)
assert_close(points, expected, atol=1e-4, rtol=1e-4)
def test_points_batch(self, device, dtype):
# generate input data
points_h = torch.tensor([[[2.0, 1.0, 0.0]], [[0.0, 1.0, 2.0]], [[0.0, 1.0, -2.0]]], device=device, dtype=dtype)
expected = torch.tensor([[[2.0, 1.0]], [[0.0, 0.5]], [[0.0, -0.5]]], device=device, dtype=dtype)
# to euclidean
points = kornia.geometry.conversions.convert_points_from_homogeneous(points_h)
assert_close(points, expected, atol=1e-4, rtol=1e-4)
def test_gradcheck(self, device, dtype):
points_h = torch.ones(1, 10, 3, device=device, dtype=dtype)
# evaluate function gradient
points_h = tensor_to_gradcheck_var(points_h) # to var
assert gradcheck(kornia.geometry.conversions.convert_points_from_homogeneous, (points_h,), raise_exception=True)
@pytest.mark.skip("RuntimeError: Jacobian mismatch for output 0 with respect to input 0,")
def test_gradcheck_zvec_zeros(self, device, dtype):
# generate input data
points_h = torch.tensor([[1.0, 2.0, 0.0], [0.0, 1.0, 0.1], [2.0, 1.0, 0.1]], device=device, dtype=dtype)
# evaluate function gradient
points_h = tensor_to_gradcheck_var(points_h) # to var
assert gradcheck(kornia.geometry.conversions.convert_points_from_homogeneous, (points_h,), raise_exception=True)
def test_jit(self, device, dtype):
op = kornia.geometry.conversions.convert_points_from_homogeneous
op_jit = torch.jit.script(op)
points_h = torch.zeros(1, 2, 3, device=device, dtype=dtype)
assert_close(op(points_h), op_jit(points_h))
class TestNormalizePixelCoordinates:
def test_tensor_bhw2(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
height, width = 3, 4
grid = kornia.utils.create_meshgrid(height, width, normalized_coordinates=False, device=device).to(dtype=dtype)
expected = kornia.utils.create_meshgrid(height, width, normalized_coordinates=True, device=device).to(
dtype=dtype
)
grid_norm = kornia.geometry.conversions.normalize_pixel_coordinates(grid, height, width, eps=eps)
assert_close(grid_norm, expected, atol=atol, rtol=rtol)
def test_list(self, device, dtype, atol, rtol):
eps = torch.finfo(dtype).eps
height, width = 3, 4
grid = kornia.utils.create_meshgrid(height, width, normalized_coordinates=False, device=device).to(dtype=dtype)
grid = grid.contiguous().view(-1, 2)
expected = kornia.utils.create_meshgrid(height, width, normalized_coordinates=True, device=device).to(
dtype=dtype
)
expected = expected.contiguous().view(-1, 2)
grid_norm = kornia.geometry.conversions.normalize_pixel_coordinates(grid, height, width, eps=eps)
assert_close(grid_norm, expected, atol=atol, rtol=rtol)
def test_jit(self, device, dtype):
op = kornia.geometry.conversions.normalize_pixel_coordinates
op_script = torch.jit.script(op)
height, width = 3, 4
grid = kornia.utils.create_meshgrid(height, width, normalized_coordinates=True, device=device).to(dtype=dtype)
actual = op_script(grid, height, width)
expected = op(grid, height, width)
assert_close(actual, expected)
class TestDenormalizePixelCoordinates:
def test_tensor_bhw2(self, device, dtype):
height, width = 3, 4
grid = kornia.utils.create_meshgrid(height, width, normalized_coordinates=True, device=device).to(dtype=dtype)
expected = kornia.utils.create_meshgrid(height, width, normalized_coordinates=False, device=device).to(
dtype=dtype
)
grid_norm = kornia.geometry.conversions.denormalize_pixel_coordinates(grid, height, width)
assert_close(grid_norm, expected, atol=1e-4, rtol=1e-4)
def test_list(self, device, dtype):
height, width = 3, 4
grid = kornia.utils.create_meshgrid(height, width, normalized_coordinates=True, device=device).to(dtype=dtype)
grid = grid.contiguous().view(-1, 2)
expected = kornia.utils.create_meshgrid(height, width, normalized_coordinates=False, device=device).to(
dtype=dtype
)
expected = expected.contiguous().view(-1, 2)
grid_norm = kornia.geometry.conversions.denormalize_pixel_coordinates(grid, height, width)
assert_close(grid_norm, expected, atol=1e-4, rtol=1e-4)
def test_jit(self, device, dtype):
op = kornia.geometry.conversions.denormalize_pixel_coordinates
op_script = torch.jit.script(op)
height, width = 3, 4
grid = kornia.utils.create_meshgrid(height, width, normalized_coordinates=True, device=device).to(dtype=dtype)
actual = op_script(grid, height, width)
expected = op(grid, height, width)
assert_close(actual, expected)