compvis / test /geometry /test_conversions.py
Dexter's picture
Upload folder using huggingface_hub
36c95ba verified
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)