Files
wehub-resource-sync 3a2c66702c
Tests on CPU (scheduled) / check-skip (push) Has been cancelled
Tests on CPU (scheduled) / pre-tests (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-ubuntu (float32) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-ubuntu (float64) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.11, float32, 2.5.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.11, float32, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.11, float64, 2.5.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.11, float64, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.12, float32, 2.5.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.12, float32, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.12, float64, 2.5.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.12, float64, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.13, float32, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.13, float64, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-mac (3.11, float32, 2.5.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-mac (3.11, float32, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-mac (3.12, float32, 2.5.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-mac (3.12, float32, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-mac (3.13, float32, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / coverage (push) Has been cancelled
Tests on CPU (scheduled) / typing (push) Has been cancelled
Tests on CPU (scheduled) / tutorials (push) Has been cancelled
Tests on CPU (scheduled) / docs (push) Has been cancelled
Lint / TOML Format (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:49:27 +08:00

243 lines
9.6 KiB
Python

# LICENSE HEADER MANAGED BY add-license-header
#
# Copyright 2018 Kornia Team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import pytest
import torch
from torch.autograd import gradcheck
from kornia.geometry.line import ParametrizedLine, fit_line
from kornia.geometry.plane import Hyperplane
from testing.base import BaseTester, assert_close
class TestParametrizedLine(BaseTester):
def test_smoke(self, device, dtype):
p0 = torch.tensor([0.0, 0.0], device=device, dtype=dtype)
d0 = torch.tensor([1.0, 0.0], device=device, dtype=dtype)
l0 = ParametrizedLine(p0, d0)
self.assert_close(l0.origin, p0)
self.assert_close(l0.direction, d0)
assert l0.dim() == 2
def test_through(self, device, dtype):
p0 = torch.tensor([-1.0, -1.0], device=device, dtype=dtype)
p1 = torch.tensor([1.0, 1.0], device=device, dtype=dtype)
l1 = ParametrizedLine.through(p0, p1)
direction_expected = torch.tensor([0.7071, 0.7071], device=device, dtype=dtype)
self.assert_close(l1.origin, p0)
self.assert_close(l1.direction, direction_expected)
def test_point_at(self, device, dtype):
p0 = torch.tensor([0.0, 0.0], device=device, dtype=dtype)
p1 = torch.tensor([1.0, 0.0], device=device, dtype=dtype)
l1 = ParametrizedLine.through(p0, p1)
self.assert_close(l1.point_at(0.0), torch.tensor([0.0, 0.0], device=device, dtype=dtype))
self.assert_close(l1.point_at(0.5), torch.tensor([0.5, 0.0], device=device, dtype=dtype))
self.assert_close(l1.point_at(1.0), torch.tensor([1.0, 0.0], device=device, dtype=dtype))
def test_projection1(self, device, dtype):
p0 = torch.tensor([0.0, 0.0], device=device, dtype=dtype)
p1 = torch.tensor([1.0, 0.0], device=device, dtype=dtype)
p2 = torch.tensor([0.5, 0.5], device=device, dtype=dtype)
p3_expected = torch.tensor([0.5, 0.0], device=device, dtype=dtype)
l1 = ParametrizedLine.through(p0, p1)
p3 = l1.projection(p2)
self.assert_close(p3, p3_expected)
def test_projection2(self, device, dtype):
p0 = torch.tensor([0.0, 0.0], device=device, dtype=dtype)
p1 = torch.tensor([0.0, 1.0], device=device, dtype=dtype)
p2 = torch.tensor([0.5, 0.5], device=device, dtype=dtype)
p3_expected = torch.tensor([0.0, 0.5], device=device, dtype=dtype)
l1 = ParametrizedLine.through(p0, p1)
p3 = l1.projection(p2)
self.assert_close(p3, p3_expected)
def test_projection(self, device, dtype):
p0 = torch.tensor([0.0, 0.0], device=device, dtype=dtype)
p1 = torch.tensor([1.0, 0.0], device=device, dtype=dtype)
l1 = ParametrizedLine.through(p0, p1)
point = torch.tensor([1.0, 2.0], device=device, dtype=dtype)
point_projection = torch.tensor([1.0, 0.0], device=device, dtype=dtype)
self.assert_close(l1.projection(point), point_projection)
def test_distance(self, device, dtype):
p0 = torch.tensor([0.0, 0.0], device=device, dtype=dtype)
p1 = torch.tensor([1.0, 0.0], device=device, dtype=dtype)
l1 = ParametrizedLine.through(p0, p1)
point = torch.tensor([1.0, 4.0], device=device, dtype=dtype)
distance_expected = torch.tensor(4.0, device=device, dtype=dtype)
self.assert_close(l1.distance(point), distance_expected)
def test_squared_distance(self, device, dtype):
p0 = torch.tensor([0.0, 0.0], device=device, dtype=dtype)
p1 = torch.tensor([1.0, 0.0], device=device, dtype=dtype)
l1 = ParametrizedLine.through(p0, p1)
point = torch.tensor([1.0, 4.0], device=device, dtype=dtype)
distance_expected = torch.tensor(16.0, device=device, dtype=dtype)
self.assert_close(l1.squared_distance(point), distance_expected)
def test_instersect_plane(self, device, dtype):
p0 = torch.tensor([0.0, 0.0, 0.0], device=device, dtype=dtype)
p1 = torch.tensor([1.0, 0.0, 0.0], device=device, dtype=dtype)
l1 = ParametrizedLine.through(p0, p1)
v0 = torch.tensor([3.0, 0.0, 1.0], device=device, dtype=dtype)
v1 = torch.tensor([3.0, 1.0, 0.0], device=device, dtype=dtype)
v2 = torch.tensor([3.0, 0.0, -1.0], device=device, dtype=dtype)
pl0 = Hyperplane.through(v0, v1, v2)
lmbda, point = l1.intersect(pl0)
expected_point = torch.tensor([3.0, 0.0, 0.0], device=device, dtype=dtype)
expected_lambda = torch.tensor(3.0, device=device, dtype=dtype)
self.assert_close(lmbda, expected_lambda)
self.assert_close(point, expected_point)
@pytest.mark.skip(reason="not implemented yet")
def test_cardinality(self, device, dtype):
pass
@pytest.mark.skip(reason="not implemented yet")
def test_jit(self, device, dtype):
pass
@pytest.mark.skip(reason="not implemented yet")
def test_exception(self, device, dtype):
pass
@pytest.mark.skip(reason="not implemented yet")
def test_module(self, device, dtype):
pass
@pytest.mark.skip(reason="not implemented yet")
def test_gradcheck(self, device):
pass
class TestFitLine(BaseTester):
@pytest.mark.parametrize("B", (1, 2))
@pytest.mark.parametrize("D", (2, 3, 4))
def test_smoke(self, device, dtype, B, D):
N: int = 10 # num points
points = torch.ones(B, N, D, device=device, dtype=dtype)
line = fit_line(points)
assert isinstance(line, ParametrizedLine)
assert line.origin.shape == (B, D)
assert line.direction.shape == (B, D)
assert_close(line.origin, line[0])
assert_close(line.direction, line[1])
origin, direction = fit_line(points)
assert_close(line.origin, origin)
assert_close(line.direction, direction)
def test_fit_line2(self, device, dtype):
p0 = torch.tensor([0.0, 0.0], device=device, dtype=dtype)
p1 = torch.tensor([1.0, 1.0], device=device, dtype=dtype)
l1 = ParametrizedLine.through(p0, p1)
num_points: int = 10
pts = []
for t in torch.linspace(-10, 10, num_points):
p2 = l1.point_at(t)
pts.append(p2)
pts = torch.stack(pts)
line_est = fit_line(pts[None])
dir_exp = torch.tensor([0.7071, 0.7071], device=device, dtype=dtype)
# NOTE: for some reason the result in c[u/cuda differs
angle_est = torch.nn.functional.cosine_similarity(line_est.direction, dir_exp, -1)
angle_exp = torch.tensor([1.0], device=device, dtype=dtype)
self.assert_close(angle_est.abs(), angle_exp)
def test_fit_line3(self, device, dtype):
p0 = torch.tensor([0.0, 0.0, 0.0], device=device, dtype=dtype)
p1 = torch.tensor([1.0, 1.0, 1.0], device=device, dtype=dtype)
l1 = ParametrizedLine.through(p0, p1)
num_points: int = 10
pts = []
for t in torch.linspace(-10, 10, num_points):
p2 = l1.point_at(t)
pts.append(p2)
pts = torch.stack(pts)
line_est = fit_line(pts[None])
dir_exp = torch.tensor([0.7071, 0.7071, 0.7071], device=device, dtype=dtype)
# NOTE: result differs with the sign between cpu/cuda
angle_est = torch.nn.functional.cosine_similarity(line_est.direction, dir_exp, -1)
angle_exp = torch.tensor([1.0], device=device, dtype=dtype)
self.assert_close(angle_est.abs(), angle_exp)
def test_fit_line_weighted(self, device, dtype):
p0 = torch.tensor([0.0, 0.0], device=device, dtype=dtype)
p1 = torch.tensor([1.0, 1.0], device=device, dtype=dtype)
l1 = ParametrizedLine.through(p0, p1)
num_points = 20
ts = torch.linspace(-10, 10, num_points)
points = torch.stack([l1.point_at(t) for t in ts])
noise = torch.randn_like(points) * 0.05
points_noisy = points + noise
distances = torch.norm(points, dim=1)
weights = torch.exp(-distances * 0.2)
weights = weights / weights.max()
line_est = fit_line(points_noisy[None], weights=weights[None])
expected_dir = torch.tensor([0.7071, 0.7071], device=device, dtype=dtype)
expected_dir = expected_dir / expected_dir.norm()
angle_est = torch.nn.functional.cosine_similarity(line_est.direction, expected_dir, dim=-1)
assert angle_est.abs() > 0.998
@pytest.mark.skip(reason="numerical do not match with analytical")
def test_gradcheck(self, device):
def proxy_func(pts, weights):
line = fit_line(pts, weights)
return line.projection(pts[:, 0].T)
pts = torch.rand(1, 3, 2, device=device, dtype=torch.float64, requires_grad=True)
weights = torch.rand(1, 3, device=device, dtype=torch.float64, requires_grad=False)
assert gradcheck(proxy_func, (pts, weights), raise_exception=True)
@pytest.mark.skip(reason="not implemented yet")
def test_cardinality(self, device, dtype):
pass
@pytest.mark.skip(reason="not implemented yet")
def test_jit(self, device, dtype):
pass
@pytest.mark.skip(reason="not implemented yet")
def test_exception(self, device, dtype):
pass
@pytest.mark.skip(reason="not implemented yet")
def test_module(self, device, dtype):
pass