update
This commit is contained in:
0
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/__init__.py
vendored
Normal file
0
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/__init__.py
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/__pycache__/__init__.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/__pycache__/__init__.cpython-312.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/__pycache__/test_geometric.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/__pycache__/test_geometric.cpython-312.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/__pycache__/test_integral.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/__pycache__/test_integral.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/__pycache__/test_pyramids.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/__pycache__/test_pyramids.cpython-312.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/__pycache__/test_warps.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/__pycache__/test_warps.cpython-312.pyc
vendored
Normal file
Binary file not shown.
13
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_finite_radon_transform.py
vendored
Normal file
13
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_finite_radon_transform.py
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import numpy as np
|
||||
|
||||
from skimage.transform import frt2, ifrt2
|
||||
|
||||
|
||||
def test_frt():
|
||||
SIZE = 59 # must be prime to ensure that f inverse is unique
|
||||
|
||||
# Generate a test image
|
||||
L = np.tri(SIZE, dtype=np.int32) + np.tri(SIZE, dtype=np.int32)[::-1]
|
||||
f = frt2(L)
|
||||
fi = ifrt2(f)
|
||||
assert np.array_equal(L, fi)
|
||||
1078
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_geometric.py
vendored
Normal file
1078
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_geometric.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
635
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_hough_transform.py
vendored
Normal file
635
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_hough_transform.py
vendored
Normal file
@@ -0,0 +1,635 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
from numpy.testing import assert_almost_equal, assert_equal
|
||||
|
||||
from skimage import data, transform
|
||||
from skimage._shared.testing import run_in_parallel
|
||||
from skimage.draw import circle_perimeter, ellipse_perimeter, line
|
||||
|
||||
|
||||
@run_in_parallel()
|
||||
def test_hough_line():
|
||||
# Generate a test image
|
||||
img = np.zeros((100, 150), dtype=int)
|
||||
rr, cc = line(60, 130, 80, 10)
|
||||
img[rr, cc] = 1
|
||||
|
||||
out, angles, d = transform.hough_line(img)
|
||||
|
||||
y, x = np.where(out == out.max())
|
||||
dist = d[y[0]]
|
||||
theta = angles[x[0]]
|
||||
|
||||
assert_almost_equal(dist, 80.0, 1)
|
||||
assert_almost_equal(theta, 1.41, 1)
|
||||
|
||||
|
||||
def test_hough_line_angles():
|
||||
img = np.zeros((10, 10))
|
||||
img[0, 0] = 1
|
||||
|
||||
out, angles, d = transform.hough_line(img, np.linspace(0, 360, 10))
|
||||
|
||||
assert_equal(len(angles), 10)
|
||||
|
||||
|
||||
def test_hough_line_bad_input():
|
||||
img = np.zeros(100)
|
||||
img[10] = 1
|
||||
|
||||
# Expected error, img must be 2D
|
||||
with pytest.raises(ValueError):
|
||||
transform.hough_line(img, np.linspace(0, 360, 10))
|
||||
|
||||
|
||||
def test_probabilistic_hough():
|
||||
# Generate a test image
|
||||
img = np.zeros((100, 100), dtype=int)
|
||||
for i in range(25, 75):
|
||||
img[100 - i, i] = 100
|
||||
img[i, i] = 100
|
||||
|
||||
# decrease default theta sampling because similar orientations may confuse
|
||||
# as mentioned in article of Galambos et al
|
||||
theta = np.linspace(0, np.pi, 45)
|
||||
lines = transform.probabilistic_hough_line(
|
||||
img, threshold=10, line_length=10, line_gap=1, theta=theta
|
||||
)
|
||||
# sort the lines according to the x-axis
|
||||
sorted_lines = []
|
||||
for ln in lines:
|
||||
ln = list(ln)
|
||||
ln.sort(key=lambda x: x[0])
|
||||
sorted_lines.append(ln)
|
||||
|
||||
assert [(25, 75), (74, 26)] in sorted_lines
|
||||
assert [(25, 25), (74, 74)] in sorted_lines
|
||||
|
||||
# Execute with default theta
|
||||
transform.probabilistic_hough_line(img, line_length=10, line_gap=3)
|
||||
|
||||
|
||||
def test_probabilistic_hough_seed():
|
||||
# Load image that is likely to give a randomly varying number of lines
|
||||
image = data.checkerboard()
|
||||
|
||||
# Use constant seed to ensure a deterministic output
|
||||
lines = transform.probabilistic_hough_line(
|
||||
image, threshold=50, line_length=50, line_gap=1, rng=41537233
|
||||
)
|
||||
assert len(lines) == 56
|
||||
|
||||
|
||||
def test_probabilistic_hough_bad_input():
|
||||
img = np.zeros(100)
|
||||
img[10] = 1
|
||||
|
||||
# Expected error, img must be 2D
|
||||
with pytest.raises(ValueError):
|
||||
transform.probabilistic_hough_line(img)
|
||||
|
||||
|
||||
def test_hough_line_peaks():
|
||||
img = np.zeros((100, 150), dtype=int)
|
||||
rr, cc = line(60, 130, 80, 10)
|
||||
img[rr, cc] = 1
|
||||
|
||||
out, angles, d = transform.hough_line(img)
|
||||
|
||||
out, theta, dist = transform.hough_line_peaks(out, angles, d)
|
||||
|
||||
assert_equal(len(dist), 1)
|
||||
assert_almost_equal(dist[0], 81.0, 1)
|
||||
assert_almost_equal(theta[0], 1.41, 1)
|
||||
|
||||
|
||||
def test_hough_line_peaks_ordered():
|
||||
# Regression test per PR #1421
|
||||
testim = np.zeros((256, 64), dtype=bool)
|
||||
|
||||
testim[50:100, 20] = True
|
||||
testim[20:225, 25] = True
|
||||
testim[15:35, 50] = True
|
||||
testim[1:-1, 58] = True
|
||||
|
||||
hough_space, angles, dists = transform.hough_line(testim)
|
||||
|
||||
hspace, _, _ = transform.hough_line_peaks(hough_space, angles, dists)
|
||||
assert hspace[0] > hspace[1]
|
||||
|
||||
|
||||
def test_hough_line_peaks_single_line():
|
||||
# Regression test for gh-6187, gh-4129
|
||||
|
||||
# create an empty test image
|
||||
img = np.zeros((100, 100), dtype=bool)
|
||||
# draw a horizontal line into our test image
|
||||
img[30, :] = 1
|
||||
|
||||
hough_space, angles, dist = transform.hough_line(img)
|
||||
|
||||
best_h_space, best_angles, best_dist = transform.hough_line_peaks(
|
||||
hough_space, angles, dist
|
||||
)
|
||||
assert len(best_angles) == 1
|
||||
assert len(best_dist) == 1
|
||||
expected_angle = -np.pi / 2
|
||||
expected_dist = -30
|
||||
assert abs(best_angles[0] - expected_angle) < 0.01
|
||||
assert abs(best_dist[0] - expected_dist) < 0.01
|
||||
|
||||
|
||||
def test_hough_line_peaks_dist():
|
||||
img = np.zeros((100, 100), dtype=bool)
|
||||
img[:, 30] = True
|
||||
img[:, 40] = True
|
||||
hspace, angles, dists = transform.hough_line(img)
|
||||
assert (
|
||||
len(transform.hough_line_peaks(hspace, angles, dists, min_distance=5)[0]) == 2
|
||||
)
|
||||
assert (
|
||||
len(transform.hough_line_peaks(hspace, angles, dists, min_distance=15)[0]) == 1
|
||||
)
|
||||
|
||||
|
||||
def test_hough_line_peaks_angle():
|
||||
check_hough_line_peaks_angle()
|
||||
|
||||
|
||||
def check_hough_line_peaks_angle():
|
||||
img = np.zeros((100, 100), dtype=bool)
|
||||
img[:, 0] = True
|
||||
img[0, :] = True
|
||||
|
||||
hspace, angles, dists = transform.hough_line(img)
|
||||
assert len(transform.hough_line_peaks(hspace, angles, dists, min_angle=45)[0]) == 2
|
||||
assert len(transform.hough_line_peaks(hspace, angles, dists, min_angle=90)[0]) == 1
|
||||
|
||||
theta = np.linspace(0, np.pi, 100)
|
||||
hspace, angles, dists = transform.hough_line(img, theta)
|
||||
assert len(transform.hough_line_peaks(hspace, angles, dists, min_angle=45)[0]) == 2
|
||||
assert len(transform.hough_line_peaks(hspace, angles, dists, min_angle=90)[0]) == 1
|
||||
|
||||
theta = np.linspace(np.pi / 3, 4.0 / 3 * np.pi, 100)
|
||||
hspace, angles, dists = transform.hough_line(img, theta)
|
||||
assert len(transform.hough_line_peaks(hspace, angles, dists, min_angle=45)[0]) == 2
|
||||
assert len(transform.hough_line_peaks(hspace, angles, dists, min_angle=90)[0]) == 1
|
||||
|
||||
|
||||
def test_hough_line_peaks_num():
|
||||
img = np.zeros((100, 100), dtype=bool)
|
||||
img[:, 30] = True
|
||||
img[:, 40] = True
|
||||
hspace, angles, dists = transform.hough_line(img)
|
||||
assert (
|
||||
len(
|
||||
transform.hough_line_peaks(
|
||||
hspace, angles, dists, min_distance=0, min_angle=0, num_peaks=1
|
||||
)[0]
|
||||
)
|
||||
== 1
|
||||
)
|
||||
|
||||
|
||||
def test_hough_line_peaks_zero_input():
|
||||
# Test to make sure empty input doesn't cause a failure
|
||||
img = np.zeros((100, 100), dtype='uint8')
|
||||
theta = np.linspace(0, np.pi, 100)
|
||||
hspace, angles, dists = transform.hough_line(img, theta)
|
||||
h, a, d = transform.hough_line_peaks(hspace, angles, dists)
|
||||
assert_equal(a, np.array([]))
|
||||
|
||||
|
||||
def test_hough_line_peaks_single_angle():
|
||||
# Regression test for gh-4814
|
||||
# This code snippet used to raise an IndexError
|
||||
img = np.random.random((100, 100))
|
||||
tested_angles = np.array([np.pi / 2])
|
||||
h, theta, d = transform.hough_line(img, theta=tested_angles)
|
||||
accum, angles, dists = transform.hough_line_peaks(h, theta, d, threshold=2)
|
||||
|
||||
|
||||
@run_in_parallel()
|
||||
def test_hough_circle():
|
||||
# Prepare picture
|
||||
img = np.zeros((120, 100), dtype=int)
|
||||
radius = 20
|
||||
x_0, y_0 = (99, 50)
|
||||
y, x = circle_perimeter(y_0, x_0, radius)
|
||||
img[x, y] = 1
|
||||
|
||||
out1 = transform.hough_circle(img, radius)
|
||||
out2 = transform.hough_circle(img, [radius])
|
||||
assert_equal(out1, out2)
|
||||
out = transform.hough_circle(img, np.array([radius], dtype=np.intp))
|
||||
assert_equal(out, out1)
|
||||
x, y = np.where(out[0] == out[0].max())
|
||||
assert_equal(x[0], x_0)
|
||||
assert_equal(y[0], y_0)
|
||||
|
||||
|
||||
def test_hough_circle_extended():
|
||||
# Prepare picture
|
||||
# The circle center is outside the image
|
||||
img = np.zeros((100, 100), dtype=int)
|
||||
radius = 20
|
||||
x_0, y_0 = (-5, 50)
|
||||
y, x = circle_perimeter(y_0, x_0, radius)
|
||||
img[x[np.where(x > 0)], y[np.where(x > 0)]] = 1
|
||||
|
||||
out = transform.hough_circle(
|
||||
img, np.array([radius], dtype=np.intp), full_output=True
|
||||
)
|
||||
|
||||
x, y = np.where(out[0] == out[0].max())
|
||||
# Offset for x_0, y_0
|
||||
assert_equal(x[0], x_0 + radius)
|
||||
assert_equal(y[0], y_0 + radius)
|
||||
|
||||
|
||||
def test_hough_circle_peaks():
|
||||
x_0, y_0, rad_0 = (99, 50, 20)
|
||||
img = np.zeros((120, 100), dtype=int)
|
||||
y, x = circle_perimeter(y_0, x_0, rad_0)
|
||||
img[x, y] = 1
|
||||
|
||||
x_1, y_1, rad_1 = (49, 60, 30)
|
||||
y, x = circle_perimeter(y_1, x_1, rad_1)
|
||||
img[x, y] = 1
|
||||
|
||||
radii = [rad_0, rad_1]
|
||||
hspaces = transform.hough_circle(img, radii)
|
||||
out = transform.hough_circle_peaks(
|
||||
hspaces,
|
||||
radii,
|
||||
min_xdistance=1,
|
||||
min_ydistance=1,
|
||||
threshold=None,
|
||||
num_peaks=np.inf,
|
||||
total_num_peaks=np.inf,
|
||||
)
|
||||
s = np.argsort(out[3]) # sort by radii
|
||||
assert_equal(out[1][s], np.array([y_0, y_1]))
|
||||
assert_equal(out[2][s], np.array([x_0, x_1]))
|
||||
assert_equal(out[3][s], np.array([rad_0, rad_1]))
|
||||
|
||||
|
||||
def test_hough_circle_peaks_total_peak():
|
||||
img = np.zeros((120, 100), dtype=int)
|
||||
|
||||
x_0, y_0, rad_0 = (99, 50, 20)
|
||||
y, x = circle_perimeter(y_0, x_0, rad_0)
|
||||
img[x, y] = 1
|
||||
|
||||
x_1, y_1, rad_1 = (49, 60, 30)
|
||||
y, x = circle_perimeter(y_1, x_1, rad_1)
|
||||
img[x, y] = 1
|
||||
|
||||
radii = [rad_0, rad_1]
|
||||
hspaces = transform.hough_circle(img, radii)
|
||||
out = transform.hough_circle_peaks(
|
||||
hspaces,
|
||||
radii,
|
||||
min_xdistance=1,
|
||||
min_ydistance=1,
|
||||
threshold=None,
|
||||
num_peaks=np.inf,
|
||||
total_num_peaks=1,
|
||||
)
|
||||
assert_equal(
|
||||
out[1][0],
|
||||
np.array(
|
||||
[
|
||||
y_1,
|
||||
]
|
||||
),
|
||||
)
|
||||
assert_equal(
|
||||
out[2][0],
|
||||
np.array(
|
||||
[
|
||||
x_1,
|
||||
]
|
||||
),
|
||||
)
|
||||
assert_equal(
|
||||
out[3][0],
|
||||
np.array(
|
||||
[
|
||||
rad_1,
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def test_hough_circle_peaks_min_distance():
|
||||
x_0, y_0, rad_0 = (50, 50, 20)
|
||||
img = np.zeros((120, 100), dtype=int)
|
||||
y, x = circle_perimeter(y_0, x_0, rad_0)
|
||||
img[x, y] = 1
|
||||
|
||||
x_1, y_1, rad_1 = (60, 60, 30)
|
||||
y, x = circle_perimeter(y_1, x_1, rad_1)
|
||||
# Add noise and create an imperfect circle to lower the peak in Hough space
|
||||
y[::2] += 1
|
||||
x[::2] += 1
|
||||
img[x, y] = 1
|
||||
|
||||
x_2, y_2, rad_2 = (70, 70, 20)
|
||||
y, x = circle_perimeter(y_2, x_2, rad_2)
|
||||
# Add noise and create an imperfect circle to lower the peak in Hough space
|
||||
y[::2] += 1
|
||||
x[::2] += 1
|
||||
img[x, y] = 1
|
||||
|
||||
radii = [rad_0, rad_1, rad_2]
|
||||
hspaces = transform.hough_circle(img, radii)
|
||||
out = transform.hough_circle_peaks(
|
||||
hspaces,
|
||||
radii,
|
||||
min_xdistance=15,
|
||||
min_ydistance=15,
|
||||
threshold=None,
|
||||
num_peaks=np.inf,
|
||||
total_num_peaks=np.inf,
|
||||
normalize=True,
|
||||
)
|
||||
|
||||
# The second circle is too close to the first one
|
||||
# and has a weaker peak in Hough space due to imperfectness.
|
||||
# Therefore it got removed.
|
||||
assert_equal(out[1], np.array([y_0, y_2]))
|
||||
assert_equal(out[2], np.array([x_0, x_2]))
|
||||
assert_equal(out[3], np.array([rad_0, rad_2]))
|
||||
|
||||
|
||||
def test_hough_circle_peaks_total_peak_and_min_distance():
|
||||
img = np.zeros((120, 120), dtype=int)
|
||||
cx = cy = [40, 50, 60, 70, 80]
|
||||
radii = range(20, 30, 2)
|
||||
for i in range(len(cx)):
|
||||
y, x = circle_perimeter(cy[i], cx[i], radii[i])
|
||||
img[x, y] = 1
|
||||
|
||||
hspaces = transform.hough_circle(img, radii)
|
||||
out = transform.hough_circle_peaks(
|
||||
hspaces,
|
||||
radii,
|
||||
min_xdistance=15,
|
||||
min_ydistance=15,
|
||||
threshold=None,
|
||||
num_peaks=np.inf,
|
||||
total_num_peaks=2,
|
||||
normalize=True,
|
||||
)
|
||||
|
||||
# 2nd (4th) circle is removed as it is close to 1st (3rd) oneself.
|
||||
# 5th is removed as total_num_peaks = 2
|
||||
assert_equal(out[1], np.array(cy[:4:2]))
|
||||
assert_equal(out[2], np.array(cx[:4:2]))
|
||||
assert_equal(out[3], np.array(radii[:4:2]))
|
||||
|
||||
|
||||
def test_hough_circle_peaks_normalize():
|
||||
x_0, y_0, rad_0 = (50, 50, 20)
|
||||
img = np.zeros((120, 100), dtype=int)
|
||||
y, x = circle_perimeter(y_0, x_0, rad_0)
|
||||
img[x, y] = 1
|
||||
|
||||
x_1, y_1, rad_1 = (60, 60, 30)
|
||||
y, x = circle_perimeter(y_1, x_1, rad_1)
|
||||
img[x, y] = 1
|
||||
|
||||
radii = [rad_0, rad_1]
|
||||
hspaces = transform.hough_circle(img, radii)
|
||||
out = transform.hough_circle_peaks(
|
||||
hspaces,
|
||||
radii,
|
||||
min_xdistance=15,
|
||||
min_ydistance=15,
|
||||
threshold=None,
|
||||
num_peaks=np.inf,
|
||||
total_num_peaks=np.inf,
|
||||
normalize=False,
|
||||
)
|
||||
|
||||
# Two perfect circles are close but the second one is bigger.
|
||||
# Therefore, it is picked due to its high peak.
|
||||
assert_equal(out[1], np.array([y_1]))
|
||||
assert_equal(out[2], np.array([x_1]))
|
||||
assert_equal(out[3], np.array([rad_1]))
|
||||
|
||||
|
||||
def test_hough_ellipse_zero_angle():
|
||||
img = np.zeros((25, 25), dtype=int)
|
||||
rx = 6
|
||||
ry = 8
|
||||
x0 = 12
|
||||
y0 = 15
|
||||
angle = 0
|
||||
rr, cc = ellipse_perimeter(y0, x0, ry, rx)
|
||||
img[rr, cc] = 1
|
||||
result = transform.hough_ellipse(img, threshold=9)
|
||||
best = result[-1]
|
||||
assert_equal(best[1], y0)
|
||||
assert_equal(best[2], x0)
|
||||
assert_almost_equal(best[3], ry, decimal=1)
|
||||
assert_almost_equal(best[4], rx, decimal=1)
|
||||
assert_equal(best[5], angle)
|
||||
# Check if I re-draw the ellipse, points are the same!
|
||||
# ie check API compatibility between hough_ellipse and ellipse_perimeter
|
||||
rr2, cc2 = ellipse_perimeter(
|
||||
y0, x0, int(best[3]), int(best[4]), orientation=best[5]
|
||||
)
|
||||
assert_equal(rr, rr2)
|
||||
assert_equal(cc, cc2)
|
||||
|
||||
|
||||
def test_hough_ellipse_non_zero_posangle1():
|
||||
# ry > rx, angle in [0:pi/2]
|
||||
img = np.zeros((30, 24), dtype=int)
|
||||
rx = 6
|
||||
ry = 12
|
||||
x0 = 10
|
||||
y0 = 15
|
||||
angle = np.pi / 1.35
|
||||
rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle)
|
||||
img[rr, cc] = 1
|
||||
result = transform.hough_ellipse(img, threshold=15, accuracy=3)
|
||||
result.sort(order='accumulator')
|
||||
best = result[-1]
|
||||
assert_almost_equal(best[1] / 100.0, y0 / 100.0, decimal=1)
|
||||
assert_almost_equal(best[2] / 100.0, x0 / 100.0, decimal=1)
|
||||
assert_almost_equal(best[3] / 10.0, ry / 10.0, decimal=1)
|
||||
assert_almost_equal(best[4] / 100.0, rx / 100.0, decimal=1)
|
||||
assert_almost_equal(best[5], angle, decimal=1)
|
||||
# Check if I re-draw the ellipse, points are the same!
|
||||
# ie check API compatibility between hough_ellipse and ellipse_perimeter
|
||||
rr2, cc2 = ellipse_perimeter(
|
||||
y0, x0, int(best[3]), int(best[4]), orientation=best[5]
|
||||
)
|
||||
assert_equal(rr, rr2)
|
||||
assert_equal(cc, cc2)
|
||||
|
||||
|
||||
def test_hough_ellipse_non_zero_posangle2():
|
||||
# ry < rx, angle in [0:pi/2]
|
||||
img = np.zeros((30, 24), dtype=int)
|
||||
rx = 12
|
||||
ry = 6
|
||||
x0 = 10
|
||||
y0 = 15
|
||||
angle = np.pi / 1.35
|
||||
rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle)
|
||||
img[rr, cc] = 1
|
||||
result = transform.hough_ellipse(img, threshold=15, accuracy=3)
|
||||
result.sort(order='accumulator')
|
||||
best = result[-1]
|
||||
assert_almost_equal(best[1] / 100.0, y0 / 100.0, decimal=1)
|
||||
assert_almost_equal(best[2] / 100.0, x0 / 100.0, decimal=1)
|
||||
assert_almost_equal(best[3] / 10.0, ry / 10.0, decimal=1)
|
||||
assert_almost_equal(best[4] / 100.0, rx / 100.0, decimal=1)
|
||||
assert_almost_equal(best[5], angle, decimal=1)
|
||||
# Check if I re-draw the ellipse, points are the same!
|
||||
# ie check API compatibility between hough_ellipse and ellipse_perimeter
|
||||
rr2, cc2 = ellipse_perimeter(
|
||||
y0, x0, int(best[3]), int(best[4]), orientation=best[5]
|
||||
)
|
||||
assert_equal(rr, rr2)
|
||||
assert_equal(cc, cc2)
|
||||
|
||||
|
||||
def test_hough_ellipse_non_zero_posangle3():
|
||||
# ry < rx, angle in [pi/2:pi]
|
||||
img = np.zeros((30, 24), dtype=int)
|
||||
rx = 12
|
||||
ry = 6
|
||||
x0 = 10
|
||||
y0 = 15
|
||||
angle = np.pi / 1.35 + np.pi / 2.0
|
||||
rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle)
|
||||
img[rr, cc] = 1
|
||||
result = transform.hough_ellipse(img, threshold=15, accuracy=3)
|
||||
result.sort(order='accumulator')
|
||||
best = result[-1]
|
||||
# Check if I re-draw the ellipse, points are the same!
|
||||
# ie check API compatibility between hough_ellipse and ellipse_perimeter
|
||||
rr2, cc2 = ellipse_perimeter(
|
||||
y0, x0, int(best[3]), int(best[4]), orientation=best[5]
|
||||
)
|
||||
assert_equal(rr, rr2)
|
||||
assert_equal(cc, cc2)
|
||||
|
||||
|
||||
def test_hough_ellipse_non_zero_posangle4():
|
||||
# ry < rx, angle in [pi:3pi/4]
|
||||
img = np.zeros((30, 24), dtype=int)
|
||||
rx = 12
|
||||
ry = 6
|
||||
x0 = 10
|
||||
y0 = 15
|
||||
angle = np.pi / 1.35 + np.pi
|
||||
rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle)
|
||||
img[rr, cc] = 1
|
||||
result = transform.hough_ellipse(img, threshold=15, accuracy=3)
|
||||
result.sort(order='accumulator')
|
||||
best = result[-1]
|
||||
# Check if I re-draw the ellipse, points are the same!
|
||||
# ie check API compatibility between hough_ellipse and ellipse_perimeter
|
||||
rr2, cc2 = ellipse_perimeter(
|
||||
y0, x0, int(best[3]), int(best[4]), orientation=best[5]
|
||||
)
|
||||
assert_equal(rr, rr2)
|
||||
assert_equal(cc, cc2)
|
||||
|
||||
|
||||
def test_hough_ellipse_non_zero_negangle1():
|
||||
# ry > rx, angle in [0:-pi/2]
|
||||
img = np.zeros((30, 24), dtype=int)
|
||||
rx = 6
|
||||
ry = 12
|
||||
x0 = 10
|
||||
y0 = 15
|
||||
angle = -np.pi / 1.35
|
||||
rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle)
|
||||
img[rr, cc] = 1
|
||||
result = transform.hough_ellipse(img, threshold=15, accuracy=3)
|
||||
result.sort(order='accumulator')
|
||||
best = result[-1]
|
||||
# Check if I re-draw the ellipse, points are the same!
|
||||
# ie check API compatibility between hough_ellipse and ellipse_perimeter
|
||||
rr2, cc2 = ellipse_perimeter(
|
||||
y0, x0, int(best[3]), int(best[4]), orientation=best[5]
|
||||
)
|
||||
assert_equal(rr, rr2)
|
||||
assert_equal(cc, cc2)
|
||||
|
||||
|
||||
def test_hough_ellipse_non_zero_negangle2():
|
||||
# ry < rx, angle in [0:-pi/2]
|
||||
img = np.zeros((30, 24), dtype=int)
|
||||
rx = 12
|
||||
ry = 6
|
||||
x0 = 10
|
||||
y0 = 15
|
||||
angle = -np.pi / 1.35
|
||||
rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle)
|
||||
img[rr, cc] = 1
|
||||
result = transform.hough_ellipse(img, threshold=15, accuracy=3)
|
||||
result.sort(order='accumulator')
|
||||
best = result[-1]
|
||||
# Check if I re-draw the ellipse, points are the same!
|
||||
# ie check API compatibility between hough_ellipse and ellipse_perimeter
|
||||
rr2, cc2 = ellipse_perimeter(
|
||||
y0, x0, int(best[3]), int(best[4]), orientation=best[5]
|
||||
)
|
||||
assert_equal(rr, rr2)
|
||||
assert_equal(cc, cc2)
|
||||
|
||||
|
||||
def test_hough_ellipse_non_zero_negangle3():
|
||||
# ry < rx, angle in [-pi/2:-pi]
|
||||
img = np.zeros((30, 24), dtype=int)
|
||||
rx = 12
|
||||
ry = 6
|
||||
x0 = 10
|
||||
y0 = 15
|
||||
angle = -np.pi / 1.35 - np.pi / 2.0
|
||||
rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle)
|
||||
img[rr, cc] = 1
|
||||
result = transform.hough_ellipse(img, threshold=15, accuracy=3)
|
||||
result.sort(order='accumulator')
|
||||
best = result[-1]
|
||||
# Check if I re-draw the ellipse, points are the same!
|
||||
# ie check API compatibility between hough_ellipse and ellipse_perimeter
|
||||
rr2, cc2 = ellipse_perimeter(
|
||||
y0, x0, int(best[3]), int(best[4]), orientation=best[5]
|
||||
)
|
||||
assert_equal(rr, rr2)
|
||||
assert_equal(cc, cc2)
|
||||
|
||||
|
||||
def test_hough_ellipse_non_zero_negangle4():
|
||||
# ry < rx, angle in [-pi:-3pi/4]
|
||||
img = np.zeros((30, 24), dtype=int)
|
||||
rx = 12
|
||||
ry = 6
|
||||
x0 = 10
|
||||
y0 = 15
|
||||
angle = -np.pi / 1.35 - np.pi
|
||||
rr, cc = ellipse_perimeter(y0, x0, ry, rx, orientation=angle)
|
||||
img[rr, cc] = 1
|
||||
result = transform.hough_ellipse(img, threshold=15, accuracy=3)
|
||||
result.sort(order='accumulator')
|
||||
best = result[-1]
|
||||
# Check if I re-draw the ellipse, points are the same!
|
||||
# ie check API compatibility between hough_ellipse and ellipse_perimeter
|
||||
rr2, cc2 = ellipse_perimeter(
|
||||
y0, x0, int(best[3]), int(best[4]), orientation=best[5]
|
||||
)
|
||||
assert_equal(rr, rr2)
|
||||
assert_equal(cc, cc2)
|
||||
|
||||
|
||||
def test_hough_ellipse_all_black_img():
|
||||
assert transform.hough_ellipse(np.zeros((100, 100))).shape == (0, 6)
|
||||
68
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_integral.py
vendored
Normal file
68
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_integral.py
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
from numpy.testing import assert_allclose, assert_equal
|
||||
|
||||
from skimage.transform import integral_image, integrate
|
||||
|
||||
|
||||
np.random.seed(0)
|
||||
x = (np.random.rand(50, 50) * 255).astype(np.uint8)
|
||||
s = integral_image(x)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'dtype', [np.float16, np.float32, np.float64, np.uint8, np.int32]
|
||||
)
|
||||
@pytest.mark.parametrize('dtype_as_kwarg', [False, True])
|
||||
def test_integral_image_validity(dtype, dtype_as_kwarg):
|
||||
rstate = np.random.default_rng(1234)
|
||||
dtype_kwarg = dtype if dtype_as_kwarg else None
|
||||
y = (rstate.random((20, 20)) * 255).astype(dtype)
|
||||
out = integral_image(y, dtype=dtype_kwarg)
|
||||
if y.dtype.kind == 'f':
|
||||
if dtype_as_kwarg:
|
||||
assert out.dtype == dtype
|
||||
rtol = 1e-3 if dtype == np.float16 else 1e-7
|
||||
assert_allclose(out[-1, -1], y.sum(dtype=np.float64), rtol=rtol)
|
||||
else:
|
||||
assert out.dtype == np.float64
|
||||
assert_allclose(out[-1, -1], y.sum(dtype=np.float64))
|
||||
else:
|
||||
assert out.dtype.kind == y.dtype.kind
|
||||
if not (dtype_as_kwarg and dtype == np.uint8):
|
||||
# omit check for dtype=uint8 case as it will overflow
|
||||
assert_equal(out[-1, -1], y.sum())
|
||||
|
||||
|
||||
def test_integrate_basic():
|
||||
assert_equal(x[12:24, 10:20].sum(), integrate(s, (12, 10), (23, 19)))
|
||||
assert_equal(x[:20, :20].sum(), integrate(s, (0, 0), (19, 19)))
|
||||
assert_equal(x[:20, 10:20].sum(), integrate(s, (0, 10), (19, 19)))
|
||||
assert_equal(x[10:20, :20].sum(), integrate(s, (10, 0), (19, 19)))
|
||||
|
||||
|
||||
def test_integrate_single():
|
||||
assert_equal(x[0, 0], integrate(s, (0, 0), (0, 0)))
|
||||
assert_equal(x[10, 10], integrate(s, (10, 10), (10, 10)))
|
||||
|
||||
|
||||
def test_vectorized_integrate():
|
||||
r0 = np.array([12, 0, 0, 10, 0, 10, 30])
|
||||
c0 = np.array([10, 0, 10, 0, 0, 10, 31])
|
||||
r1 = np.array([23, 19, 19, 19, 0, 10, 49])
|
||||
c1 = np.array([19, 19, 19, 19, 0, 10, 49])
|
||||
|
||||
expected = np.array(
|
||||
[
|
||||
x[12:24, 10:20].sum(),
|
||||
x[:20, :20].sum(),
|
||||
x[:20, 10:20].sum(),
|
||||
x[10:20, :20].sum(),
|
||||
x[0, 0],
|
||||
x[10, 10],
|
||||
x[30:, 31:].sum(),
|
||||
]
|
||||
)
|
||||
start_pts = [(r0[i], c0[i]) for i in range(len(r0))]
|
||||
end_pts = [(r1[i], c1[i]) for i in range(len(r0))]
|
||||
assert_equal(expected, integrate(s, start_pts, end_pts))
|
||||
210
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_pyramids.py
vendored
Normal file
210
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_pyramids.py
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
import math
|
||||
import warnings
|
||||
|
||||
import pytest
|
||||
import numpy as np
|
||||
from numpy.testing import assert_almost_equal, assert_array_equal, assert_equal
|
||||
|
||||
from skimage import data
|
||||
from skimage._shared.utils import _supported_float_type
|
||||
from skimage.transform import pyramids
|
||||
|
||||
|
||||
image = data.astronaut()
|
||||
image_gray = image[..., 0]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('channel_axis', [0, 1, -1])
|
||||
def test_pyramid_reduce_rgb(channel_axis):
|
||||
image = data.astronaut()
|
||||
rows, cols, dim = image.shape
|
||||
image = np.moveaxis(image, source=-1, destination=channel_axis)
|
||||
out_ = pyramids.pyramid_reduce(image, downscale=2, channel_axis=channel_axis)
|
||||
out = np.moveaxis(out_, channel_axis, -1)
|
||||
assert_array_equal(out.shape, (rows / 2, cols / 2, dim))
|
||||
|
||||
|
||||
def test_pyramid_reduce_gray():
|
||||
rows, cols = image_gray.shape
|
||||
out1 = pyramids.pyramid_reduce(image_gray, downscale=2, channel_axis=None)
|
||||
assert_array_equal(out1.shape, (rows / 2, cols / 2))
|
||||
assert_almost_equal(np.ptp(out1), 1.0, decimal=2)
|
||||
out2 = pyramids.pyramid_reduce(
|
||||
image_gray, downscale=2, channel_axis=None, preserve_range=True
|
||||
)
|
||||
assert_almost_equal(np.ptp(out2) / np.ptp(image_gray), 1.0, decimal=2)
|
||||
|
||||
|
||||
def test_pyramid_reduce_gray_defaults():
|
||||
rows, cols = image_gray.shape
|
||||
out1 = pyramids.pyramid_reduce(image_gray)
|
||||
assert_array_equal(out1.shape, (rows / 2, cols / 2))
|
||||
assert_almost_equal(np.ptp(out1), 1.0, decimal=2)
|
||||
out2 = pyramids.pyramid_reduce(image_gray, preserve_range=True)
|
||||
assert_almost_equal(np.ptp(out2) / np.ptp(image_gray), 1.0, decimal=2)
|
||||
|
||||
|
||||
def test_pyramid_reduce_nd():
|
||||
for ndim in [1, 2, 3, 4]:
|
||||
img = np.random.randn(*((8,) * ndim))
|
||||
out = pyramids.pyramid_reduce(img, downscale=2, channel_axis=None)
|
||||
expected_shape = np.asarray(img.shape) / 2
|
||||
assert_array_equal(out.shape, expected_shape)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('channel_axis', [0, 1, 2, -1, -2, -3])
|
||||
def test_pyramid_expand_rgb(channel_axis):
|
||||
image = data.astronaut()
|
||||
rows, cols, dim = image.shape
|
||||
image = np.moveaxis(image, source=-1, destination=channel_axis)
|
||||
out = pyramids.pyramid_expand(image, upscale=2, channel_axis=channel_axis)
|
||||
expected_shape = [rows * 2, cols * 2]
|
||||
expected_shape.insert(channel_axis % image.ndim, dim)
|
||||
assert_array_equal(out.shape, expected_shape)
|
||||
|
||||
|
||||
def test_pyramid_expand_gray():
|
||||
rows, cols = image_gray.shape
|
||||
out = pyramids.pyramid_expand(image_gray, upscale=2)
|
||||
assert_array_equal(out.shape, (rows * 2, cols * 2))
|
||||
|
||||
|
||||
def test_pyramid_expand_nd():
|
||||
for ndim in [1, 2, 3, 4]:
|
||||
img = np.random.randn(*((4,) * ndim))
|
||||
out = pyramids.pyramid_expand(img, upscale=2, channel_axis=None)
|
||||
expected_shape = np.asarray(img.shape) * 2
|
||||
assert_array_equal(out.shape, expected_shape)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('channel_axis', [0, 1, 2, -1, -2, -3])
|
||||
def test_build_gaussian_pyramid_rgb(channel_axis):
|
||||
image = data.astronaut()
|
||||
rows, cols, dim = image.shape
|
||||
image = np.moveaxis(image, source=-1, destination=channel_axis)
|
||||
pyramid = pyramids.pyramid_gaussian(image, downscale=2, channel_axis=channel_axis)
|
||||
for layer, out in enumerate(pyramid):
|
||||
layer_shape = [rows / 2**layer, cols / 2**layer]
|
||||
layer_shape.insert(channel_axis % image.ndim, dim)
|
||||
assert out.shape == tuple(layer_shape)
|
||||
|
||||
|
||||
def test_build_gaussian_pyramid_gray():
|
||||
rows, cols = image_gray.shape
|
||||
pyramid = pyramids.pyramid_gaussian(image_gray, downscale=2, channel_axis=None)
|
||||
for layer, out in enumerate(pyramid):
|
||||
layer_shape = (rows / 2**layer, cols / 2**layer)
|
||||
assert_array_equal(out.shape, layer_shape)
|
||||
|
||||
|
||||
def test_build_gaussian_pyramid_gray_defaults():
|
||||
rows, cols = image_gray.shape
|
||||
pyramid = pyramids.pyramid_gaussian(image_gray)
|
||||
for layer, out in enumerate(pyramid):
|
||||
layer_shape = (rows / 2**layer, cols / 2**layer)
|
||||
assert_array_equal(out.shape, layer_shape)
|
||||
|
||||
|
||||
def test_build_gaussian_pyramid_nd():
|
||||
for ndim in [1, 2, 3, 4]:
|
||||
img = np.random.randn(*((8,) * ndim))
|
||||
original_shape = np.asarray(img.shape)
|
||||
pyramid = pyramids.pyramid_gaussian(img, downscale=2, channel_axis=None)
|
||||
for layer, out in enumerate(pyramid):
|
||||
layer_shape = original_shape / 2**layer
|
||||
assert_array_equal(out.shape, layer_shape)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('channel_axis', [0, 1, 2, -1, -2, -3])
|
||||
def test_build_laplacian_pyramid_rgb(channel_axis):
|
||||
image = data.astronaut()
|
||||
rows, cols, dim = image.shape
|
||||
image = np.moveaxis(image, source=-1, destination=channel_axis)
|
||||
pyramid = pyramids.pyramid_laplacian(image, downscale=2, channel_axis=channel_axis)
|
||||
for layer, out in enumerate(pyramid):
|
||||
layer_shape = [rows / 2**layer, cols / 2**layer]
|
||||
layer_shape.insert(channel_axis % image.ndim, dim)
|
||||
assert out.shape == tuple(layer_shape)
|
||||
|
||||
|
||||
def test_build_laplacian_pyramid_defaults():
|
||||
rows, cols = image_gray.shape
|
||||
pyramid = pyramids.pyramid_laplacian(image_gray)
|
||||
for layer, out in enumerate(pyramid):
|
||||
layer_shape = (rows / 2**layer, cols / 2**layer)
|
||||
assert_array_equal(out.shape, layer_shape)
|
||||
|
||||
|
||||
def test_build_laplacian_pyramid_nd():
|
||||
for ndim in [1, 2, 3, 4]:
|
||||
img = np.random.randn(*(16,) * ndim)
|
||||
original_shape = np.asarray(img.shape)
|
||||
pyramid = pyramids.pyramid_laplacian(img, downscale=2, channel_axis=None)
|
||||
for layer, out in enumerate(pyramid):
|
||||
layer_shape = original_shape / 2**layer
|
||||
assert_array_equal(out.shape, layer_shape)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('channel_axis', [0, 1, 2, -1, -2, -3])
|
||||
def test_laplacian_pyramid_max_layers(channel_axis):
|
||||
for downscale in [2, 3, 5, 7]:
|
||||
if channel_axis is None:
|
||||
shape = (32, 8)
|
||||
shape_without_channels = shape
|
||||
else:
|
||||
shape_without_channels = (32, 8)
|
||||
ndim = len(shape_without_channels) + 1
|
||||
n_channels = 5
|
||||
shape = list(shape_without_channels)
|
||||
shape.insert(channel_axis % ndim, n_channels)
|
||||
shape = tuple(shape)
|
||||
img = np.ones(shape)
|
||||
pyramid = pyramids.pyramid_laplacian(
|
||||
img, downscale=downscale, channel_axis=channel_axis
|
||||
)
|
||||
max_layer = math.ceil(math.log(max(shape_without_channels), downscale))
|
||||
for layer, out in enumerate(pyramid):
|
||||
if channel_axis is None:
|
||||
out_shape_without_channels = out.shape
|
||||
else:
|
||||
assert out.shape[channel_axis] == n_channels
|
||||
out_shape_without_channels = list(out.shape)
|
||||
out_shape_without_channels.pop(channel_axis)
|
||||
out_shape_without_channels = tuple(out_shape_without_channels)
|
||||
|
||||
if layer < max_layer:
|
||||
# should not reach all axes as size 1 prior to final level
|
||||
assert max(out_shape_without_channels) > 1
|
||||
|
||||
# total number of images is max_layer + 1
|
||||
assert_equal(max_layer, layer)
|
||||
|
||||
# final layer should be size 1 on all axes
|
||||
assert out_shape_without_channels == (1, 1)
|
||||
|
||||
|
||||
def test_check_factor():
|
||||
with pytest.raises(ValueError):
|
||||
pyramids._check_factor(0.99)
|
||||
with pytest.raises(ValueError):
|
||||
pyramids._check_factor(-2)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('dtype', ['float16', 'float32', 'float64', 'uint8', 'int64'])
|
||||
@pytest.mark.parametrize(
|
||||
'pyramid_func', [pyramids.pyramid_gaussian, pyramids.pyramid_laplacian]
|
||||
)
|
||||
def test_pyramid_dtype_support(pyramid_func, dtype):
|
||||
with warnings.catch_warnings():
|
||||
# Ignore arch specific warning on arm64, armhf, ppc64el, riscv64, s390x
|
||||
# https://github.com/scikit-image/scikit-image/issues/7391
|
||||
warnings.filterwarnings(
|
||||
action="ignore",
|
||||
category=RuntimeWarning,
|
||||
message="invalid value encountered in cast",
|
||||
)
|
||||
img = np.random.randn(32, 8).astype(dtype)
|
||||
|
||||
pyramid = pyramid_func(img)
|
||||
float_dtype = _supported_float_type(dtype)
|
||||
assert np.all([im.dtype == float_dtype for im in pyramid])
|
||||
533
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_radon_transform.py
vendored
Normal file
533
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_radon_transform.py
vendored
Normal file
@@ -0,0 +1,533 @@
|
||||
import itertools
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from skimage._shared._dependency_checks import has_mpl
|
||||
from skimage._shared._warnings import expected_warnings
|
||||
from skimage._shared.testing import run_in_parallel
|
||||
from skimage._shared.utils import _supported_float_type, convert_to_float
|
||||
from skimage.data import shepp_logan_phantom
|
||||
from skimage.transform import radon, iradon, iradon_sart, rescale
|
||||
|
||||
|
||||
PHANTOM = shepp_logan_phantom()[::2, ::2]
|
||||
PHANTOM = rescale(
|
||||
PHANTOM, 0.5, order=1, mode='constant', anti_aliasing=False, channel_axis=None
|
||||
)
|
||||
|
||||
|
||||
def _debug_plot(original, result, sinogram=None):
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
imkwargs = dict(cmap='gray', interpolation='nearest')
|
||||
if sinogram is None:
|
||||
plt.figure(figsize=(15, 6))
|
||||
sp = 130
|
||||
else:
|
||||
plt.figure(figsize=(11, 11))
|
||||
sp = 221
|
||||
plt.subplot(sp + 0)
|
||||
plt.imshow(sinogram, aspect='auto', **imkwargs)
|
||||
plt.subplot(sp + 1)
|
||||
plt.imshow(original, **imkwargs)
|
||||
plt.subplot(sp + 2)
|
||||
plt.imshow(result, vmin=original.min(), vmax=original.max(), **imkwargs)
|
||||
plt.subplot(sp + 3)
|
||||
plt.imshow(result - original, **imkwargs)
|
||||
plt.colorbar()
|
||||
plt.show()
|
||||
|
||||
|
||||
def _rescale_intensity(x):
|
||||
x = x.astype(float)
|
||||
x -= x.min()
|
||||
x /= x.max()
|
||||
return x
|
||||
|
||||
|
||||
def test_iradon_bias_circular_phantom():
|
||||
"""
|
||||
test that a uniform circular phantom has a small reconstruction bias
|
||||
"""
|
||||
pixels = 128
|
||||
xy = np.arange(-pixels / 2, pixels / 2) + 0.5
|
||||
x, y = np.meshgrid(xy, xy)
|
||||
image = x**2 + y**2 <= (pixels / 4) ** 2
|
||||
|
||||
theta = np.linspace(0.0, 180.0, max(image.shape), endpoint=False)
|
||||
sinogram = radon(image, theta=theta)
|
||||
|
||||
reconstruction_fbp = iradon(sinogram, theta=theta)
|
||||
error = reconstruction_fbp - image
|
||||
|
||||
tol = 5e-5
|
||||
roi_err = np.abs(np.mean(error))
|
||||
assert roi_err < tol
|
||||
|
||||
|
||||
def check_radon_center(shape, circle, dtype, preserve_range):
|
||||
# Create a test image with only a single non-zero pixel at the origin
|
||||
image = np.zeros(shape, dtype=dtype)
|
||||
image[(shape[0] // 2, shape[1] // 2)] = 1.0
|
||||
# Calculate the sinogram
|
||||
theta = np.linspace(0.0, 180.0, max(shape), endpoint=False)
|
||||
sinogram = radon(image, theta=theta, circle=circle, preserve_range=preserve_range)
|
||||
assert sinogram.dtype == _supported_float_type(sinogram.dtype)
|
||||
# The sinogram should be a straight, horizontal line
|
||||
sinogram_max = np.argmax(sinogram, axis=0)
|
||||
print(sinogram_max)
|
||||
assert np.std(sinogram_max) < 1e-6
|
||||
|
||||
|
||||
@pytest.mark.parametrize("shape", [(16, 16), (17, 17)])
|
||||
@pytest.mark.parametrize("circle", [False, True])
|
||||
@pytest.mark.parametrize("dtype", [np.float64, np.float32, np.float16, np.uint8, bool])
|
||||
@pytest.mark.parametrize("preserve_range", [False, True])
|
||||
def test_radon_center(shape, circle, dtype, preserve_range):
|
||||
check_radon_center(shape, circle, dtype, preserve_range)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("shape", [(32, 16), (33, 17)])
|
||||
@pytest.mark.parametrize("circle", [False])
|
||||
@pytest.mark.parametrize("dtype", [np.float64, np.float32, np.uint8, bool])
|
||||
@pytest.mark.parametrize("preserve_range", [False, True])
|
||||
def test_radon_center_rectangular(shape, circle, dtype, preserve_range):
|
||||
check_radon_center(shape, circle, dtype, preserve_range)
|
||||
|
||||
|
||||
def check_iradon_center(size, theta, circle):
|
||||
debug = False
|
||||
# Create a test sinogram corresponding to a single projection
|
||||
# with a single non-zero pixel at the rotation center
|
||||
if circle:
|
||||
sinogram = np.zeros((size, 1), dtype=float)
|
||||
sinogram[size // 2, 0] = 1.0
|
||||
else:
|
||||
diagonal = int(np.ceil(np.sqrt(2) * size))
|
||||
sinogram = np.zeros((diagonal, 1), dtype=float)
|
||||
sinogram[sinogram.shape[0] // 2, 0] = 1.0
|
||||
maxpoint = np.unravel_index(np.argmax(sinogram), sinogram.shape)
|
||||
print('shape of generated sinogram', sinogram.shape)
|
||||
print('maximum in generated sinogram', maxpoint)
|
||||
# Compare reconstructions for theta=angle and theta=angle + 180;
|
||||
# these should be exactly equal
|
||||
reconstruction = iradon(sinogram, theta=[theta], circle=circle)
|
||||
reconstruction_opposite = iradon(sinogram, theta=[theta + 180], circle=circle)
|
||||
print(
|
||||
'rms deviance:',
|
||||
np.sqrt(np.mean((reconstruction_opposite - reconstruction) ** 2)),
|
||||
)
|
||||
if debug and has_mpl:
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
imkwargs = dict(cmap='gray', interpolation='nearest')
|
||||
plt.figure()
|
||||
plt.subplot(221)
|
||||
plt.imshow(sinogram, **imkwargs)
|
||||
plt.subplot(222)
|
||||
plt.imshow(reconstruction_opposite - reconstruction, **imkwargs)
|
||||
plt.subplot(223)
|
||||
plt.imshow(reconstruction, **imkwargs)
|
||||
plt.subplot(224)
|
||||
plt.imshow(reconstruction_opposite, **imkwargs)
|
||||
plt.show()
|
||||
|
||||
assert np.allclose(reconstruction, reconstruction_opposite)
|
||||
|
||||
|
||||
sizes_for_test_iradon_center = [16, 17]
|
||||
thetas_for_test_iradon_center = [0, 90]
|
||||
circles_for_test_iradon_center = [False, True]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"size, theta, circle",
|
||||
itertools.product(
|
||||
sizes_for_test_iradon_center,
|
||||
thetas_for_test_iradon_center,
|
||||
circles_for_test_iradon_center,
|
||||
),
|
||||
)
|
||||
def test_iradon_center(size, theta, circle):
|
||||
check_iradon_center(size, theta, circle)
|
||||
|
||||
|
||||
def check_radon_iradon(interpolation_type, filter_type):
|
||||
debug = False
|
||||
image = PHANTOM
|
||||
reconstructed = iradon(
|
||||
radon(image, circle=False),
|
||||
filter_name=filter_type,
|
||||
interpolation=interpolation_type,
|
||||
circle=False,
|
||||
)
|
||||
delta = np.mean(np.abs(image - reconstructed))
|
||||
print('\n\tmean error:', delta)
|
||||
if debug and has_mpl:
|
||||
_debug_plot(image, reconstructed)
|
||||
if filter_type in ('ramp', 'shepp-logan'):
|
||||
if interpolation_type == 'nearest':
|
||||
allowed_delta = 0.03
|
||||
else:
|
||||
allowed_delta = 0.025
|
||||
else:
|
||||
allowed_delta = 0.05
|
||||
assert delta < allowed_delta
|
||||
|
||||
|
||||
filter_types = ["ramp", "shepp-logan", "cosine", "hamming", "hann"]
|
||||
interpolation_types = ['linear', 'nearest']
|
||||
radon_iradon_inputs = list(itertools.product(interpolation_types, filter_types))
|
||||
# cubic interpolation is slow; only run one test for it
|
||||
radon_iradon_inputs.append(('cubic', 'shepp-logan'))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("interpolation_type, filter_type", radon_iradon_inputs)
|
||||
def test_radon_iradon(interpolation_type, filter_type):
|
||||
check_radon_iradon(interpolation_type, filter_type)
|
||||
|
||||
|
||||
def test_iradon_angles():
|
||||
"""
|
||||
Test with different number of projections
|
||||
"""
|
||||
size = 100
|
||||
# Synthetic data
|
||||
image = np.tri(size) + np.tri(size)[::-1]
|
||||
# Large number of projections: a good quality is expected
|
||||
nb_angles = 200
|
||||
theta = np.linspace(0, 180, nb_angles, endpoint=False)
|
||||
radon_image_200 = radon(image, theta=theta, circle=False)
|
||||
reconstructed = iradon(radon_image_200, circle=False)
|
||||
delta_200 = np.mean(
|
||||
abs(_rescale_intensity(image) - _rescale_intensity(reconstructed))
|
||||
)
|
||||
assert delta_200 < 0.03
|
||||
# Lower number of projections
|
||||
nb_angles = 80
|
||||
radon_image_80 = radon(image, theta=theta, circle=False)
|
||||
# Test whether the sum of all projections is approximately the same
|
||||
s = radon_image_80.sum(axis=0)
|
||||
assert np.allclose(s, s[0], rtol=0.01)
|
||||
reconstructed = iradon(radon_image_80, circle=False)
|
||||
delta_80 = np.mean(
|
||||
abs(image / np.max(image) - reconstructed / np.max(reconstructed))
|
||||
)
|
||||
# Loss of quality when the number of projections is reduced
|
||||
assert delta_80 > delta_200
|
||||
|
||||
|
||||
def check_radon_iradon_minimal(shape, slices):
|
||||
debug = False
|
||||
theta = np.arange(180)
|
||||
image = np.zeros(shape, dtype=float)
|
||||
image[slices] = 1.0
|
||||
sinogram = radon(image, theta, circle=False)
|
||||
reconstructed = iradon(sinogram, theta, circle=False)
|
||||
print('\n\tMaximum deviation:', np.max(np.abs(image - reconstructed)))
|
||||
if debug and has_mpl:
|
||||
_debug_plot(image, reconstructed, sinogram)
|
||||
if image.sum() == 1:
|
||||
assert np.unravel_index(
|
||||
np.argmax(reconstructed), image.shape
|
||||
) == np.unravel_index(np.argmax(image), image.shape)
|
||||
|
||||
|
||||
shapes = [(3, 3), (4, 4), (5, 5)]
|
||||
|
||||
|
||||
def generate_test_data_for_radon_iradon_minimal(shapes):
|
||||
def shape2coordinates(shape):
|
||||
c0, c1 = shape[0] // 2, shape[1] // 2
|
||||
coordinates = itertools.product((c0 - 1, c0, c0 + 1), (c1 - 1, c1, c1 + 1))
|
||||
return coordinates
|
||||
|
||||
def shape2shapeandcoordinates(shape):
|
||||
return itertools.product([shape], shape2coordinates(shape))
|
||||
|
||||
return itertools.chain.from_iterable(
|
||||
[shape2shapeandcoordinates(shape) for shape in shapes]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"shape, coordinate", generate_test_data_for_radon_iradon_minimal(shapes)
|
||||
)
|
||||
def test_radon_iradon_minimal(shape, coordinate):
|
||||
check_radon_iradon_minimal(shape, coordinate)
|
||||
|
||||
|
||||
def test_reconstruct_with_wrong_angles():
|
||||
a = np.zeros((3, 3))
|
||||
p = radon(a, theta=[0, 1, 2], circle=False)
|
||||
iradon(p, theta=[0, 1, 2], circle=False)
|
||||
with pytest.raises(ValueError):
|
||||
iradon(p, theta=[0, 1, 2, 3])
|
||||
|
||||
|
||||
def _random_circle(shape):
|
||||
# Synthetic random data, zero outside reconstruction circle
|
||||
np.random.seed(98312871)
|
||||
image = np.random.rand(*shape)
|
||||
c0, c1 = np.ogrid[0 : shape[0], 0 : shape[1]]
|
||||
r = np.sqrt((c0 - shape[0] // 2) ** 2 + (c1 - shape[1] // 2) ** 2)
|
||||
radius = min(shape) // 2
|
||||
image[r > radius] = 0.0
|
||||
return image
|
||||
|
||||
|
||||
def test_radon_circle():
|
||||
a = np.ones((10, 10))
|
||||
with expected_warnings(['reconstruction circle']):
|
||||
radon(a, circle=True)
|
||||
|
||||
# Synthetic data, circular symmetry
|
||||
shape = (61, 79)
|
||||
c0, c1 = np.ogrid[0 : shape[0], 0 : shape[1]]
|
||||
r = np.sqrt((c0 - shape[0] // 2) ** 2 + (c1 - shape[1] // 2) ** 2)
|
||||
radius = min(shape) // 2
|
||||
image = np.clip(radius - r, 0, np.inf)
|
||||
image = _rescale_intensity(image)
|
||||
angles = np.linspace(0, 180, min(shape), endpoint=False)
|
||||
sinogram = radon(image, theta=angles, circle=True)
|
||||
assert np.all(sinogram.std(axis=1) < 1e-2)
|
||||
|
||||
# Synthetic data, random
|
||||
image = _random_circle(shape)
|
||||
sinogram = radon(image, theta=angles, circle=True)
|
||||
mass = sinogram.sum(axis=0)
|
||||
average_mass = mass.mean()
|
||||
relative_error = np.abs(mass - average_mass) / average_mass
|
||||
print(relative_error.max(), relative_error.mean())
|
||||
assert np.all(relative_error < 3.2e-3)
|
||||
|
||||
|
||||
def check_sinogram_circle_to_square(size):
|
||||
from skimage.transform.radon_transform import _sinogram_circle_to_square
|
||||
|
||||
image = _random_circle((size, size))
|
||||
theta = np.linspace(0.0, 180.0, size, False)
|
||||
sinogram_circle = radon(image, theta, circle=True)
|
||||
|
||||
def argmax_shape(a):
|
||||
return np.unravel_index(np.argmax(a), a.shape)
|
||||
|
||||
print('\n\targmax of circle:', argmax_shape(sinogram_circle))
|
||||
sinogram_square = radon(image, theta, circle=False)
|
||||
print('\targmax of square:', argmax_shape(sinogram_square))
|
||||
sinogram_circle_to_square = _sinogram_circle_to_square(sinogram_circle)
|
||||
print('\targmax of circle to square:', argmax_shape(sinogram_circle_to_square))
|
||||
error = abs(sinogram_square - sinogram_circle_to_square)
|
||||
print(np.mean(error), np.max(error))
|
||||
assert argmax_shape(sinogram_square) == argmax_shape(sinogram_circle_to_square)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("size", (50, 51))
|
||||
def test_sinogram_circle_to_square(size):
|
||||
check_sinogram_circle_to_square(size)
|
||||
|
||||
|
||||
def check_radon_iradon_circle(interpolation, shape, output_size):
|
||||
# Forward and inverse radon on synthetic data
|
||||
image = _random_circle(shape)
|
||||
radius = min(shape) // 2
|
||||
sinogram_rectangle = radon(image, circle=False)
|
||||
reconstruction_rectangle = iradon(
|
||||
sinogram_rectangle,
|
||||
output_size=output_size,
|
||||
interpolation=interpolation,
|
||||
circle=False,
|
||||
)
|
||||
sinogram_circle = radon(image, circle=True)
|
||||
reconstruction_circle = iradon(
|
||||
sinogram_circle,
|
||||
output_size=output_size,
|
||||
interpolation=interpolation,
|
||||
circle=True,
|
||||
)
|
||||
# Crop rectangular reconstruction to match circle=True reconstruction
|
||||
width = reconstruction_circle.shape[0]
|
||||
excess = int(np.ceil((reconstruction_rectangle.shape[0] - width) / 2))
|
||||
s = np.s_[excess : width + excess, excess : width + excess]
|
||||
reconstruction_rectangle = reconstruction_rectangle[s]
|
||||
# Find the reconstruction circle, set reconstruction to zero outside
|
||||
c0, c1 = np.ogrid[0:width, 0:width]
|
||||
r = np.sqrt((c0 - width // 2) ** 2 + (c1 - width // 2) ** 2)
|
||||
reconstruction_rectangle[r > radius] = 0.0
|
||||
print(reconstruction_circle.shape)
|
||||
print(reconstruction_rectangle.shape)
|
||||
np.allclose(reconstruction_rectangle, reconstruction_circle)
|
||||
|
||||
|
||||
# if adding more shapes to test data, you might want to look at commit d0f2bac3f
|
||||
shapes_radon_iradon_circle = ((61, 79),)
|
||||
interpolations = ('nearest', 'linear')
|
||||
output_sizes = (
|
||||
None,
|
||||
min(shapes_radon_iradon_circle[0]),
|
||||
max(shapes_radon_iradon_circle[0]),
|
||||
97,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"shape, interpolation, output_size",
|
||||
itertools.product(shapes_radon_iradon_circle, interpolations, output_sizes),
|
||||
)
|
||||
def test_radon_iradon_circle(shape, interpolation, output_size):
|
||||
check_radon_iradon_circle(interpolation, shape, output_size)
|
||||
|
||||
|
||||
def test_order_angles_golden_ratio():
|
||||
from skimage.transform.radon_transform import order_angles_golden_ratio
|
||||
|
||||
np.random.seed(1231)
|
||||
lengths = [1, 4, 10, 180]
|
||||
for l in lengths:
|
||||
theta_ordered = np.linspace(0, 180, l, endpoint=False)
|
||||
theta_random = np.random.uniform(0, 180, l)
|
||||
for theta in (theta_random, theta_ordered):
|
||||
indices = [x for x in order_angles_golden_ratio(theta)]
|
||||
# no duplicate indices allowed
|
||||
assert len(indices) == len(set(indices))
|
||||
|
||||
|
||||
@run_in_parallel()
|
||||
def test_iradon_sart():
|
||||
debug = False
|
||||
|
||||
image = rescale(
|
||||
PHANTOM, 0.8, mode='reflect', channel_axis=None, anti_aliasing=False
|
||||
)
|
||||
theta_ordered = np.linspace(0.0, 180.0, image.shape[0], endpoint=False)
|
||||
theta_missing_wedge = np.linspace(0.0, 150.0, image.shape[0], endpoint=True)
|
||||
for theta, error_factor in ((theta_ordered, 1.0), (theta_missing_wedge, 2.0)):
|
||||
sinogram = radon(image, theta, circle=True)
|
||||
reconstructed = iradon_sart(sinogram, theta)
|
||||
|
||||
if debug and has_mpl:
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
plt.figure()
|
||||
plt.subplot(221)
|
||||
plt.imshow(image, interpolation='nearest')
|
||||
plt.subplot(222)
|
||||
plt.imshow(sinogram, interpolation='nearest')
|
||||
plt.subplot(223)
|
||||
plt.imshow(reconstructed, interpolation='nearest')
|
||||
plt.subplot(224)
|
||||
plt.imshow(reconstructed - image, interpolation='nearest')
|
||||
plt.show()
|
||||
|
||||
delta = np.mean(np.abs(reconstructed - image))
|
||||
print('delta (1 iteration) =', delta)
|
||||
assert delta < 0.02 * error_factor
|
||||
reconstructed = iradon_sart(sinogram, theta, reconstructed)
|
||||
delta = np.mean(np.abs(reconstructed - image))
|
||||
print('delta (2 iterations) =', delta)
|
||||
assert delta < 0.014 * error_factor
|
||||
reconstructed = iradon_sart(sinogram, theta, clip=(0, 1))
|
||||
delta = np.mean(np.abs(reconstructed - image))
|
||||
print('delta (1 iteration, clip) =', delta)
|
||||
assert delta < 0.018 * error_factor
|
||||
|
||||
np.random.seed(1239867)
|
||||
shifts = np.random.uniform(-3, 3, sinogram.shape[1])
|
||||
x = np.arange(sinogram.shape[0])
|
||||
sinogram_shifted = np.vstack(
|
||||
[
|
||||
np.interp(x + shifts[i], x, sinogram[:, i])
|
||||
for i in range(sinogram.shape[1])
|
||||
]
|
||||
).T
|
||||
reconstructed = iradon_sart(sinogram_shifted, theta, projection_shifts=shifts)
|
||||
if debug and has_mpl:
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
plt.figure()
|
||||
plt.subplot(221)
|
||||
plt.imshow(image, interpolation='nearest')
|
||||
plt.subplot(222)
|
||||
plt.imshow(sinogram_shifted, interpolation='nearest')
|
||||
plt.subplot(223)
|
||||
plt.imshow(reconstructed, interpolation='nearest')
|
||||
plt.subplot(224)
|
||||
plt.imshow(reconstructed - image, interpolation='nearest')
|
||||
plt.show()
|
||||
|
||||
delta = np.mean(np.abs(reconstructed - image))
|
||||
print('delta (1 iteration, shifted sinogram) =', delta)
|
||||
assert delta < 0.022 * error_factor
|
||||
|
||||
|
||||
@pytest.mark.parametrize("preserve_range", [True, False])
|
||||
def test_iradon_dtype(preserve_range):
|
||||
sinogram = np.zeros((16, 1), dtype=int)
|
||||
sinogram[8, 0] = 1.0
|
||||
sinogram64 = sinogram.astype('float64')
|
||||
sinogram32 = sinogram.astype('float32')
|
||||
|
||||
assert iradon(sinogram, theta=[0], preserve_range=preserve_range).dtype == 'float64'
|
||||
assert (
|
||||
iradon(sinogram64, theta=[0], preserve_range=preserve_range).dtype
|
||||
== sinogram64.dtype
|
||||
)
|
||||
assert (
|
||||
iradon(sinogram32, theta=[0], preserve_range=preserve_range).dtype
|
||||
== sinogram32.dtype
|
||||
)
|
||||
|
||||
|
||||
def test_radon_dtype():
|
||||
img = convert_to_float(PHANTOM, False)
|
||||
img32 = img.astype(np.float32)
|
||||
|
||||
assert radon(img).dtype == img.dtype
|
||||
assert radon(img32).dtype == img32.dtype
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dtype", [np.float32, np.float64])
|
||||
def test_iradon_sart_dtype(dtype):
|
||||
sinogram = np.zeros((16, 1), dtype=int)
|
||||
sinogram[8, 0] = 1.0
|
||||
sinogram64 = sinogram.astype('float64')
|
||||
sinogram32 = sinogram.astype('float32')
|
||||
|
||||
with expected_warnings(['Input data is cast to float']):
|
||||
assert iradon_sart(sinogram, theta=[0]).dtype == 'float64'
|
||||
|
||||
assert iradon_sart(sinogram64, theta=[0]).dtype == sinogram64.dtype
|
||||
assert iradon_sart(sinogram32, theta=[0]).dtype == sinogram32.dtype
|
||||
|
||||
assert iradon_sart(sinogram, theta=[0], dtype=dtype).dtype == dtype
|
||||
assert iradon_sart(sinogram32, theta=[0], dtype=dtype).dtype == dtype
|
||||
assert iradon_sart(sinogram64, theta=[0], dtype=dtype).dtype == dtype
|
||||
|
||||
|
||||
def test_iradon_sart_wrong_dtype():
|
||||
sinogram = np.zeros((16, 1))
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
iradon_sart(sinogram, dtype=int)
|
||||
|
||||
|
||||
def test_iradon_rampfilter_bias_circular_phantom():
|
||||
"""
|
||||
test that a uniform circular phantom has a small reconstruction bias using
|
||||
the ramp filter
|
||||
"""
|
||||
pixels = 128
|
||||
xy = np.arange(-pixels / 2, pixels / 2) + 0.5
|
||||
x, y = np.meshgrid(xy, xy)
|
||||
image = x**2 + y**2 <= (pixels / 4) ** 2
|
||||
|
||||
theta = np.linspace(0.0, 180.0, max(image.shape), endpoint=False)
|
||||
sinogram = radon(image, theta=theta)
|
||||
|
||||
reconstruction_fbp = iradon(sinogram, theta=theta)
|
||||
error = reconstruction_fbp - image
|
||||
|
||||
tol = 5e-5
|
||||
roi_err = np.abs(np.mean(error))
|
||||
assert roi_err < tol
|
||||
77
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_thin_plate_splines.py
vendored
Normal file
77
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_thin_plate_splines.py
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import skimage as ski
|
||||
from skimage.transform import ThinPlateSplineTransform
|
||||
|
||||
SRC = np.array([[0, 0], [0, 5], [5, 5], [5, 0]])
|
||||
|
||||
DST = np.array([[5, 0], [0, 0], [0, 5], [5, 5]])
|
||||
|
||||
|
||||
class TestThinPlateSplineTransform:
|
||||
def test_call_before_estimation(self):
|
||||
tps = ThinPlateSplineTransform()
|
||||
assert tps.src is None
|
||||
with pytest.raises(ValueError, match="Transformation is undefined"):
|
||||
tps(SRC)
|
||||
|
||||
def test_call_invalid_coords_shape(self):
|
||||
tps = ThinPlateSplineTransform()
|
||||
tps.estimate(SRC, DST)
|
||||
coords = np.array([1, 2, 3])
|
||||
with pytest.raises(
|
||||
ValueError, match=r"Input `coords` must have shape \(N, 2\)"
|
||||
):
|
||||
tps(coords)
|
||||
|
||||
def test_call_on_SRC(self):
|
||||
tps = ThinPlateSplineTransform()
|
||||
tps.estimate(SRC, DST)
|
||||
result = tps(SRC)
|
||||
np.testing.assert_allclose(result, DST, atol=1e-15)
|
||||
|
||||
def test_tps_transform_inverse(self):
|
||||
tps = ThinPlateSplineTransform()
|
||||
tps.estimate(SRC, DST)
|
||||
with pytest.raises(NotImplementedError):
|
||||
tps.inverse()
|
||||
|
||||
def test_tps_estimation_faulty_input(self):
|
||||
src = np.array([[0, 0], [0, 5], [5, 5], [5, 0]])
|
||||
dst = np.array([[5, 0], [0, 0], [0, 5]])
|
||||
|
||||
tps = ThinPlateSplineTransform()
|
||||
assert tps.src is None
|
||||
|
||||
with pytest.raises(ValueError, match="Shape of `src` and `dst` didn't match"):
|
||||
tps.estimate(src, dst)
|
||||
|
||||
less_than_3pts = np.array([[0, 0], [0, 5]])
|
||||
with pytest.raises(ValueError, match="Need at least 3 points"):
|
||||
tps.estimate(less_than_3pts, dst)
|
||||
with pytest.raises(ValueError, match="Need at least 3 points"):
|
||||
tps.estimate(src, less_than_3pts)
|
||||
with pytest.raises(ValueError, match="Need at least 3 points"):
|
||||
tps.estimate(less_than_3pts, less_than_3pts)
|
||||
|
||||
not_2d = np.array([0, 1, 2, 3])
|
||||
with pytest.raises(ValueError, match=".*`src` must be a 2-dimensional array"):
|
||||
tps.estimate(not_2d, dst)
|
||||
with pytest.raises(ValueError, match=".*`dst` must be a 2-dimensional array"):
|
||||
tps.estimate(src, not_2d)
|
||||
|
||||
# When the estimation fails, the instance attributes remain unchanged
|
||||
assert tps.src is None
|
||||
|
||||
def test_rotate(self):
|
||||
image = ski.data.astronaut()
|
||||
desired = ski.transform.rotate(image, angle=90)
|
||||
|
||||
src = np.array([[0, 0], [0, 511], [511, 511], [511, 0]])
|
||||
dst = np.array([[511, 0], [0, 0], [0, 511], [511, 511]])
|
||||
tps = ThinPlateSplineTransform()
|
||||
tps.estimate(src, dst)
|
||||
result = ski.transform.warp(image, tps)
|
||||
|
||||
np.testing.assert_allclose(result, desired, atol=1e-13)
|
||||
1061
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_warps.py
vendored
Normal file
1061
.CondaPkg/env/Lib/site-packages/skimage/transform/tests/test_warps.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user