|
import pytest |
|
import torch |
|
from torch.autograd import gradcheck |
|
|
|
import kornia |
|
import kornia.testing as utils |
|
from kornia.testing import assert_close |
|
|
|
|
|
class TestCanny: |
|
def test_shape(self, device, dtype): |
|
inp = torch.zeros(1, 3, 4, 4, device=device, dtype=dtype) |
|
|
|
canny = kornia.filters.Canny() |
|
magnitude, edges = canny(inp) |
|
|
|
assert magnitude.shape == (1, 1, 4, 4) |
|
assert edges.shape == (1, 1, 4, 4) |
|
|
|
def test_shape_batch(self, device, dtype): |
|
batch_size = 2 |
|
inp = torch.zeros(batch_size, 3, 4, 4, device=device, dtype=dtype) |
|
|
|
canny = kornia.filters.Canny() |
|
magnitude, edges = canny(inp) |
|
|
|
assert magnitude.shape == (batch_size, 1, 4, 4) |
|
assert edges.shape == (batch_size, 1, 4, 4) |
|
|
|
def test_noncontiguous(self, device, dtype): |
|
batch_size = 3 |
|
inp = torch.rand(3, 5, 5, device=device, dtype=dtype).expand(batch_size, -1, -1, -1) |
|
|
|
magnitude, edges = kornia.filters.canny(inp) |
|
|
|
assert inp.is_contiguous() is False |
|
|
|
assert magnitude.is_contiguous() |
|
assert edges.is_contiguous() |
|
|
|
assert magnitude.shape == (batch_size, 1, 5, 5) |
|
assert edges.shape == (batch_size, 1, 5, 5) |
|
|
|
def test_magnitude(self, device, dtype): |
|
inp = torch.tensor( |
|
[ |
|
[ |
|
[ |
|
[0.0, 0.0, 0.0, 0.0, 0.0], |
|
[0.0, 0.0, 1.0, 0.0, 0.0], |
|
[0.0, 1.0, 1.0, 1.0, 0.0], |
|
[0.0, 0.0, 1.0, 0.0, 0.0], |
|
[0.0, 0.0, 0.0, 0.0, 0.0], |
|
] |
|
] |
|
], |
|
device=device, |
|
dtype=dtype, |
|
) |
|
|
|
expected_magnitude = torch.tensor( |
|
[ |
|
[ |
|
[ |
|
[0.0, 0.0, 0.0, 0.0, 0.0], |
|
[0.0, 1.2458, 0.9672, 1.2458, 0.0], |
|
[0.0, 0.9672, 0.0, 0.9672, 0.0], |
|
[0.0, 1.2458, 0.9672, 1.2458, 0.0], |
|
[0.0, 0.0, 0.0, 0.0, 0.0], |
|
] |
|
] |
|
], |
|
device=device, |
|
dtype=dtype, |
|
) |
|
|
|
expected_edges = torch.tensor( |
|
[ |
|
[ |
|
[ |
|
[0.0, 0.0, 0.0, 0.0, 0.0], |
|
[0.0, 1.0, 1.0, 1.0, 0.0], |
|
[0.0, 1.0, 0.0, 1.0, 0.0], |
|
[0.0, 1.0, 1.0, 1.0, 0.0], |
|
[0.0, 0.0, 0.0, 0.0, 0.0], |
|
] |
|
] |
|
], |
|
device=device, |
|
dtype=dtype, |
|
) |
|
|
|
magnitude, edges = kornia.filters.canny(inp) |
|
|
|
tol_val: float = utils._get_precision(device, dtype) |
|
assert_close(magnitude, expected_magnitude, rtol=tol_val, atol=tol_val) |
|
assert_close(edges, expected_edges, rtol=tol_val, atol=tol_val) |
|
|
|
def test_magnitude_hyst(self, device, dtype): |
|
inp = torch.tensor( |
|
[ |
|
[ |
|
[ |
|
[0.5, 0.4, 0.5, 0.45, 0.1], |
|
[0.3, 0.2, 0.3, 0.0, 0.3], |
|
[0.5, 1.0, 1.0, 0.6, 0.75], |
|
[0.2, 0.4, 0.6, 0.0, 0.5], |
|
[0.1, 0.35, 0.35, 0.26, 0.1], |
|
] |
|
] |
|
], |
|
device=device, |
|
dtype=dtype, |
|
) |
|
|
|
expected_magnitude = torch.tensor( |
|
[ |
|
[ |
|
[ |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
[0.4858, 0.5594, 0.6878, 0.6977, 0.5602], |
|
[0.1129, 0.0000, 0.0000, 0.4531, 0.0000], |
|
[0.6115, 0.5859, 0.6110, 0.6766, 0.5160], |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
] |
|
] |
|
], |
|
device=device, |
|
dtype=dtype, |
|
) |
|
|
|
expected_edges = torch.tensor( |
|
[ |
|
[ |
|
[ |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
[1.0000, 1.0000, 1.0000, 1.0000, 1.0000], |
|
[1.0000, 0.0000, 0.0000, 1.0000, 0.0000], |
|
[1.0000, 1.0000, 1.0000, 1.0000, 1.0000], |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
] |
|
] |
|
], |
|
device=device, |
|
dtype=dtype, |
|
) |
|
|
|
magnitude, edges = kornia.filters.canny(inp, hysteresis=True) |
|
|
|
tol_val: float = utils._get_precision(device, dtype) |
|
assert_close(magnitude, expected_magnitude, rtol=tol_val, atol=tol_val) |
|
assert_close(edges, expected_edges, rtol=tol_val, atol=tol_val) |
|
|
|
def test_magnitude_hyst_false(self, device, dtype): |
|
inp = torch.tensor( |
|
[ |
|
[ |
|
[ |
|
[0.5, 0.4, 0.5, 0.45, 0.1], |
|
[0.3, 0.2, 0.3, 0.0, 0.3], |
|
[0.5, 1.0, 1.0, 0.6, 0.75], |
|
[0.2, 0.4, 0.6, 0.0, 0.5], |
|
[0.1, 0.35, 0.35, 0.26, 0.1], |
|
] |
|
] |
|
], |
|
device=device, |
|
dtype=dtype, |
|
) |
|
|
|
expected_magnitude = torch.tensor( |
|
[ |
|
[ |
|
[ |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
[0.4858, 0.5594, 0.6878, 0.6977, 0.5602], |
|
[0.1129, 0.0000, 0.0000, 0.4531, 0.0000], |
|
[0.6115, 0.5859, 0.6110, 0.6766, 0.5160], |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
] |
|
] |
|
], |
|
device=device, |
|
dtype=dtype, |
|
) |
|
|
|
expected_edges = torch.tensor( |
|
[ |
|
[ |
|
[ |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
[1.0000, 1.0000, 1.0000, 1.0000, 1.0000], |
|
[0.5000, 0.0000, 0.0000, 1.0000, 0.0000], |
|
[1.0000, 1.0000, 1.0000, 1.0000, 1.0000], |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
] |
|
] |
|
], |
|
device=device, |
|
dtype=dtype, |
|
) |
|
|
|
magnitude, edges = kornia.filters.canny(inp, hysteresis=False) |
|
|
|
tol_val: float = utils._get_precision(device, dtype) |
|
assert_close(magnitude, expected_magnitude, rtol=tol_val, atol=tol_val) |
|
assert_close(edges, expected_edges, rtol=tol_val, atol=tol_val) |
|
|
|
def test_magnitude_threshold(self, device, dtype): |
|
inp = torch.tensor( |
|
[ |
|
[ |
|
[ |
|
[0.5, 0.4, 0.5, 0.45, 0.1], |
|
[0.3, 0.2, 0.3, 0.0, 0.3], |
|
[0.5, 1.0, 1.0, 0.6, 0.75], |
|
[0.2, 0.4, 0.6, 0.0, 0.5], |
|
[0.1, 0.35, 0.35, 0.26, 0.1], |
|
] |
|
] |
|
], |
|
device=device, |
|
dtype=dtype, |
|
) |
|
|
|
expected_magnitude = torch.tensor( |
|
[ |
|
[ |
|
[ |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
[0.4858, 0.5594, 0.6878, 0.6977, 0.5602], |
|
[0.1129, 0.0000, 0.0000, 0.4531, 0.0000], |
|
[0.6115, 0.5859, 0.6110, 0.6766, 0.5160], |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
] |
|
] |
|
], |
|
device=device, |
|
dtype=dtype, |
|
) |
|
|
|
expected_edges = torch.tensor( |
|
[ |
|
[ |
|
[ |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000], |
|
] |
|
] |
|
], |
|
device=device, |
|
dtype=dtype, |
|
) |
|
|
|
magnitude, edges = kornia.filters.canny(inp, low_threshold=0.3, high_threshold=0.9) |
|
|
|
tol_val: float = utils._get_precision(device, dtype) |
|
assert_close(magnitude, expected_magnitude, rtol=tol_val, atol=tol_val) |
|
assert_close(edges, expected_edges, rtol=tol_val, atol=tol_val) |
|
|
|
def test_gradcheck(self, device, dtype): |
|
if "cuda" in str(device): |
|
pytest.skip("RuntimeError: Backward is not reentrant, i.e., running backward,") |
|
batch_size, channels, height, width = 1, 1, 3, 4 |
|
img = torch.rand(batch_size, channels, height, width, device=device, dtype=dtype) |
|
img = utils.tensor_to_gradcheck_var(img) |
|
assert gradcheck(kornia.filters.canny, img, raise_exception=True) |
|
|
|
def test_jit(self, device, dtype): |
|
img = torch.rand(2, 3, 4, 5, device=device, dtype=dtype) |
|
op = kornia.filters.sobel |
|
op_script = torch.jit.script(op) |
|
expected_magnitude, expected_edges = op(img) |
|
actual_magnitude, actual_edges = op_script(img) |
|
assert_close(actual_magnitude, expected_magnitude) |
|
assert_close(actual_edges, expected_edges) |
|
|
|
def test_module(self, device, dtype): |
|
img = torch.rand(2, 3, 4, 5, device=device, dtype=dtype) |
|
op = kornia.filters.canny |
|
op_module = kornia.filters.Canny() |
|
expected_magnitude, expected_edges = op(img) |
|
actual_magnitude, actual_edges = op_module(img) |
|
assert_close(actual_magnitude, expected_magnitude) |
|
assert_close(actual_edges, expected_edges) |
|
|