using for loop to install conda package
This commit is contained in:
0
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__init__.py
vendored
Normal file
0
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__init__.py
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/__init__.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/__init__.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_binary.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_binary.cpython-311.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_extrema.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_extrema.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_flood_fill.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_flood_fill.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_footprints.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_footprints.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_gray.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_gray.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_isotropic.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_isotropic.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_max_tree.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_max_tree.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_misc.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_misc.cpython-311.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_util.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/__pycache__/test_util.cpython-311.pyc
vendored
Normal file
Binary file not shown.
317
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_binary.py
vendored
Normal file
317
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_binary.py
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
from numpy.testing import assert_array_equal, assert_equal
|
||||
from scipy import ndimage as ndi
|
||||
|
||||
from skimage import data, color, morphology
|
||||
from skimage.util import img_as_bool
|
||||
from skimage.morphology import binary, footprints, gray
|
||||
|
||||
|
||||
img = color.rgb2gray(data.astronaut())
|
||||
bw_img = img > 100 / 255.
|
||||
|
||||
|
||||
def test_non_square_image():
|
||||
footprint = morphology.square(3)
|
||||
binary_res = binary.binary_erosion(bw_img[:100, :200], footprint)
|
||||
gray_res = img_as_bool(gray.erosion(bw_img[:100, :200], footprint))
|
||||
assert_array_equal(binary_res, gray_res)
|
||||
|
||||
|
||||
def test_binary_erosion():
|
||||
footprint = morphology.square(3)
|
||||
binary_res = binary.binary_erosion(bw_img, footprint)
|
||||
gray_res = img_as_bool(gray.erosion(bw_img, footprint))
|
||||
assert_array_equal(binary_res, gray_res)
|
||||
|
||||
|
||||
def test_binary_dilation():
|
||||
footprint = morphology.square(3)
|
||||
binary_res = binary.binary_dilation(bw_img, footprint)
|
||||
gray_res = img_as_bool(gray.dilation(bw_img, footprint))
|
||||
assert_array_equal(binary_res, gray_res)
|
||||
|
||||
|
||||
def test_binary_closing():
|
||||
footprint = morphology.square(3)
|
||||
binary_res = binary.binary_closing(bw_img, footprint)
|
||||
gray_res = img_as_bool(gray.closing(bw_img, footprint))
|
||||
assert_array_equal(binary_res, gray_res)
|
||||
|
||||
|
||||
def test_binary_opening():
|
||||
footprint = morphology.square(3)
|
||||
binary_res = binary.binary_opening(bw_img, footprint)
|
||||
gray_res = img_as_bool(gray.opening(bw_img, footprint))
|
||||
assert_array_equal(binary_res, gray_res)
|
||||
|
||||
|
||||
def _get_decomp_test_data(function, ndim=2):
|
||||
if function == 'binary_erosion':
|
||||
img = np.ones((17, ) * ndim, dtype=np.uint8)
|
||||
img[8, 8] = 0
|
||||
elif function == 'binary_dilation':
|
||||
img = np.zeros((17, ) * ndim, dtype=np.uint8)
|
||||
img[8, 8] = 1
|
||||
else:
|
||||
img = data.binary_blobs(32, n_dim=ndim, seed=1)
|
||||
return img
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"function",
|
||||
["binary_erosion", "binary_dilation", "binary_closing", "binary_opening"],
|
||||
)
|
||||
@pytest.mark.parametrize("size", (3, 4, 11))
|
||||
@pytest.mark.parametrize("decomposition", ['separable', 'sequence'])
|
||||
def test_square_decomposition(function, size, decomposition):
|
||||
"""Validate footprint decomposition for various shapes.
|
||||
|
||||
comparison is made to the case without decomposition.
|
||||
"""
|
||||
footprint_ndarray = footprints.square(size, decomposition=None)
|
||||
footprint = footprints.square(size, decomposition=decomposition)
|
||||
img = _get_decomp_test_data(function)
|
||||
func = getattr(binary, function)
|
||||
expected = func(img, footprint=footprint_ndarray)
|
||||
out = func(img, footprint=footprint)
|
||||
assert_array_equal(expected, out)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"function",
|
||||
["binary_erosion", "binary_dilation", "binary_closing", "binary_opening"],
|
||||
)
|
||||
@pytest.mark.parametrize("nrows", (3, 4, 11))
|
||||
@pytest.mark.parametrize("ncols", (3, 4, 11))
|
||||
@pytest.mark.parametrize("decomposition", ['separable', 'sequence'])
|
||||
def test_rectangle_decomposition(function, nrows, ncols, decomposition):
|
||||
"""Validate footprint decomposition for various shapes.
|
||||
|
||||
comparison is made to the case without decomposition.
|
||||
"""
|
||||
footprint_ndarray = footprints.rectangle(nrows, ncols, decomposition=None)
|
||||
footprint = footprints.rectangle(nrows, ncols, decomposition=decomposition)
|
||||
img = _get_decomp_test_data(function)
|
||||
func = getattr(binary, function)
|
||||
expected = func(img, footprint=footprint_ndarray)
|
||||
out = func(img, footprint=footprint)
|
||||
assert_array_equal(expected, out)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"function",
|
||||
["binary_erosion", "binary_dilation", "binary_closing", "binary_opening"],
|
||||
)
|
||||
@pytest.mark.parametrize("m", (0, 1, 2, 3, 4, 5))
|
||||
@pytest.mark.parametrize("n", (0, 1, 2, 3, 4, 5))
|
||||
@pytest.mark.parametrize("decomposition", ['sequence'])
|
||||
def test_octagon_decomposition(function, m, n, decomposition):
|
||||
"""Validate footprint decomposition for various shapes.
|
||||
|
||||
comparison is made to the case without decomposition.
|
||||
"""
|
||||
if m == 0 and n == 0:
|
||||
with pytest.raises(ValueError):
|
||||
footprints.octagon(m, n, decomposition=decomposition)
|
||||
else:
|
||||
footprint_ndarray = footprints.octagon(m, n, decomposition=None)
|
||||
footprint = footprints.octagon(m, n, decomposition=decomposition)
|
||||
img = _get_decomp_test_data(function)
|
||||
func = getattr(binary, function)
|
||||
expected = func(img, footprint=footprint_ndarray)
|
||||
out = func(img, footprint=footprint)
|
||||
assert_array_equal(expected, out)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"function",
|
||||
["binary_erosion", "binary_dilation", "binary_closing", "binary_opening"],
|
||||
)
|
||||
@pytest.mark.parametrize("radius", (1, 2, 5))
|
||||
@pytest.mark.parametrize("decomposition", ['sequence'])
|
||||
def test_diamond_decomposition(function, radius, decomposition):
|
||||
"""Validate footprint decomposition for various shapes.
|
||||
|
||||
comparison is made to the case without decomposition.
|
||||
"""
|
||||
footprint_ndarray = footprints.diamond(radius, decomposition=None)
|
||||
footprint = footprints.diamond(radius, decomposition=decomposition)
|
||||
img = _get_decomp_test_data(function)
|
||||
func = getattr(binary, function)
|
||||
expected = func(img, footprint=footprint_ndarray)
|
||||
out = func(img, footprint=footprint)
|
||||
assert_array_equal(expected, out)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"function",
|
||||
["binary_erosion", "binary_dilation", "binary_closing", "binary_opening"],
|
||||
)
|
||||
@pytest.mark.parametrize("size", (3, 4, 5))
|
||||
@pytest.mark.parametrize("decomposition", ['separable', 'sequence'])
|
||||
def test_cube_decomposition(function, size, decomposition):
|
||||
"""Validate footprint decomposition for various shapes.
|
||||
|
||||
comparison is made to the case without decomposition.
|
||||
"""
|
||||
footprint_ndarray = footprints.cube(size, decomposition=None)
|
||||
footprint = footprints.cube(size, decomposition=decomposition)
|
||||
img = _get_decomp_test_data(function, ndim=3)
|
||||
func = getattr(binary, function)
|
||||
expected = func(img, footprint=footprint_ndarray)
|
||||
out = func(img, footprint=footprint)
|
||||
assert_array_equal(expected, out)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"function",
|
||||
["binary_erosion", "binary_dilation", "binary_closing", "binary_opening"],
|
||||
)
|
||||
@pytest.mark.parametrize("radius", (1, 2, 3))
|
||||
@pytest.mark.parametrize("decomposition", ['sequence'])
|
||||
def test_octahedron_decomposition(function, radius, decomposition):
|
||||
"""Validate footprint decomposition for various shapes.
|
||||
|
||||
comparison is made to the case without decomposition.
|
||||
"""
|
||||
footprint_ndarray = footprints.octahedron(radius, decomposition=None)
|
||||
footprint = footprints.octahedron(radius, decomposition=decomposition)
|
||||
img = _get_decomp_test_data(function, ndim=3)
|
||||
func = getattr(binary, function)
|
||||
expected = func(img, footprint=footprint_ndarray)
|
||||
out = func(img, footprint=footprint)
|
||||
assert_array_equal(expected, out)
|
||||
|
||||
|
||||
def test_footprint_overflow():
|
||||
footprint = np.ones((17, 17), dtype=np.uint8)
|
||||
img = np.zeros((20, 20), dtype=bool)
|
||||
img[2:19, 2:19] = True
|
||||
binary_res = binary.binary_erosion(img, footprint)
|
||||
gray_res = img_as_bool(gray.erosion(img, footprint))
|
||||
assert_array_equal(binary_res, gray_res)
|
||||
|
||||
|
||||
def test_out_argument():
|
||||
for func in (binary.binary_erosion, binary.binary_dilation):
|
||||
footprint = np.ones((3, 3), dtype=np.uint8)
|
||||
img = np.ones((10, 10))
|
||||
out = np.zeros_like(img)
|
||||
out_saved = out.copy()
|
||||
func(img, footprint, out=out)
|
||||
assert np.any(out != out_saved)
|
||||
assert_array_equal(out, func(img, footprint))
|
||||
|
||||
|
||||
binary_functions = [binary.binary_erosion, binary.binary_dilation,
|
||||
binary.binary_opening, binary.binary_closing]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("function", binary_functions)
|
||||
def test_default_footprint(function):
|
||||
footprint = morphology.diamond(radius=1)
|
||||
image = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], np.uint8)
|
||||
im_expected = function(image, footprint)
|
||||
im_test = function(image)
|
||||
assert_array_equal(im_expected, im_test)
|
||||
|
||||
|
||||
def test_3d_fallback_default_footprint():
|
||||
# 3x3x3 cube inside a 7x7x7 image:
|
||||
image = np.zeros((7, 7, 7), bool)
|
||||
image[2:-2, 2:-2, 2:-2] = 1
|
||||
|
||||
opened = binary.binary_opening(image)
|
||||
|
||||
# expect a "hyper-cross" centered in the 5x5x5:
|
||||
image_expected = np.zeros((7, 7, 7), dtype=bool)
|
||||
image_expected[2:5, 2:5, 2:5] = ndi.generate_binary_structure(3, 1)
|
||||
assert_array_equal(opened, image_expected)
|
||||
|
||||
|
||||
binary_3d_fallback_functions = [binary.binary_opening, binary.binary_closing]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("function", binary_3d_fallback_functions)
|
||||
def test_3d_fallback_cube_footprint(function):
|
||||
# 3x3x3 cube inside a 7x7x7 image:
|
||||
image = np.zeros((7, 7, 7), bool)
|
||||
image[2:-2, 2:-2, 2:-2] = 1
|
||||
|
||||
cube = np.ones((3, 3, 3), dtype=np.uint8)
|
||||
|
||||
new_image = function(image, cube)
|
||||
assert_array_equal(new_image, image)
|
||||
|
||||
|
||||
def test_2d_ndimage_equivalence():
|
||||
image = np.zeros((9, 9), np.uint16)
|
||||
image[2:-2, 2:-2] = 2**14
|
||||
image[3:-3, 3:-3] = 2**15
|
||||
image[4, 4] = 2**16-1
|
||||
|
||||
bin_opened = binary.binary_opening(image)
|
||||
bin_closed = binary.binary_closing(image)
|
||||
|
||||
footprint = ndi.generate_binary_structure(2, 1)
|
||||
ndimage_opened = ndi.binary_opening(image, structure=footprint)
|
||||
ndimage_closed = ndi.binary_closing(image, structure=footprint)
|
||||
|
||||
assert_array_equal(bin_opened, ndimage_opened)
|
||||
assert_array_equal(bin_closed, ndimage_closed)
|
||||
|
||||
|
||||
def test_binary_output_2d():
|
||||
image = np.zeros((9, 9), np.uint16)
|
||||
image[2:-2, 2:-2] = 2**14
|
||||
image[3:-3, 3:-3] = 2**15
|
||||
image[4, 4] = 2**16-1
|
||||
|
||||
bin_opened = binary.binary_opening(image)
|
||||
bin_closed = binary.binary_closing(image)
|
||||
|
||||
int_opened = np.empty_like(image, dtype=np.uint8)
|
||||
int_closed = np.empty_like(image, dtype=np.uint8)
|
||||
binary.binary_opening(image, out=int_opened)
|
||||
binary.binary_closing(image, out=int_closed)
|
||||
|
||||
assert_equal(bin_opened.dtype, bool)
|
||||
assert_equal(bin_closed.dtype, bool)
|
||||
|
||||
assert_equal(int_opened.dtype, np.uint8)
|
||||
assert_equal(int_closed.dtype, np.uint8)
|
||||
|
||||
|
||||
def test_binary_output_3d():
|
||||
image = np.zeros((9, 9, 9), np.uint16)
|
||||
image[2:-2, 2:-2, 2:-2] = 2**14
|
||||
image[3:-3, 3:-3, 3:-3] = 2**15
|
||||
image[4, 4, 4] = 2**16-1
|
||||
|
||||
bin_opened = binary.binary_opening(image)
|
||||
bin_closed = binary.binary_closing(image)
|
||||
|
||||
int_opened = np.empty_like(image, dtype=np.uint8)
|
||||
int_closed = np.empty_like(image, dtype=np.uint8)
|
||||
binary.binary_opening(image, out=int_opened)
|
||||
binary.binary_closing(image, out=int_closed)
|
||||
|
||||
assert_equal(bin_opened.dtype, bool)
|
||||
assert_equal(bin_closed.dtype, bool)
|
||||
|
||||
assert_equal(int_opened.dtype, np.uint8)
|
||||
assert_equal(int_closed.dtype, np.uint8)
|
||||
197
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_convex_hull.py
vendored
Normal file
197
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_convex_hull.py
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
import numpy as np
|
||||
from skimage.morphology import convex_hull_image, convex_hull_object
|
||||
from skimage.morphology._convex_hull import possible_hull
|
||||
|
||||
from skimage._shared import testing
|
||||
from skimage._shared.testing import assert_array_equal
|
||||
from skimage._shared._warnings import expected_warnings
|
||||
|
||||
|
||||
def test_basic():
|
||||
image = np.array(
|
||||
[[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, 0, 0],
|
||||
[0, 0, 1, 0, 0, 0, 1, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool)
|
||||
|
||||
expected = np.array(
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 1, 1, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool)
|
||||
|
||||
assert_array_equal(convex_hull_image(image), expected)
|
||||
|
||||
|
||||
def test_empty_image():
|
||||
image = np.zeros((6, 6), dtype=bool)
|
||||
with expected_warnings(['entirely zero']):
|
||||
assert_array_equal(convex_hull_image(image), image)
|
||||
|
||||
|
||||
def test_qhull_offset_example():
|
||||
nonzeros = (([1367, 1368, 1368, 1368, 1369, 1369, 1369, 1369, 1369, 1370,
|
||||
1370, 1370, 1370, 1370, 1370, 1370, 1371, 1371, 1371, 1371,
|
||||
1371, 1371, 1371, 1371, 1371, 1372, 1372, 1372, 1372, 1372,
|
||||
1372, 1372, 1372, 1372, 1373, 1373, 1373, 1373, 1373, 1373,
|
||||
1373, 1373, 1373, 1374, 1374, 1374, 1374, 1374, 1374, 1374,
|
||||
1375, 1375, 1375, 1375, 1375, 1376, 1376, 1376, 1377, 1372]),
|
||||
([151, 150, 151, 152, 149, 150, 151, 152, 153, 148, 149, 150,
|
||||
151, 152, 153, 154, 147, 148, 149, 150, 151, 152, 153, 154,
|
||||
155, 146, 147, 148, 149, 150, 151, 152, 153, 154, 146, 147,
|
||||
148, 149, 150, 151, 152, 153, 154, 147, 148, 149, 150, 151,
|
||||
152, 153, 148, 149, 150, 151, 152, 149, 150, 151, 150, 155]))
|
||||
image = np.zeros((1392, 1040), dtype=bool)
|
||||
image[nonzeros] = True
|
||||
expected = image.copy()
|
||||
assert_array_equal(convex_hull_image(image), expected)
|
||||
|
||||
|
||||
def test_pathological_qhull_example():
|
||||
image = np.array(
|
||||
[[0, 0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 0, 0, 0, 0]], dtype=bool)
|
||||
expected = np.array(
|
||||
[[0, 0, 0, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 0, 0]], dtype=bool)
|
||||
assert_array_equal(convex_hull_image(image), expected)
|
||||
|
||||
|
||||
def test_pathological_qhull_labels():
|
||||
image = np.array([[0, 0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 0, 0, 0, 0]], dtype=bool)
|
||||
|
||||
expected = np.array([[0, 0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 0, 0, 0]], dtype=bool)
|
||||
|
||||
actual = convex_hull_image(image, include_borders=False)
|
||||
assert_array_equal(actual, expected)
|
||||
|
||||
|
||||
def test_possible_hull():
|
||||
image = np.array(
|
||||
[[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, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.uint8)
|
||||
|
||||
expected = np.array([[1, 4],
|
||||
[2, 3],
|
||||
[3, 2],
|
||||
[4, 1],
|
||||
[4, 1],
|
||||
[3, 2],
|
||||
[2, 3],
|
||||
[1, 4],
|
||||
[2, 5],
|
||||
[3, 6],
|
||||
[4, 7],
|
||||
[2, 5],
|
||||
[3, 6],
|
||||
[4, 7],
|
||||
[4, 2],
|
||||
[4, 3],
|
||||
[4, 4],
|
||||
[4, 5],
|
||||
[4, 6]])
|
||||
|
||||
ph = possible_hull(image)
|
||||
assert_array_equal(ph, expected)
|
||||
|
||||
|
||||
def test_object():
|
||||
image = np.array(
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 1, 1, 0, 0, 1, 0, 1],
|
||||
[1, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||
[1, 0, 0, 0, 0, 0, 1, 0, 1],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool)
|
||||
|
||||
expected_conn_1 = np.array(
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 1, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 1, 1, 0, 0, 1, 0, 1],
|
||||
[1, 1, 1, 0, 0, 0, 0, 1, 0],
|
||||
[1, 1, 0, 0, 0, 0, 1, 0, 1],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool)
|
||||
|
||||
assert_array_equal(convex_hull_object(image, connectivity=1),
|
||||
expected_conn_1)
|
||||
|
||||
expected_conn_2 = np.array(
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 1, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 1, 1, 0, 0, 1, 1, 1],
|
||||
[1, 1, 1, 0, 0, 0, 1, 1, 1],
|
||||
[1, 1, 0, 0, 0, 0, 1, 1, 1],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool)
|
||||
|
||||
assert_array_equal(convex_hull_object(image, connectivity=2),
|
||||
expected_conn_2)
|
||||
|
||||
with testing.raises(ValueError):
|
||||
convex_hull_object(image, connectivity=3)
|
||||
|
||||
out = convex_hull_object(image, connectivity=1)
|
||||
assert_array_equal(out, expected_conn_1)
|
||||
|
||||
|
||||
def test_non_c_contiguous():
|
||||
# 2D Fortran-contiguous
|
||||
image = np.ones((2, 2), order='F', dtype=bool)
|
||||
assert_array_equal(convex_hull_image(image), image)
|
||||
# 3D Fortran-contiguous
|
||||
image = np.ones((2, 2, 2), order='F', dtype=bool)
|
||||
assert_array_equal(convex_hull_image(image), image)
|
||||
# 3D non-contiguous
|
||||
image = np.transpose(np.ones((2, 2, 2), dtype=bool), [0, 2, 1])
|
||||
assert_array_equal(convex_hull_image(image), image)
|
||||
|
||||
|
||||
@testing.fixture
|
||||
def images2d3d():
|
||||
from ...measure.tests.test_regionprops import SAMPLE as image
|
||||
image3d = np.stack((image, image, image))
|
||||
return image, image3d
|
||||
|
||||
|
||||
def test_consistent_2d_3d_hulls(images2d3d):
|
||||
image, image3d = images2d3d
|
||||
chimage = convex_hull_image(image)
|
||||
chimage[8, 0] = True # correct for single point exactly on hull edge
|
||||
chimage3d = convex_hull_image(image3d)
|
||||
assert_array_equal(chimage3d[1], chimage)
|
||||
|
||||
|
||||
def test_few_points():
|
||||
image = np.array(
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.uint8)
|
||||
image3d = np.stack([image, image, image])
|
||||
with testing.assert_warns(UserWarning):
|
||||
chimage3d = convex_hull_image(image3d)
|
||||
assert_array_equal(chimage3d, np.zeros(image3d.shape, dtype=bool))
|
||||
637
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_extrema.py
vendored
Normal file
637
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_extrema.py
vendored
Normal file
@@ -0,0 +1,637 @@
|
||||
import math
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import assert_equal
|
||||
from pytest import raises, warns
|
||||
|
||||
from skimage._shared.testing import expected_warnings
|
||||
from skimage.morphology import extrema
|
||||
|
||||
|
||||
eps = 1e-12
|
||||
|
||||
|
||||
def diff(a, b):
|
||||
a = np.asarray(a, dtype=np.float64)
|
||||
b = np.asarray(b, dtype=np.float64)
|
||||
t = ((a - b) ** 2).sum()
|
||||
return math.sqrt(t)
|
||||
|
||||
|
||||
class TestExtrema():
|
||||
|
||||
def test_saturated_arithmetic(self):
|
||||
"""Adding/subtracting a constant and clipping"""
|
||||
# Test for unsigned integer
|
||||
data = np.array([[250, 251, 5, 5],
|
||||
[100, 200, 253, 252],
|
||||
[4, 10, 1, 3]],
|
||||
dtype=np.uint8)
|
||||
# adding the constant
|
||||
img_constant_added = extrema._add_constant_clip(data, 4)
|
||||
expected = np.array([[254, 255, 9, 9],
|
||||
[104, 204, 255, 255],
|
||||
[8, 14, 5, 7]],
|
||||
dtype=np.uint8)
|
||||
error = diff(img_constant_added, expected)
|
||||
assert error < eps
|
||||
img_constant_subtracted = extrema._subtract_constant_clip(data, 4)
|
||||
expected = np.array([[246, 247, 1, 1],
|
||||
[96, 196, 249, 248],
|
||||
[0, 6, 0, 0]],
|
||||
dtype=np.uint8)
|
||||
error = diff(img_constant_subtracted, expected)
|
||||
assert error < eps
|
||||
|
||||
# Test for signed integer
|
||||
data = np.array([[32767, 32766],
|
||||
[-32768, -32767]],
|
||||
dtype=np.int16)
|
||||
img_constant_added = extrema._add_constant_clip(data, 1)
|
||||
expected = np.array([[32767, 32767],
|
||||
[-32767, -32766]],
|
||||
dtype=np.int16)
|
||||
error = diff(img_constant_added, expected)
|
||||
assert error < eps
|
||||
img_constant_subtracted = extrema._subtract_constant_clip(data, 1)
|
||||
expected = np.array([[32766, 32765],
|
||||
[-32768, -32768]],
|
||||
dtype=np.int16)
|
||||
error = diff(img_constant_subtracted, expected)
|
||||
assert error < eps
|
||||
|
||||
def test_h_maxima(self):
|
||||
"""h-maxima for various data types"""
|
||||
|
||||
data = np.array([[10, 11, 13, 14, 14, 15, 14, 14, 13, 11],
|
||||
[11, 13, 15, 16, 16, 16, 16, 16, 15, 13],
|
||||
[13, 15, 40, 40, 18, 18, 18, 60, 60, 15],
|
||||
[14, 16, 40, 40, 19, 19, 19, 60, 60, 16],
|
||||
[14, 16, 18, 19, 19, 19, 19, 19, 18, 16],
|
||||
[15, 16, 18, 19, 19, 20, 19, 19, 18, 16],
|
||||
[14, 16, 18, 19, 19, 19, 19, 19, 18, 16],
|
||||
[14, 16, 80, 80, 19, 19, 19, 100, 100, 16],
|
||||
[13, 15, 80, 80, 18, 18, 18, 100, 100, 15],
|
||||
[11, 13, 15, 16, 16, 16, 16, 16, 15, 13]],
|
||||
dtype=np.uint8)
|
||||
|
||||
expected_result = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=np.uint8)
|
||||
for dtype in [np.uint8, np.uint64, np.int8, np.int64]:
|
||||
data = data.astype(dtype)
|
||||
out = extrema.h_maxima(data, 40)
|
||||
|
||||
error = diff(expected_result, out)
|
||||
assert error < eps
|
||||
|
||||
def test_h_minima(self):
|
||||
"""h-minima for various data types"""
|
||||
|
||||
data = np.array([[10, 11, 13, 14, 14, 15, 14, 14, 13, 11],
|
||||
[11, 13, 15, 16, 16, 16, 16, 16, 15, 13],
|
||||
[13, 15, 40, 40, 18, 18, 18, 60, 60, 15],
|
||||
[14, 16, 40, 40, 19, 19, 19, 60, 60, 16],
|
||||
[14, 16, 18, 19, 19, 19, 19, 19, 18, 16],
|
||||
[15, 16, 18, 19, 19, 20, 19, 19, 18, 16],
|
||||
[14, 16, 18, 19, 19, 19, 19, 19, 18, 16],
|
||||
[14, 16, 80, 80, 19, 19, 19, 100, 100, 16],
|
||||
[13, 15, 80, 80, 18, 18, 18, 100, 100, 15],
|
||||
[11, 13, 15, 16, 16, 16, 16, 16, 15, 13]],
|
||||
dtype=np.uint8)
|
||||
data = 100 - data
|
||||
expected_result = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=np.uint8)
|
||||
for dtype in [np.uint8, np.uint64, np.int8, np.int64]:
|
||||
data = data.astype(dtype)
|
||||
out = extrema.h_minima(data, 40)
|
||||
|
||||
error = diff(expected_result, out)
|
||||
assert error < eps
|
||||
assert out.dtype == expected_result.dtype
|
||||
|
||||
def test_extrema_float(self):
|
||||
"""specific tests for float type"""
|
||||
data = np.array([[0.10, 0.11, 0.13, 0.14, 0.14, 0.15, 0.14,
|
||||
0.14, 0.13, 0.11],
|
||||
[0.11, 0.13, 0.15, 0.16, 0.16, 0.16, 0.16,
|
||||
0.16, 0.15, 0.13],
|
||||
[0.13, 0.15, 0.40, 0.40, 0.18, 0.18, 0.18,
|
||||
0.60, 0.60, 0.15],
|
||||
[0.14, 0.16, 0.40, 0.40, 0.19, 0.19, 0.19,
|
||||
0.60, 0.60, 0.16],
|
||||
[0.14, 0.16, 0.18, 0.19, 0.19, 0.19, 0.19,
|
||||
0.19, 0.18, 0.16],
|
||||
[0.15, 0.182, 0.18, 0.19, 0.204, 0.20, 0.19,
|
||||
0.19, 0.18, 0.16],
|
||||
[0.14, 0.16, 0.18, 0.19, 0.19, 0.19, 0.19,
|
||||
0.19, 0.18, 0.16],
|
||||
[0.14, 0.16, 0.80, 0.80, 0.19, 0.19, 0.19,
|
||||
1.0, 1.0, 0.16],
|
||||
[0.13, 0.15, 0.80, 0.80, 0.18, 0.18, 0.18,
|
||||
1.0, 1.0, 0.15],
|
||||
[0.11, 0.13, 0.15, 0.16, 0.16, 0.16, 0.16,
|
||||
0.16, 0.15, 0.13]],
|
||||
dtype=np.float32)
|
||||
inverted_data = 1.0 - data
|
||||
|
||||
out = extrema.h_maxima(data, 0.003)
|
||||
expected_result = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=np.uint8)
|
||||
|
||||
error = diff(expected_result, out)
|
||||
assert error < eps
|
||||
|
||||
out = extrema.h_minima(inverted_data, 0.003)
|
||||
error = diff(expected_result, out)
|
||||
assert error < eps
|
||||
|
||||
def test_h_maxima_float_image(self):
|
||||
"""specific tests for h-maxima float image type"""
|
||||
w = 10
|
||||
x, y = np.mgrid[0:w, 0:w]
|
||||
data = 20 - 0.2 * ((x - w / 2) ** 2 + (y - w / 2) ** 2)
|
||||
data[2:4, 2:4] = 40
|
||||
data[2:4, 7:9] = 60
|
||||
data[7:9, 2:4] = 80
|
||||
data[7:9, 7:9] = 100
|
||||
data = data.astype(np.float32)
|
||||
|
||||
expected_result = np.zeros_like(data)
|
||||
expected_result[(data > 19.9)] = 1.0
|
||||
|
||||
for h in [1.0e-12, 1.0e-6, 1.0e-3, 1.0e-2, 1.0e-1, 0.1]:
|
||||
out = extrema.h_maxima(data, h)
|
||||
error = diff(expected_result, out)
|
||||
assert error < eps
|
||||
|
||||
def test_h_maxima_float_h(self):
|
||||
"""specific tests for h-maxima float h parameter"""
|
||||
data = np.array([[0, 0, 0, 0, 0],
|
||||
[0, 3, 3, 3, 0],
|
||||
[0, 3, 4, 3, 0],
|
||||
[0, 3, 3, 3, 0],
|
||||
[0, 0, 0, 0, 0]], dtype=np.uint8)
|
||||
|
||||
h_vals = np.linspace(1.0, 2.0, 100)
|
||||
failures = 0
|
||||
|
||||
for h in h_vals:
|
||||
if h % 1 != 0:
|
||||
msgs = ['possible precision loss converting image']
|
||||
else:
|
||||
msgs = []
|
||||
|
||||
with expected_warnings(msgs):
|
||||
maxima = extrema.h_maxima(data, h)
|
||||
|
||||
if (maxima[2, 2] == 0):
|
||||
failures += 1
|
||||
|
||||
assert (failures == 0)
|
||||
|
||||
def test_h_maxima_large_h(self):
|
||||
"""test that h-maxima works correctly for large h"""
|
||||
data = np.array([[10, 10, 10, 10, 10],
|
||||
[10, 13, 13, 13, 10],
|
||||
[10, 13, 14, 13, 10],
|
||||
[10, 13, 13, 13, 10],
|
||||
[10, 10, 10, 10, 10]], dtype=np.uint8)
|
||||
|
||||
maxima = extrema.h_maxima(data, 5)
|
||||
assert (np.sum(maxima) == 0)
|
||||
|
||||
data = np.array([[10, 10, 10, 10, 10],
|
||||
[10, 13, 13, 13, 10],
|
||||
[10, 13, 14, 13, 10],
|
||||
[10, 13, 13, 13, 10],
|
||||
[10, 10, 10, 10, 10]], dtype=np.float32)
|
||||
|
||||
maxima = extrema.h_maxima(data, 5.0)
|
||||
assert (np.sum(maxima) == 0)
|
||||
|
||||
def test_h_minima_float_image(self):
|
||||
"""specific tests for h-minima float image type"""
|
||||
w = 10
|
||||
x, y = np.mgrid[0:w, 0:w]
|
||||
data = 180 + 0.2 * ((x - w / 2) ** 2 + (y - w / 2) ** 2)
|
||||
data[2:4, 2:4] = 160
|
||||
data[2:4, 7:9] = 140
|
||||
data[7:9, 2:4] = 120
|
||||
data[7:9, 7:9] = 100
|
||||
data = data.astype(np.float32)
|
||||
|
||||
expected_result = np.zeros_like(data)
|
||||
expected_result[(data < 180.1)] = 1.0
|
||||
|
||||
for h in [1.0e-12, 1.0e-6, 1.0e-3, 1.0e-2, 1.0e-1, 0.1]:
|
||||
out = extrema.h_minima(data, h)
|
||||
error = diff(expected_result, out)
|
||||
assert error < eps
|
||||
|
||||
def test_h_minima_float_h(self):
|
||||
"""specific tests for h-minima float h parameter"""
|
||||
data = np.array([[4, 4, 4, 4, 4],
|
||||
[4, 1, 1, 1, 4],
|
||||
[4, 1, 0, 1, 4],
|
||||
[4, 1, 1, 1, 4],
|
||||
[4, 4, 4, 4, 4]], dtype=np.uint8)
|
||||
|
||||
h_vals = np.linspace(1.0, 2.0, 100)
|
||||
failures = 0
|
||||
for h in h_vals:
|
||||
if h % 1 != 0:
|
||||
msgs = ['possible precision loss converting image']
|
||||
else:
|
||||
msgs = []
|
||||
|
||||
with expected_warnings(msgs):
|
||||
minima = extrema.h_minima(data, h)
|
||||
|
||||
if (minima[2, 2] == 0):
|
||||
failures += 1
|
||||
|
||||
assert (failures == 0)
|
||||
|
||||
def test_h_minima_large_h(self):
|
||||
"""test that h-minima works correctly for large h"""
|
||||
data = np.array([[14, 14, 14, 14, 14],
|
||||
[14, 11, 11, 11, 14],
|
||||
[14, 11, 10, 11, 14],
|
||||
[14, 11, 11, 11, 14],
|
||||
[14, 14, 14, 14, 14]], dtype=np.uint8)
|
||||
|
||||
maxima = extrema.h_minima(data, 5)
|
||||
assert (np.sum(maxima) == 0)
|
||||
|
||||
data = np.array([[14, 14, 14, 14, 14],
|
||||
[14, 11, 11, 11, 14],
|
||||
[14, 11, 10, 11, 14],
|
||||
[14, 11, 11, 11, 14],
|
||||
[14, 14, 14, 14, 14]], dtype=np.float32)
|
||||
|
||||
maxima = extrema.h_minima(data, 5.0)
|
||||
assert (np.sum(maxima) == 0)
|
||||
|
||||
|
||||
class TestLocalMaxima(unittest.TestCase):
|
||||
"""Some tests for local_minima are included as well."""
|
||||
|
||||
supported_dtypes = [
|
||||
np.uint8, np.uint16, np.uint32, np.uint64,
|
||||
np.int8, np.int16, np.int32, np.int64,
|
||||
np.float32, np.float64
|
||||
]
|
||||
image = np.array(
|
||||
[[1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 0, 2, 0, 0, 3, 3, 0, 0, 4, 0, 2, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 4, 4, 0, 3, 0, 0, 0],
|
||||
[0, 2, 0, 1, 0, 2, 1, 0, 0, 0, 0, 3, 0, 0, 0],
|
||||
[0, 0, 2, 0, 2, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0]],
|
||||
dtype=np.uint8
|
||||
)
|
||||
# Connectivity 2, maxima can touch border, returned with default values
|
||||
expected_default = np.array(
|
||||
[[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=bool
|
||||
)
|
||||
# Connectivity 1 (cross), maxima can touch border
|
||||
expected_cross = np.array(
|
||||
[[1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0],
|
||||
[0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=bool
|
||||
)
|
||||
|
||||
def test_empty(self):
|
||||
"""Test result with empty image."""
|
||||
result = extrema.local_maxima(np.array([[]]), indices=False)
|
||||
assert result.size == 0
|
||||
assert result.dtype == bool
|
||||
assert result.shape == (1, 0)
|
||||
|
||||
result = extrema.local_maxima(np.array([]), indices=True)
|
||||
assert isinstance(result, tuple)
|
||||
assert len(result) == 1
|
||||
assert result[0].size == 0
|
||||
assert result[0].dtype == np.intp
|
||||
|
||||
result = extrema.local_maxima(np.array([[]]), indices=True)
|
||||
assert isinstance(result, tuple)
|
||||
assert len(result) == 2
|
||||
assert result[0].size == 0
|
||||
assert result[0].dtype == np.intp
|
||||
assert result[1].size == 0
|
||||
assert result[1].dtype == np.intp
|
||||
|
||||
def test_dtypes(self):
|
||||
"""Test results with default configuration for all supported dtypes."""
|
||||
for dtype in self.supported_dtypes:
|
||||
result = extrema.local_maxima(self.image.astype(dtype))
|
||||
assert result.dtype == bool
|
||||
assert_equal(result, self.expected_default)
|
||||
|
||||
def test_dtypes_old(self):
|
||||
"""
|
||||
Test results with default configuration and data copied from old unit
|
||||
tests for all supported dtypes.
|
||||
"""
|
||||
data = np.array(
|
||||
[[10, 11, 13, 14, 14, 15, 14, 14, 13, 11],
|
||||
[11, 13, 15, 16, 16, 16, 16, 16, 15, 13],
|
||||
[13, 15, 40, 40, 18, 18, 18, 60, 60, 15],
|
||||
[14, 16, 40, 40, 19, 19, 19, 60, 60, 16],
|
||||
[14, 16, 18, 19, 19, 19, 19, 19, 18, 16],
|
||||
[15, 16, 18, 19, 19, 20, 19, 19, 18, 16],
|
||||
[14, 16, 18, 19, 19, 19, 19, 19, 18, 16],
|
||||
[14, 16, 80, 80, 19, 19, 19, 100, 100, 16],
|
||||
[13, 15, 80, 80, 18, 18, 18, 100, 100, 15],
|
||||
[11, 13, 15, 16, 16, 16, 16, 16, 15, 13]],
|
||||
dtype=np.uint8
|
||||
)
|
||||
expected = np.array(
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=bool
|
||||
)
|
||||
for dtype in self.supported_dtypes:
|
||||
image = data.astype(dtype)
|
||||
result = extrema.local_maxima(image)
|
||||
assert result.dtype == bool
|
||||
assert_equal(result, expected)
|
||||
|
||||
def test_connectivity(self):
|
||||
"""Test results if footprint is a scalar."""
|
||||
# Connectivity 1: generates cross shaped footprint
|
||||
result_conn1 = extrema.local_maxima(self.image, connectivity=1)
|
||||
assert result_conn1.dtype == bool
|
||||
assert_equal(result_conn1, self.expected_cross)
|
||||
|
||||
# Connectivity 2: generates square shaped footprint
|
||||
result_conn2 = extrema.local_maxima(self.image, connectivity=2)
|
||||
assert result_conn2.dtype == bool
|
||||
assert_equal(result_conn2, self.expected_default)
|
||||
|
||||
# Connectivity 3: generates square shaped footprint
|
||||
result_conn3 = extrema.local_maxima(self.image, connectivity=3)
|
||||
assert result_conn3.dtype == bool
|
||||
assert_equal(result_conn3, self.expected_default)
|
||||
|
||||
def test_footprint(self):
|
||||
"""Test results if footprint is given."""
|
||||
footprint_cross = np.array(
|
||||
[[0, 1, 0], [1, 1, 1], [0, 1, 0]], dtype=bool)
|
||||
result_footprint_cross = extrema.local_maxima(
|
||||
self.image, footprint=footprint_cross)
|
||||
assert result_footprint_cross.dtype == bool
|
||||
assert_equal(result_footprint_cross, self.expected_cross)
|
||||
|
||||
for footprint in [
|
||||
((True,) * 3,) * 3,
|
||||
np.ones((3, 3), dtype=np.float64),
|
||||
np.ones((3, 3), dtype=np.uint8),
|
||||
np.ones((3, 3), dtype=bool),
|
||||
]:
|
||||
# Test different dtypes for footprint which expects a boolean array
|
||||
# but will accept and convert other types if possible
|
||||
result_footprint_square = extrema.local_maxima(
|
||||
self.image, footprint=footprint
|
||||
)
|
||||
assert result_footprint_square.dtype == bool
|
||||
assert_equal(result_footprint_square, self.expected_default)
|
||||
|
||||
footprint_x = np.array([[1, 0, 1], [0, 1, 0], [1, 0, 1]], dtype=bool)
|
||||
expected_footprint_x = np.array(
|
||||
[[1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0],
|
||||
[1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0]],
|
||||
dtype=bool
|
||||
)
|
||||
result_footprint_x = extrema.local_maxima(self.image,
|
||||
footprint=footprint_x)
|
||||
assert result_footprint_x.dtype == bool
|
||||
assert_equal(result_footprint_x, expected_footprint_x)
|
||||
|
||||
def test_indices(self):
|
||||
"""Test output if indices of peaks are desired."""
|
||||
# Connectivity 1
|
||||
expected_conn1 = np.nonzero(self.expected_cross)
|
||||
result_conn1 = extrema.local_maxima(self.image, connectivity=1,
|
||||
indices=True)
|
||||
assert_equal(result_conn1, expected_conn1)
|
||||
|
||||
# Connectivity 2
|
||||
expected_conn2 = np.nonzero(self.expected_default)
|
||||
result_conn2 = extrema.local_maxima(self.image, connectivity=2,
|
||||
indices=True)
|
||||
assert_equal(result_conn2, expected_conn2)
|
||||
|
||||
def test_allow_borders(self):
|
||||
"""Test maxima detection at the image border."""
|
||||
# Use connectivity 1 to allow many maxima, only filtering at border is
|
||||
# of interest
|
||||
result_with_boder = extrema.local_maxima(
|
||||
self.image, connectivity=1, allow_borders=True)
|
||||
assert result_with_boder.dtype == bool
|
||||
assert_equal(result_with_boder, self.expected_cross)
|
||||
|
||||
expected_without_border = np.array(
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0],
|
||||
[0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=bool
|
||||
)
|
||||
result_without_border = extrema.local_maxima(
|
||||
self.image, connectivity=1, allow_borders=False)
|
||||
assert result_with_boder.dtype == bool
|
||||
assert_equal(result_without_border, expected_without_border)
|
||||
|
||||
def test_nd(self):
|
||||
"""Test one- and three-dimensional case."""
|
||||
# One-dimension
|
||||
x_1d = np.array([1, 1, 0, 1, 2, 3, 0, 2, 1, 2, 0])
|
||||
expected_1d = np.array([1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0],
|
||||
dtype=bool)
|
||||
result_1d = extrema.local_maxima(x_1d)
|
||||
assert result_1d.dtype == bool
|
||||
assert_equal(result_1d, expected_1d)
|
||||
|
||||
# 3-dimensions (adapted from old unit test)
|
||||
x_3d = np.zeros((8, 8, 8), dtype=np.uint8)
|
||||
expected_3d = np.zeros((8, 8, 8), dtype=bool)
|
||||
# first maximum: only one pixel
|
||||
x_3d[1, 1:3, 1:3] = 100
|
||||
x_3d[2, 2, 2] = 200
|
||||
x_3d[3, 1:3, 1:3] = 100
|
||||
expected_3d[2, 2, 2] = 1
|
||||
# second maximum: three pixels in z-direction
|
||||
x_3d[5:8, 1, 1] = 200
|
||||
expected_3d[5:8, 1, 1] = 1
|
||||
# third: two maxima in 0 and 3.
|
||||
x_3d[0, 5:8, 5:8] = 200
|
||||
x_3d[1, 6, 6] = 100
|
||||
x_3d[2, 5:7, 5:7] = 200
|
||||
x_3d[0:3, 5:8, 5:8] += 50
|
||||
expected_3d[0, 5:8, 5:8] = 1
|
||||
expected_3d[2, 5:7, 5:7] = 1
|
||||
# four : one maximum in the corner of the square
|
||||
x_3d[6:8, 6:8, 6:8] = 200
|
||||
x_3d[7, 7, 7] = 255
|
||||
expected_3d[7, 7, 7] = 1
|
||||
result_3d = extrema.local_maxima(x_3d)
|
||||
assert result_3d.dtype == bool
|
||||
assert_equal(result_3d, expected_3d)
|
||||
|
||||
def test_constant(self):
|
||||
"""Test behaviour for 'flat' images."""
|
||||
const_image = np.full((7, 6), 42, dtype=np.uint8)
|
||||
expected = np.zeros((7, 6), dtype=np.uint8)
|
||||
for dtype in self.supported_dtypes:
|
||||
const_image = const_image.astype(dtype)
|
||||
# test for local maxima
|
||||
result = extrema.local_maxima(const_image)
|
||||
assert result.dtype == bool
|
||||
assert_equal(result, expected)
|
||||
# test for local minima
|
||||
result = extrema.local_minima(const_image)
|
||||
assert result.dtype == bool
|
||||
assert_equal(result, expected)
|
||||
|
||||
def test_extrema_float(self):
|
||||
"""Specific tests for float type."""
|
||||
# Copied from old unit test for local_maxma
|
||||
image = np.array(
|
||||
[[0.10, 0.11, 0.13, 0.14, 0.14, 0.15, 0.14, 0.14, 0.13, 0.11],
|
||||
[0.11, 0.13, 0.15, 0.16, 0.16, 0.16, 0.16, 0.16, 0.15, 0.13],
|
||||
[0.13, 0.15, 0.40, 0.40, 0.18, 0.18, 0.18, 0.60, 0.60, 0.15],
|
||||
[0.14, 0.16, 0.40, 0.40, 0.19, 0.19, 0.19, 0.60, 0.60, 0.16],
|
||||
[0.14, 0.16, 0.18, 0.19, 0.19, 0.19, 0.19, 0.19, 0.18, 0.16],
|
||||
[0.15, 0.182, 0.18, 0.19, 0.204, 0.20, 0.19, 0.19, 0.18, 0.16],
|
||||
[0.14, 0.16, 0.18, 0.19, 0.19, 0.19, 0.19, 0.19, 0.18, 0.16],
|
||||
[0.14, 0.16, 0.80, 0.80, 0.19, 0.19, 0.19, 1.0, 1.0, 0.16],
|
||||
[0.13, 0.15, 0.80, 0.80, 0.18, 0.18, 0.18, 1.0, 1.0, 0.15],
|
||||
[0.11, 0.13, 0.15, 0.16, 0.16, 0.16, 0.16, 0.16, 0.15, 0.13]],
|
||||
dtype=np.float32
|
||||
)
|
||||
inverted_image = 1.0 - image
|
||||
expected_result = np.array(
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=bool
|
||||
)
|
||||
|
||||
# Test for local maxima with automatic step calculation
|
||||
result = extrema.local_maxima(image)
|
||||
assert result.dtype == bool
|
||||
assert_equal(result, expected_result)
|
||||
|
||||
# Test for local minima with automatic step calculation
|
||||
result = extrema.local_minima(inverted_image)
|
||||
assert result.dtype == bool
|
||||
assert_equal(result, expected_result)
|
||||
|
||||
def test_exceptions(self):
|
||||
"""Test if input validation triggers correct exceptions."""
|
||||
# Mismatching number of dimensions
|
||||
with raises(ValueError, match="number of dimensions"):
|
||||
extrema.local_maxima(
|
||||
self.image, footprint=np.ones((3, 3, 3), dtype=bool))
|
||||
with raises(ValueError, match="number of dimensions"):
|
||||
extrema.local_maxima(
|
||||
self.image, footprint=np.ones((3,), dtype=bool))
|
||||
|
||||
# All dimensions in footprint must be of size 3
|
||||
with raises(ValueError, match="dimension size"):
|
||||
extrema.local_maxima(
|
||||
self.image, footprint=np.ones((2, 3), dtype=bool))
|
||||
with raises(ValueError, match="dimension size"):
|
||||
extrema.local_maxima(
|
||||
self.image, footprint=np.ones((5, 5), dtype=bool))
|
||||
|
||||
with raises(TypeError, match="float16 which is not supported"):
|
||||
extrema.local_maxima(np.empty(1, dtype=np.float16))
|
||||
|
||||
def test_small_array(self):
|
||||
"""Test output for arrays with dimension smaller 3.
|
||||
|
||||
If any dimension of an array is smaller than 3 and `allow_borders` is
|
||||
false a footprint, which has at least 3 elements in each
|
||||
dimension, can't be applied. This is an implementation detail so
|
||||
`local_maxima` should still return valid output (see gh-3261).
|
||||
|
||||
If `allow_borders` is true the array is padded internally and there is
|
||||
no problem.
|
||||
"""
|
||||
warning_msg = "maxima can't exist .* any dimension smaller 3 .*"
|
||||
x = np.array([0, 1])
|
||||
extrema.local_maxima(x, allow_borders=True) # no warning
|
||||
with warns(UserWarning, match=warning_msg):
|
||||
result = extrema.local_maxima(x, allow_borders=False)
|
||||
assert_equal(result, [0, 0])
|
||||
assert result.dtype == bool
|
||||
|
||||
x = np.array([[1, 2], [2, 2]])
|
||||
extrema.local_maxima(x, allow_borders=True, indices=True) # no warning
|
||||
with warns(UserWarning, match=warning_msg):
|
||||
result = extrema.local_maxima(x, allow_borders=False, indices=True)
|
||||
assert_equal(result, np.zeros((2, 0), dtype=np.intp))
|
||||
assert result[0].dtype == np.intp
|
||||
assert result[1].dtype == np.intp
|
||||
286
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_flood_fill.py
vendored
Normal file
286
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_flood_fill.py
vendored
Normal file
@@ -0,0 +1,286 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from skimage.morphology import flood, flood_fill
|
||||
|
||||
eps = 1e-12
|
||||
|
||||
|
||||
def test_empty_input():
|
||||
# Test shortcut
|
||||
output = flood_fill(np.empty(0), (), 2)
|
||||
assert output.size == 0
|
||||
|
||||
# Boolean output type
|
||||
assert flood(np.empty(0), ()).dtype == bool
|
||||
|
||||
# Maintain shape, even with zero size present
|
||||
assert flood(np.empty((20, 0, 4)), ()).shape == (20, 0, 4)
|
||||
|
||||
|
||||
def test_float16():
|
||||
image = np.array([9., 0.1, 42], dtype=np.float16)
|
||||
with pytest.raises(TypeError, match="dtype of `image` is float16"):
|
||||
flood_fill(image, 0, 1)
|
||||
|
||||
|
||||
def test_overrange_tolerance_int():
|
||||
image = np.arange(256, dtype=np.uint8).reshape((8, 8, 4))
|
||||
expected = np.zeros_like(image)
|
||||
|
||||
output = flood_fill(image, (7, 7, 3), 0, tolerance=379)
|
||||
|
||||
np.testing.assert_equal(output, expected)
|
||||
|
||||
|
||||
def test_overrange_tolerance_float():
|
||||
max_value = np.finfo(np.float32).max
|
||||
|
||||
image = np.random.uniform(size=(64, 64), low=-1., high=1.).astype(
|
||||
np.float32)
|
||||
image *= max_value
|
||||
|
||||
expected = np.ones_like(image)
|
||||
output = flood_fill(image, (0, 1), 1., tolerance=max_value * 10)
|
||||
|
||||
np.testing.assert_equal(output, expected)
|
||||
|
||||
|
||||
def test_inplace_int():
|
||||
image = np.array([[0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 1, 0, 2, 2, 0],
|
||||
[0, 1, 1, 0, 2, 2, 0],
|
||||
[1, 0, 0, 0, 0, 0, 3],
|
||||
[0, 1, 1, 1, 3, 3, 4]])
|
||||
|
||||
flood_fill(image, (0, 0), 5, in_place=True)
|
||||
|
||||
expected = np.array([[5, 5, 5, 5, 5, 5, 5],
|
||||
[5, 1, 1, 5, 2, 2, 5],
|
||||
[5, 1, 1, 5, 2, 2, 5],
|
||||
[1, 5, 5, 5, 5, 5, 3],
|
||||
[5, 1, 1, 1, 3, 3, 4]])
|
||||
|
||||
np.testing.assert_array_equal(image, expected)
|
||||
|
||||
|
||||
def test_inplace_float():
|
||||
image = np.array([[0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 1, 0, 2, 2, 0],
|
||||
[0, 1, 1, 0, 2, 2, 0],
|
||||
[1, 0, 0, 0, 0, 0, 3],
|
||||
[0, 1, 1, 1, 3, 3, 4]], dtype=np.float32)
|
||||
|
||||
flood_fill(image, (0, 0), 5, in_place=True)
|
||||
|
||||
expected = np.array([[5., 5., 5., 5., 5., 5., 5.],
|
||||
[5., 1., 1., 5., 2., 2., 5.],
|
||||
[5., 1., 1., 5., 2., 2., 5.],
|
||||
[1., 5., 5., 5., 5., 5., 3.],
|
||||
[5., 1., 1., 1., 3., 3., 4.]], dtype=np.float32)
|
||||
|
||||
np.testing.assert_allclose(image, expected)
|
||||
|
||||
|
||||
def test_inplace_noncontiguous():
|
||||
image = np.array([[0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 1, 0, 2, 2, 0],
|
||||
[0, 1, 1, 0, 2, 2, 0],
|
||||
[1, 0, 0, 0, 0, 0, 3],
|
||||
[0, 1, 1, 1, 3, 3, 4]])
|
||||
|
||||
# Transpose is noncontiguous
|
||||
image2 = image[::2, ::2]
|
||||
|
||||
flood_fill(image2, (0, 0), 5, in_place=True)
|
||||
|
||||
# The inplace modified result
|
||||
expected2 = np.array([[5, 5, 5, 5],
|
||||
[5, 1, 2, 5],
|
||||
[5, 1, 3, 4]])
|
||||
|
||||
np.testing.assert_allclose(image2, expected2)
|
||||
|
||||
# Projected back through the view, `image` also modified
|
||||
expected = np.array([[5, 0, 5, 0, 5, 0, 5],
|
||||
[0, 1, 1, 0, 2, 2, 0],
|
||||
[5, 1, 1, 0, 2, 2, 5],
|
||||
[1, 0, 0, 0, 0, 0, 3],
|
||||
[5, 1, 1, 1, 3, 3, 4]])
|
||||
|
||||
np.testing.assert_allclose(image, expected)
|
||||
|
||||
|
||||
def test_1d():
|
||||
image = np.arange(11)
|
||||
expected = np.array([0, 1, -20, -20, -20, -20, -20, -20, -20, 9, 10])
|
||||
|
||||
output = flood_fill(image, 5, -20, tolerance=3)
|
||||
output2 = flood_fill(image, (5,), -20, tolerance=3)
|
||||
|
||||
np.testing.assert_equal(output, expected)
|
||||
np.testing.assert_equal(output, output2)
|
||||
|
||||
|
||||
def test_wraparound():
|
||||
# If the borders (or neighbors) aren't correctly accounted for, this fails,
|
||||
# because the algorithm uses an ravelled array.
|
||||
test = np.zeros((5, 7), dtype=np.float64)
|
||||
test[:, 3] = 100
|
||||
|
||||
expected = np.array([[-1., -1., -1., 100., 0., 0., 0.],
|
||||
[-1., -1., -1., 100., 0., 0., 0.],
|
||||
[-1., -1., -1., 100., 0., 0., 0.],
|
||||
[-1., -1., -1., 100., 0., 0., 0.],
|
||||
[-1., -1., -1., 100., 0., 0., 0.]])
|
||||
|
||||
np.testing.assert_equal(flood_fill(test, (0, 0), -1), expected)
|
||||
|
||||
|
||||
def test_neighbors():
|
||||
# This test will only pass if the neighbors are exactly correct
|
||||
test = np.zeros((5, 7), dtype=np.float64)
|
||||
test[:, 3] = 100
|
||||
|
||||
expected = np.array([[0, 0, 0, 255, 0, 0, 0],
|
||||
[0, 0, 0, 255, 0, 0, 0],
|
||||
[0, 0, 0, 255, 0, 0, 0],
|
||||
[0, 0, 0, 255, 0, 0, 0],
|
||||
[0, 0, 0, 255, 0, 0, 0]])
|
||||
output = flood_fill(test, (0, 3), 255)
|
||||
|
||||
np.testing.assert_equal(output, expected)
|
||||
|
||||
test[2] = 100
|
||||
expected[2] = 255
|
||||
|
||||
output2 = flood_fill(test, (2, 3), 255)
|
||||
|
||||
np.testing.assert_equal(output2, expected)
|
||||
|
||||
|
||||
def test_footprint():
|
||||
# Basic tests for nonstandard footprints
|
||||
footprint = np.array([[0, 1, 1],
|
||||
[0, 1, 1],
|
||||
[0, 0, 0]]) # Cannot grow left or down
|
||||
|
||||
output = flood_fill(np.zeros((5, 6), dtype=np.uint8), (3, 1), 255,
|
||||
footprint=footprint)
|
||||
|
||||
expected = np.array([[0, 255, 255, 255, 255, 255],
|
||||
[0, 255, 255, 255, 255, 255],
|
||||
[0, 255, 255, 255, 255, 255],
|
||||
[0, 255, 255, 255, 255, 255],
|
||||
[0, 0, 0, 0, 0, 0]], dtype=np.uint8)
|
||||
|
||||
np.testing.assert_equal(output, expected)
|
||||
|
||||
footprint = np.array([[0, 0, 0],
|
||||
[1, 1, 0],
|
||||
[1, 1, 0]]) # Cannot grow right or up
|
||||
|
||||
output = flood_fill(np.zeros((5, 6), dtype=np.uint8), (1, 4), 255,
|
||||
footprint=footprint)
|
||||
|
||||
expected = np.array([[ 0, 0, 0, 0, 0, 0],
|
||||
[255, 255, 255, 255, 255, 0],
|
||||
[255, 255, 255, 255, 255, 0],
|
||||
[255, 255, 255, 255, 255, 0],
|
||||
[255, 255, 255, 255, 255, 0]], dtype=np.uint8)
|
||||
|
||||
np.testing.assert_equal(output, expected)
|
||||
|
||||
|
||||
def test_basic_nd():
|
||||
for dimension in (3, 4, 5):
|
||||
shape = (5,) * dimension
|
||||
hypercube = np.zeros(shape)
|
||||
slice_mid = tuple(slice(1, -1, None) for dim in range(dimension))
|
||||
hypercube[slice_mid] = 1 # sum is 3**dimension
|
||||
filled = flood_fill(hypercube, (2,) * dimension, 2)
|
||||
|
||||
# Test that the middle sum is correct
|
||||
assert filled.sum() == 3**dimension * 2
|
||||
|
||||
# Test that the entire array is as expected
|
||||
np.testing.assert_equal(
|
||||
filled, np.pad(np.ones((3,) * dimension) * 2, 1, 'constant'))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("tolerance", [None, 0])
|
||||
def test_f_order(tolerance):
|
||||
image = np.array([
|
||||
[0, 0, 0, 0],
|
||||
[1, 0, 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
], order="F")
|
||||
expected = np.array([
|
||||
[0, 0, 0, 0],
|
||||
[1, 0, 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
], dtype=bool)
|
||||
|
||||
mask = flood(image, seed_point=(1, 0), tolerance=tolerance)
|
||||
np.testing.assert_array_equal(expected, mask)
|
||||
|
||||
mask = flood(image, seed_point=(2, 1), tolerance=tolerance)
|
||||
np.testing.assert_array_equal(expected, mask)
|
||||
|
||||
|
||||
def test_negative_indexing_seed_point():
|
||||
image = np.array([[0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 1, 0, 2, 2, 0],
|
||||
[0, 1, 1, 0, 2, 2, 0],
|
||||
[1, 0, 0, 0, 0, 0, 3],
|
||||
[0, 1, 1, 1, 3, 3, 4]], dtype=np.float32)
|
||||
|
||||
expected = np.array([[5., 5., 5., 5., 5., 5., 5.],
|
||||
[5., 1., 1., 5., 2., 2., 5.],
|
||||
[5., 1., 1., 5., 2., 2., 5.],
|
||||
[1., 5., 5., 5., 5., 5., 3.],
|
||||
[5., 1., 1., 1., 3., 3., 4.]], dtype=np.float32)
|
||||
|
||||
image = flood_fill(image, (0, -1), 5)
|
||||
|
||||
np.testing.assert_allclose(image, expected)
|
||||
|
||||
|
||||
def test_non_adjacent_footprint():
|
||||
# Basic tests for non-adjacent footprints
|
||||
footprint = np.array([[1, 0, 0, 0, 1],
|
||||
[0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 0, 1]])
|
||||
|
||||
output = flood_fill(np.zeros((5, 6), dtype=np.uint8), (2, 3), 255,
|
||||
footprint=footprint)
|
||||
|
||||
expected = np.array([[0, 255, 0, 0, 0, 255],
|
||||
[0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 255, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0],
|
||||
[0, 255, 0, 0, 0, 255]], dtype=np.uint8)
|
||||
|
||||
np.testing.assert_equal(output, expected)
|
||||
|
||||
footprint = np.array([[1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1]])
|
||||
|
||||
image = np.zeros((5, 10), dtype=np.uint8)
|
||||
image[:, (3, 7, 8)] = 100
|
||||
|
||||
output = flood_fill(image, (0, 0), 255, footprint=footprint)
|
||||
|
||||
expected = np.array([[255, 255, 255, 100, 255, 255, 255, 100, 100, 0],
|
||||
[255, 255, 255, 100, 255, 255, 255, 100, 100, 0],
|
||||
[255, 255, 255, 100, 255, 255, 255, 100, 100, 0],
|
||||
[255, 255, 255, 100, 255, 255, 255, 100, 100, 0],
|
||||
[255, 255, 255, 100, 255, 255, 255, 100, 100, 0]],
|
||||
dtype=np.uint8)
|
||||
|
||||
np.testing.assert_equal(output, expected)
|
||||
238
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_footprints.py
vendored
Normal file
238
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_footprints.py
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
"""
|
||||
Tests for Morphological footprints
|
||||
(skimage.morphology.footprint)
|
||||
|
||||
Author: Damian Eads
|
||||
"""
|
||||
import numpy as np
|
||||
import pytest
|
||||
from numpy.testing import assert_equal
|
||||
|
||||
from skimage._shared.testing import fetch
|
||||
from skimage.morphology import footprints
|
||||
|
||||
|
||||
class TestFootprints:
|
||||
|
||||
def test_square_footprint(self):
|
||||
"""Test square footprints"""
|
||||
for k in range(0, 5):
|
||||
actual_mask = footprints.square(k)
|
||||
expected_mask = np.ones((k, k), dtype='uint8')
|
||||
assert_equal(expected_mask, actual_mask)
|
||||
|
||||
def test_rectangle_footprint(self):
|
||||
"""Test rectangle footprints"""
|
||||
for i in range(0, 5):
|
||||
for j in range(0, 5):
|
||||
actual_mask = footprints.rectangle(i, j)
|
||||
expected_mask = np.ones((i, j), dtype='uint8')
|
||||
assert_equal(expected_mask, actual_mask)
|
||||
|
||||
def test_cube_footprint(self):
|
||||
"""Test cube footprints"""
|
||||
for k in range(0, 5):
|
||||
actual_mask = footprints.cube(k)
|
||||
expected_mask = np.ones((k, k, k), dtype='uint8')
|
||||
assert_equal(expected_mask, actual_mask)
|
||||
|
||||
def strel_worker(self, fn, func):
|
||||
matlab_masks = np.load(fetch(fn))
|
||||
k = 0
|
||||
for arrname in sorted(matlab_masks):
|
||||
expected_mask = matlab_masks[arrname]
|
||||
actual_mask = func(k)
|
||||
if expected_mask.shape == (1,):
|
||||
expected_mask = expected_mask[:, np.newaxis]
|
||||
assert_equal(expected_mask, actual_mask)
|
||||
k = k + 1
|
||||
|
||||
def strel_worker_3d(self, fn, func):
|
||||
matlab_masks = np.load(fetch(fn))
|
||||
k = 0
|
||||
for arrname in sorted(matlab_masks):
|
||||
expected_mask = matlab_masks[arrname]
|
||||
actual_mask = func(k)
|
||||
if expected_mask.shape == (1,):
|
||||
expected_mask = expected_mask[:, np.newaxis]
|
||||
# Test center slice for each dimension. This gives a good
|
||||
# indication of validity without the need for a 3D reference
|
||||
# mask.
|
||||
c = int(expected_mask.shape[0]/2)
|
||||
assert_equal(expected_mask, actual_mask[c, :, :])
|
||||
assert_equal(expected_mask, actual_mask[:, c, :])
|
||||
assert_equal(expected_mask, actual_mask[:, :, c])
|
||||
k = k + 1
|
||||
|
||||
def test_footprint_disk(self):
|
||||
"""Test disk footprints"""
|
||||
self.strel_worker("data/disk-matlab-output.npz", footprints.disk)
|
||||
|
||||
def test_footprint_diamond(self):
|
||||
"""Test diamond footprints"""
|
||||
self.strel_worker("data/diamond-matlab-output.npz", footprints.diamond)
|
||||
|
||||
def test_footprint_ball(self):
|
||||
"""Test ball footprints"""
|
||||
self.strel_worker_3d("data/disk-matlab-output.npz", footprints.ball)
|
||||
|
||||
def test_footprint_octahedron(self):
|
||||
"""Test octahedron footprints"""
|
||||
self.strel_worker_3d("data/diamond-matlab-output.npz",
|
||||
footprints.octahedron)
|
||||
|
||||
def test_footprint_octagon(self):
|
||||
"""Test octagon footprints"""
|
||||
expected_mask1 = np.array([[0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0]],
|
||||
dtype=np.uint8)
|
||||
actual_mask1 = footprints.octagon(5, 3)
|
||||
expected_mask2 = np.array([[0, 1, 0],
|
||||
[1, 1, 1],
|
||||
[0, 1, 0]], dtype=np.uint8)
|
||||
actual_mask2 = footprints.octagon(1, 1)
|
||||
assert_equal(expected_mask1, actual_mask1)
|
||||
assert_equal(expected_mask2, actual_mask2)
|
||||
|
||||
def test_footprint_ellipse(self):
|
||||
"""Test ellipse footprints"""
|
||||
expected_mask1 = np.array([[0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0]],
|
||||
dtype=np.uint8)
|
||||
actual_mask1 = footprints.ellipse(5, 3)
|
||||
expected_mask2 = np.array([[1, 1, 1],
|
||||
[1, 1, 1],
|
||||
[1, 1, 1]], dtype=np.uint8)
|
||||
actual_mask2 = footprints.ellipse(1, 1)
|
||||
assert_equal(expected_mask1, actual_mask1)
|
||||
assert_equal(expected_mask2, actual_mask2)
|
||||
assert_equal(expected_mask1, footprints.ellipse(3, 5).T)
|
||||
assert_equal(expected_mask2, footprints.ellipse(1, 1).T)
|
||||
|
||||
def test_footprint_star(self):
|
||||
"""Test star footprints"""
|
||||
expected_mask1 = np.array([[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=np.uint8)
|
||||
actual_mask1 = footprints.star(4)
|
||||
expected_mask2 = np.array([[1, 1, 1],
|
||||
[1, 1, 1],
|
||||
[1, 1, 1]], dtype=np.uint8)
|
||||
actual_mask2 = footprints.star(1)
|
||||
assert_equal(expected_mask1, actual_mask1)
|
||||
assert_equal(expected_mask2, actual_mask2)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'function, args, supports_sequence_decomposition',
|
||||
[
|
||||
(footprints.disk, (3,), True),
|
||||
(footprints.ball, (3,), True),
|
||||
(footprints.square, (3,), True),
|
||||
(footprints.cube, (3,), True),
|
||||
(footprints.diamond, (3,), True),
|
||||
(footprints.octahedron, (3,), True),
|
||||
(footprints.rectangle, (3, 4), True),
|
||||
(footprints.ellipse, (3, 4), False),
|
||||
(footprints.octagon, (3, 4), True),
|
||||
(footprints.star, (3,), False),
|
||||
]
|
||||
)
|
||||
@pytest.mark.parametrize("dtype", [np.uint8, np.float64])
|
||||
def test_footprint_dtype(function, args, supports_sequence_decomposition,
|
||||
dtype):
|
||||
# make sure footprint dtype matches what was requested
|
||||
footprint = function(*args, dtype=dtype)
|
||||
assert footprint.dtype == dtype
|
||||
|
||||
if supports_sequence_decomposition:
|
||||
sequence = function(*args, dtype=dtype, decomposition='sequence')
|
||||
assert all([fp_tuple[0].dtype == dtype for fp_tuple in sequence])
|
||||
|
||||
|
||||
@pytest.mark.parametrize("function", ["disk", "ball"])
|
||||
@pytest.mark.parametrize("radius", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 50, 75,
|
||||
100])
|
||||
def test_nsphere_series_approximation(function, radius):
|
||||
fp_func = getattr(footprints, function)
|
||||
expected = fp_func(radius, strict_radius=False, decomposition=None)
|
||||
footprint_sequence = fp_func(radius, strict_radius=False,
|
||||
decomposition="sequence")
|
||||
approximate = footprints.footprint_from_sequence(footprint_sequence)
|
||||
assert approximate.shape == expected.shape
|
||||
|
||||
# verify that maximum error does not exceed some fraction of the size
|
||||
error = np.sum(np.abs(expected.astype(int) - approximate.astype(int)))
|
||||
if radius == 1:
|
||||
assert error == 0
|
||||
else:
|
||||
max_error = 0.1 if function == "disk" else 0.15
|
||||
assert error / expected.size <= max_error
|
||||
|
||||
|
||||
@pytest.mark.parametrize("radius", [1, 2, 3, 4, 5, 10, 20, 50, 75])
|
||||
@pytest.mark.parametrize("strict_radius", [False, True])
|
||||
def test_disk_crosses_approximation(radius, strict_radius):
|
||||
fp_func = footprints.disk
|
||||
expected = fp_func(radius, strict_radius=strict_radius, decomposition=None)
|
||||
footprint_sequence = fp_func(radius, strict_radius=strict_radius,
|
||||
decomposition="crosses")
|
||||
approximate = footprints.footprint_from_sequence(footprint_sequence)
|
||||
assert approximate.shape == expected.shape
|
||||
|
||||
# verify that maximum error does not exceed some fraction of the size
|
||||
error = np.sum(np.abs(expected.astype(int) - approximate.astype(int)))
|
||||
max_error = 0.05
|
||||
assert error / expected.size <= max_error
|
||||
|
||||
|
||||
@pytest.mark.parametrize("width", [3, 8, 20, 50])
|
||||
@pytest.mark.parametrize("height", [3, 8, 20, 50])
|
||||
def test_ellipse_crosses_approximation(width, height):
|
||||
fp_func = footprints.ellipse
|
||||
expected = fp_func(width, height, decomposition=None)
|
||||
footprint_sequence = fp_func(width, height, decomposition="crosses")
|
||||
approximate = footprints.footprint_from_sequence(footprint_sequence)
|
||||
assert approximate.shape == expected.shape
|
||||
|
||||
# verify that maximum error does not exceed some fraction of the size
|
||||
error = np.sum(np.abs(expected.astype(int) - approximate.astype(int)))
|
||||
max_error = 0.05
|
||||
assert error / expected.size <= max_error
|
||||
|
||||
|
||||
def test_disk_series_approximation_unavailable():
|
||||
# ValueError if radius is too large (only precomputed up to radius=250)
|
||||
with pytest.raises(ValueError):
|
||||
footprints.disk(radius=10000, decomposition="sequence")
|
||||
|
||||
|
||||
def test_ball_series_approximation_unavailable():
|
||||
# ValueError if radius is too large (only precomputed up to radius=100)
|
||||
with pytest.raises(ValueError):
|
||||
footprints.ball(radius=10000, decomposition="sequence")
|
||||
410
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_gray.py
vendored
Normal file
410
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_gray.py
vendored
Normal file
@@ -0,0 +1,410 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
from scipy import ndimage as ndi
|
||||
from numpy.testing import assert_allclose, assert_array_equal, assert_equal
|
||||
|
||||
from skimage import color, data, transform
|
||||
from skimage._shared._warnings import expected_warnings
|
||||
from skimage._shared.testing import fetch
|
||||
from skimage.morphology import gray, footprints
|
||||
from skimage.util import img_as_uint, img_as_ubyte
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def cam_image():
|
||||
from skimage import data
|
||||
return np.ascontiguousarray(data.camera()[64:112, 64:96])
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def cell3d_image():
|
||||
from skimage import data
|
||||
return np.ascontiguousarray(data.cells3d()[30:48, 0, 20:36, 20:32])
|
||||
|
||||
|
||||
class TestMorphology():
|
||||
|
||||
# These expected outputs were generated with skimage v0.12.1
|
||||
# using:
|
||||
#
|
||||
# from skimage.morphology.tests.test_gray import TestMorphology
|
||||
# import numpy as np
|
||||
# output = TestMorphology()._build_expected_output()
|
||||
# np.savez_compressed('gray_morph_output.npz', **output)
|
||||
|
||||
def _build_expected_output(self):
|
||||
funcs = (gray.erosion, gray.dilation, gray.opening, gray.closing,
|
||||
gray.white_tophat, gray.black_tophat)
|
||||
footprints_2D = (footprints.square, footprints.diamond,
|
||||
footprints.disk, footprints.star)
|
||||
|
||||
image = img_as_ubyte(transform.downscale_local_mean(
|
||||
color.rgb2gray(data.coffee()), (20, 20)))
|
||||
|
||||
output = {}
|
||||
for n in range(1, 4):
|
||||
for strel in footprints_2D:
|
||||
for func in funcs:
|
||||
key = f'{strel.__name__}_{n}_{func.__name__}'
|
||||
output[key] = func(image, strel(n))
|
||||
|
||||
return output
|
||||
|
||||
def test_gray_morphology(self):
|
||||
expected = dict(np.load(fetch('data/gray_morph_output.npz')))
|
||||
calculated = self._build_expected_output()
|
||||
assert_equal(expected, calculated)
|
||||
|
||||
|
||||
class TestEccentricStructuringElements():
|
||||
def setup_class(self):
|
||||
self.black_pixel = 255 * np.ones((4, 4), dtype=np.uint8)
|
||||
self.black_pixel[1, 1] = 0
|
||||
self.white_pixel = 255 - self.black_pixel
|
||||
self.footprints = [footprints.square(2), footprints.rectangle(2, 2),
|
||||
footprints.rectangle(2, 1),
|
||||
footprints.rectangle(1, 2)]
|
||||
|
||||
def test_dilate_erode_symmetry(self):
|
||||
for s in self.footprints:
|
||||
c = gray.erosion(self.black_pixel, s)
|
||||
d = gray.dilation(self.white_pixel, s)
|
||||
assert np.all(c == (255 - d))
|
||||
|
||||
def test_open_black_pixel(self):
|
||||
for s in self.footprints:
|
||||
gray_open = gray.opening(self.black_pixel, s)
|
||||
assert np.all(gray_open == self.black_pixel)
|
||||
|
||||
def test_close_white_pixel(self):
|
||||
for s in self.footprints:
|
||||
gray_close = gray.closing(self.white_pixel, s)
|
||||
assert np.all(gray_close == self.white_pixel)
|
||||
|
||||
def test_open_white_pixel(self):
|
||||
for s in self.footprints:
|
||||
assert np.all(gray.opening(self.white_pixel, s) == 0)
|
||||
|
||||
def test_close_black_pixel(self):
|
||||
for s in self.footprints:
|
||||
assert np.all(gray.closing(self.black_pixel, s) == 255)
|
||||
|
||||
def test_white_tophat_white_pixel(self):
|
||||
for s in self.footprints:
|
||||
tophat = gray.white_tophat(self.white_pixel, s)
|
||||
assert np.all(tophat == self.white_pixel)
|
||||
|
||||
def test_black_tophat_black_pixel(self):
|
||||
for s in self.footprints:
|
||||
tophat = gray.black_tophat(self.black_pixel, s)
|
||||
assert np.all(tophat == (255 - self.black_pixel))
|
||||
|
||||
def test_white_tophat_black_pixel(self):
|
||||
for s in self.footprints:
|
||||
tophat = gray.white_tophat(self.black_pixel, s)
|
||||
assert np.all(tophat == 0)
|
||||
|
||||
def test_black_tophat_white_pixel(self):
|
||||
for s in self.footprints:
|
||||
tophat = gray.black_tophat(self.white_pixel, s)
|
||||
assert np.all(tophat == 0)
|
||||
|
||||
|
||||
gray_functions = [gray.erosion, gray.dilation,
|
||||
gray.opening, gray.closing,
|
||||
gray.white_tophat, gray.black_tophat]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("function", gray_functions)
|
||||
def test_default_footprint(function):
|
||||
strel = footprints.diamond(radius=1)
|
||||
image = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], np.uint8)
|
||||
im_expected = function(image, strel)
|
||||
im_test = function(image)
|
||||
assert_array_equal(im_expected, im_test)
|
||||
|
||||
|
||||
def test_3d_fallback_default_footprint():
|
||||
# 3x3x3 cube inside a 7x7x7 image:
|
||||
image = np.zeros((7, 7, 7), bool)
|
||||
image[2:-2, 2:-2, 2:-2] = 1
|
||||
|
||||
opened = gray.opening(image)
|
||||
|
||||
# expect a "hyper-cross" centered in the 5x5x5:
|
||||
image_expected = np.zeros((7, 7, 7), dtype=bool)
|
||||
image_expected[2:5, 2:5, 2:5] = ndi.generate_binary_structure(3, 1)
|
||||
assert_array_equal(opened, image_expected)
|
||||
|
||||
|
||||
gray_3d_fallback_functions = [gray.closing, gray.opening]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("function", gray_3d_fallback_functions)
|
||||
def test_3d_fallback_cube_footprint(function):
|
||||
# 3x3x3 cube inside a 7x7x7 image:
|
||||
image = np.zeros((7, 7, 7), bool)
|
||||
image[2:-2, 2:-2, 2:-2] = 1
|
||||
|
||||
cube = np.ones((3, 3, 3), dtype=np.uint8)
|
||||
|
||||
new_image = function(image, cube)
|
||||
assert_array_equal(new_image, image)
|
||||
|
||||
|
||||
def test_3d_fallback_white_tophat():
|
||||
image = np.zeros((7, 7, 7), dtype=bool)
|
||||
image[2, 2:4, 2:4] = 1
|
||||
image[3, 2:5, 2:5] = 1
|
||||
image[4, 3:5, 3:5] = 1
|
||||
|
||||
with expected_warnings([r'operator.*deprecated|\A\Z']):
|
||||
new_image = gray.white_tophat(image)
|
||||
footprint = ndi.generate_binary_structure(3, 1)
|
||||
with expected_warnings([r'operator.*deprecated|\A\Z']):
|
||||
image_expected = ndi.white_tophat(
|
||||
image.view(dtype=np.uint8), footprint=footprint)
|
||||
assert_array_equal(new_image, image_expected)
|
||||
|
||||
|
||||
def test_3d_fallback_black_tophat():
|
||||
image = np.ones((7, 7, 7), dtype=bool)
|
||||
image[2, 2:4, 2:4] = 0
|
||||
image[3, 2:5, 2:5] = 0
|
||||
image[4, 3:5, 3:5] = 0
|
||||
|
||||
with expected_warnings([r'operator.*deprecated|\A\Z']):
|
||||
new_image = gray.black_tophat(image)
|
||||
footprint = ndi.generate_binary_structure(3, 1)
|
||||
with expected_warnings([r'operator.*deprecated|\A\Z']):
|
||||
image_expected = ndi.black_tophat(
|
||||
image.view(dtype=np.uint8), footprint=footprint)
|
||||
assert_array_equal(new_image, image_expected)
|
||||
|
||||
|
||||
def test_2d_ndimage_equivalence():
|
||||
image = np.zeros((9, 9), np.uint8)
|
||||
image[2:-2, 2:-2] = 128
|
||||
image[3:-3, 3:-3] = 196
|
||||
image[4, 4] = 255
|
||||
|
||||
opened = gray.opening(image)
|
||||
closed = gray.closing(image)
|
||||
|
||||
footprint = ndi.generate_binary_structure(2, 1)
|
||||
ndimage_opened = ndi.grey_opening(image, footprint=footprint)
|
||||
ndimage_closed = ndi.grey_closing(image, footprint=footprint)
|
||||
|
||||
assert_array_equal(opened, ndimage_opened)
|
||||
assert_array_equal(closed, ndimage_closed)
|
||||
|
||||
|
||||
# float test images
|
||||
im = np.array([[ 0.55, 0.72, 0.6 , 0.54, 0.42],
|
||||
[ 0.65, 0.44, 0.89, 0.96, 0.38],
|
||||
[ 0.79, 0.53, 0.57, 0.93, 0.07],
|
||||
[ 0.09, 0.02, 0.83, 0.78, 0.87],
|
||||
[ 0.98, 0.8 , 0.46, 0.78, 0.12]])
|
||||
|
||||
eroded = np.array([[ 0.55, 0.44, 0.54, 0.42, 0.38],
|
||||
[ 0.44, 0.44, 0.44, 0.38, 0.07],
|
||||
[ 0.09, 0.02, 0.53, 0.07, 0.07],
|
||||
[ 0.02, 0.02, 0.02, 0.78, 0.07],
|
||||
[ 0.09, 0.02, 0.46, 0.12, 0.12]])
|
||||
|
||||
dilated = np.array([[ 0.72, 0.72, 0.89, 0.96, 0.54],
|
||||
[ 0.79, 0.89, 0.96, 0.96, 0.96],
|
||||
[ 0.79, 0.79, 0.93, 0.96, 0.93],
|
||||
[ 0.98, 0.83, 0.83, 0.93, 0.87],
|
||||
[ 0.98, 0.98, 0.83, 0.78, 0.87]])
|
||||
|
||||
opened = np.array([[ 0.55, 0.55, 0.54, 0.54, 0.42],
|
||||
[ 0.55, 0.44, 0.54, 0.44, 0.38],
|
||||
[ 0.44, 0.53, 0.53, 0.78, 0.07],
|
||||
[ 0.09, 0.02, 0.78, 0.78, 0.78],
|
||||
[ 0.09, 0.46, 0.46, 0.78, 0.12]])
|
||||
|
||||
closed = np.array([[ 0.72, 0.72, 0.72, 0.54, 0.54],
|
||||
[ 0.72, 0.72, 0.89, 0.96, 0.54],
|
||||
[ 0.79, 0.79, 0.79, 0.93, 0.87],
|
||||
[ 0.79, 0.79, 0.83, 0.78, 0.87],
|
||||
[ 0.98, 0.83, 0.78, 0.78, 0.78]])
|
||||
|
||||
|
||||
def test_float():
|
||||
assert_allclose(gray.erosion(im), eroded)
|
||||
assert_allclose(gray.dilation(im), dilated)
|
||||
assert_allclose(gray.opening(im), opened)
|
||||
assert_allclose(gray.closing(im), closed)
|
||||
|
||||
|
||||
def test_uint16():
|
||||
im16, eroded16, dilated16, opened16, closed16 = (
|
||||
map(img_as_uint, [im, eroded, dilated, opened, closed]))
|
||||
assert_allclose(gray.erosion(im16), eroded16)
|
||||
assert_allclose(gray.dilation(im16), dilated16)
|
||||
assert_allclose(gray.opening(im16), opened16)
|
||||
assert_allclose(gray.closing(im16), closed16)
|
||||
|
||||
|
||||
def test_discontiguous_out_array():
|
||||
image = np.array([[5, 6, 2],
|
||||
[7, 2, 2],
|
||||
[3, 5, 1]], np.uint8)
|
||||
out_array_big = np.zeros((5, 5), np.uint8)
|
||||
out_array = out_array_big[::2, ::2]
|
||||
expected_dilation = np.array([[7, 0, 6, 0, 6],
|
||||
[0, 0, 0, 0, 0],
|
||||
[7, 0, 7, 0, 2],
|
||||
[0, 0, 0, 0, 0],
|
||||
[7, 0, 5, 0, 5]], np.uint8)
|
||||
expected_erosion = np.array([[5, 0, 2, 0, 2],
|
||||
[0, 0, 0, 0, 0],
|
||||
[2, 0, 2, 0, 1],
|
||||
[0, 0, 0, 0, 0],
|
||||
[3, 0, 1, 0, 1]], np.uint8)
|
||||
gray.dilation(image, out=out_array)
|
||||
assert_array_equal(out_array_big, expected_dilation)
|
||||
gray.erosion(image, out=out_array)
|
||||
assert_array_equal(out_array_big, expected_erosion)
|
||||
|
||||
|
||||
def test_1d_erosion():
|
||||
image = np.array([1, 2, 3, 2, 1])
|
||||
expected = np.array([1, 1, 2, 1, 1])
|
||||
eroded = gray.erosion(image)
|
||||
assert_array_equal(eroded, expected)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"function", ["erosion", "dilation", "closing", "opening", "white_tophat",
|
||||
"black_tophat"],
|
||||
)
|
||||
@pytest.mark.parametrize("size", (7,))
|
||||
@pytest.mark.parametrize("decomposition", ['separable', 'sequence'])
|
||||
def test_square_decomposition(cam_image, function, size, decomposition):
|
||||
"""Validate footprint decomposition for various shapes.
|
||||
|
||||
comparison is made to the case without decomposition.
|
||||
"""
|
||||
footprint_ndarray = footprints.square(size, decomposition=None)
|
||||
footprint = footprints.square(size, decomposition=decomposition)
|
||||
func = getattr(gray, function)
|
||||
expected = func(cam_image, footprint=footprint_ndarray)
|
||||
out = func(cam_image, footprint=footprint)
|
||||
assert_array_equal(expected, out)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"function", ["erosion", "dilation", "closing", "opening", "white_tophat",
|
||||
"black_tophat"],
|
||||
)
|
||||
@pytest.mark.parametrize("nrows", (3, 11))
|
||||
@pytest.mark.parametrize("ncols", (3, 11))
|
||||
@pytest.mark.parametrize("decomposition", ['separable', 'sequence'])
|
||||
def test_rectangle_decomposition(cam_image, function, nrows, ncols,
|
||||
decomposition):
|
||||
"""Validate footprint decomposition for various shapes.
|
||||
|
||||
comparison is made to the case without decomposition.
|
||||
"""
|
||||
footprint_ndarray = footprints.rectangle(nrows, ncols, decomposition=None)
|
||||
footprint = footprints.rectangle(nrows, ncols, decomposition=decomposition)
|
||||
func = getattr(gray, function)
|
||||
expected = func(cam_image, footprint=footprint_ndarray)
|
||||
out = func(cam_image, footprint=footprint)
|
||||
assert_array_equal(expected, out)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"function", ["erosion", "dilation", "closing", "opening", "white_tophat",
|
||||
"black_tophat"],
|
||||
)
|
||||
@pytest.mark.parametrize("radius", (2, 3))
|
||||
@pytest.mark.parametrize("decomposition", ['separable', 'sequence'])
|
||||
def test_diamond_decomposition(cam_image, function, radius, decomposition):
|
||||
"""Validate footprint decomposition for various shapes.
|
||||
|
||||
comparison is made to the case without decomposition.
|
||||
"""
|
||||
footprint_ndarray = footprints.square(radius, decomposition=None)
|
||||
footprint = footprints.square(radius, decomposition=decomposition)
|
||||
func = getattr(gray, function)
|
||||
expected = func(cam_image, footprint=footprint_ndarray)
|
||||
out = func(cam_image, footprint=footprint)
|
||||
assert_array_equal(expected, out)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"function", ["erosion", "dilation", "closing", "opening", "white_tophat",
|
||||
"black_tophat"],
|
||||
)
|
||||
@pytest.mark.parametrize("m", (0, 1, 3, 5))
|
||||
@pytest.mark.parametrize("n", (0, 1, 2, 3))
|
||||
@pytest.mark.parametrize("decomposition", ['sequence'])
|
||||
def test_octagon_decomposition(cam_image, function, m, n, decomposition):
|
||||
"""Validate footprint decomposition for various shapes.
|
||||
|
||||
comparison is made to the case without decomposition.
|
||||
"""
|
||||
if m == 0 and n == 0:
|
||||
with pytest.raises(ValueError):
|
||||
footprints.octagon(m, n, decomposition=decomposition)
|
||||
else:
|
||||
footprint_ndarray = footprints.octagon(m, n, decomposition=None)
|
||||
footprint = footprints.octagon(m, n, decomposition=decomposition)
|
||||
func = getattr(gray, function)
|
||||
expected = func(cam_image, footprint=footprint_ndarray)
|
||||
out = func(cam_image, footprint=footprint)
|
||||
assert_array_equal(expected, out)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"function", ["erosion", "dilation", "closing", "opening", "white_tophat",
|
||||
"black_tophat"],
|
||||
)
|
||||
@pytest.mark.parametrize("size", (5,))
|
||||
@pytest.mark.parametrize("decomposition", ['separable', 'sequence'])
|
||||
def test_cube_decomposition(cell3d_image, function, size, decomposition):
|
||||
"""Validate footprint decomposition for various shapes.
|
||||
|
||||
comparison is made to the case without decomposition.
|
||||
"""
|
||||
footprint_ndarray = footprints.cube(size, decomposition=None)
|
||||
footprint = footprints.cube(size, decomposition=decomposition)
|
||||
func = getattr(gray, function)
|
||||
expected = func(cell3d_image, footprint=footprint_ndarray)
|
||||
out = func(cell3d_image, footprint=footprint)
|
||||
assert_array_equal(expected, out)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"function", ["erosion", "dilation", "closing", "opening", "white_tophat",
|
||||
"black_tophat"],
|
||||
)
|
||||
@pytest.mark.parametrize("radius", (3,))
|
||||
@pytest.mark.parametrize("decomposition", ['sequence'])
|
||||
def test_octahedron_decomposition(cell3d_image, function, radius,
|
||||
decomposition):
|
||||
"""Validate footprint decomposition for various shapes.
|
||||
|
||||
comparison is made to the case without decomposition.
|
||||
"""
|
||||
footprint_ndarray = footprints.octahedron(radius, decomposition=None)
|
||||
footprint = footprints.octahedron(radius, decomposition=decomposition)
|
||||
func = getattr(gray, function)
|
||||
expected = func(cell3d_image, footprint=footprint_ndarray)
|
||||
out = func(cell3d_image, footprint=footprint)
|
||||
assert_array_equal(expected, out)
|
||||
82
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_isotropic.py
vendored
Normal file
82
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_isotropic.py
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
import numpy as np
|
||||
from numpy.testing import assert_array_equal
|
||||
|
||||
from skimage import color, data, morphology
|
||||
from skimage.morphology import binary, isotropic
|
||||
from skimage.util import img_as_bool
|
||||
|
||||
img = color.rgb2gray(data.astronaut())
|
||||
bw_img = img > 100 / 255.
|
||||
|
||||
|
||||
def test_non_square_image():
|
||||
isotropic_res = isotropic.isotropic_erosion(bw_img[:100, :200], 3)
|
||||
binary_res = img_as_bool(binary.binary_erosion(
|
||||
bw_img[:100, :200], morphology.disk(3)))
|
||||
assert_array_equal(isotropic_res, binary_res)
|
||||
|
||||
|
||||
def test_isotropic_erosion():
|
||||
isotropic_res = isotropic.isotropic_erosion(bw_img, 3)
|
||||
binary_res = img_as_bool(binary.binary_erosion(bw_img, morphology.disk(3)))
|
||||
assert_array_equal(isotropic_res, binary_res)
|
||||
|
||||
|
||||
def _disk_with_spacing(radius, dtype=np.uint8, *, strict_radius=True, spacing=None):
|
||||
# Identical to morphology.disk, but with a spacing parameter and without decomposition.
|
||||
# This is different from morphology.ellipse which produces a slightly different footprint.
|
||||
L = np.arange(-radius, radius + 1)
|
||||
X, Y = np.meshgrid(L, L)
|
||||
|
||||
if spacing is not None:
|
||||
X *= spacing[1]
|
||||
Y *= spacing[0]
|
||||
|
||||
if not strict_radius:
|
||||
radius += 0.5
|
||||
return np.array((X ** 2 + Y ** 2) <= radius ** 2, dtype=dtype)
|
||||
|
||||
|
||||
def test_isotropic_erosion_spacing():
|
||||
isotropic_res = isotropic.isotropic_dilation(bw_img, 6, spacing=(1,2))
|
||||
binary_res = img_as_bool(binary.binary_dilation(bw_img, _disk_with_spacing(6, spacing=(1,2))))
|
||||
assert_array_equal(isotropic_res, binary_res)
|
||||
|
||||
|
||||
def test_isotropic_dilation():
|
||||
isotropic_res = isotropic.isotropic_dilation(bw_img, 3)
|
||||
binary_res = img_as_bool(
|
||||
binary.binary_dilation(
|
||||
bw_img, morphology.disk(3)))
|
||||
assert_array_equal(isotropic_res, binary_res)
|
||||
|
||||
|
||||
def test_isotropic_closing():
|
||||
isotropic_res = isotropic.isotropic_closing(bw_img, 3)
|
||||
binary_res = img_as_bool(binary.binary_closing(bw_img, morphology.disk(3)))
|
||||
assert_array_equal(isotropic_res, binary_res)
|
||||
|
||||
|
||||
def test_isotropic_opening():
|
||||
isotropic_res = isotropic.isotropic_opening(bw_img, 3)
|
||||
binary_res = img_as_bool(binary.binary_opening(bw_img, morphology.disk(3)))
|
||||
assert_array_equal(isotropic_res, binary_res)
|
||||
|
||||
|
||||
def test_footprint_overflow():
|
||||
img = np.zeros((20, 20), dtype=bool)
|
||||
img[2:19, 2:19] = True
|
||||
isotropic_res = isotropic.isotropic_erosion(img, 9)
|
||||
binary_res = img_as_bool(binary.binary_erosion(img, morphology.disk(9)))
|
||||
assert_array_equal(isotropic_res, binary_res)
|
||||
|
||||
|
||||
def test_out_argument():
|
||||
for func in (isotropic.isotropic_erosion, isotropic.isotropic_dilation):
|
||||
radius = 3
|
||||
img = np.ones((10, 10))
|
||||
out = np.zeros_like(img)
|
||||
out_saved = out.copy()
|
||||
func(img, radius, out=out)
|
||||
assert np.any(out != out_saved)
|
||||
assert_array_equal(out, func(img, radius))
|
||||
453
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_max_tree.py
vendored
Normal file
453
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_max_tree.py
vendored
Normal file
@@ -0,0 +1,453 @@
|
||||
import numpy as np
|
||||
from skimage.morphology import max_tree, area_closing, area_opening
|
||||
from skimage.morphology import max_tree_local_maxima, diameter_opening
|
||||
from skimage.morphology import diameter_closing
|
||||
from skimage.util import invert
|
||||
|
||||
from skimage._shared.testing import assert_array_equal, TestCase
|
||||
|
||||
eps = 1e-12
|
||||
|
||||
|
||||
def _full_type_test(img, param, expected, func, param_scale=False,
|
||||
**keywords):
|
||||
|
||||
# images as they are
|
||||
out = func(img, param, **keywords)
|
||||
assert_array_equal(out, expected)
|
||||
|
||||
# unsigned int
|
||||
for dt in [np.uint32, np.uint64]:
|
||||
img_cast = img.astype(dt)
|
||||
out = func(img_cast, param, **keywords)
|
||||
exp_cast = expected.astype(dt)
|
||||
assert_array_equal(out, exp_cast)
|
||||
|
||||
# float
|
||||
data_float = img.astype(np.float64)
|
||||
data_float = data_float / 255.0
|
||||
expected_float = expected.astype(np.float64)
|
||||
expected_float = expected_float / 255.0
|
||||
if param_scale:
|
||||
param_cast = param / 255.0
|
||||
else:
|
||||
param_cast = param
|
||||
for dt in [np.float32, np.float64]:
|
||||
data_cast = data_float.astype(dt)
|
||||
out = func(data_cast, param_cast, **keywords)
|
||||
exp_cast = expected_float.astype(dt)
|
||||
error_img = 255.0 * exp_cast - 255.0 * out
|
||||
error = (error_img >= 1.0).sum()
|
||||
assert error < eps
|
||||
|
||||
# signed images
|
||||
img_signed = img.astype(np.int16)
|
||||
img_signed = img_signed - 128
|
||||
exp_signed = expected.astype(np.int16)
|
||||
exp_signed = exp_signed - 128
|
||||
for dt in [np.int8, np.int16, np.int32, np.int64]:
|
||||
img_s = img_signed.astype(dt)
|
||||
out = func(img_s, param, **keywords)
|
||||
exp_s = exp_signed.astype(dt)
|
||||
assert_array_equal(out, exp_s)
|
||||
|
||||
|
||||
class TestMaxtree(TestCase):
|
||||
|
||||
def test_max_tree(self):
|
||||
"Test for max tree"
|
||||
img_type = np.uint8
|
||||
img = np.array([[10, 8, 8, 9],
|
||||
[7, 7, 9, 9],
|
||||
[8, 7, 10, 10],
|
||||
[9, 9, 10, 10]], dtype=img_type)
|
||||
|
||||
P_exp = np.array([[1, 4, 1, 1],
|
||||
[4, 4, 3, 3],
|
||||
[1, 4, 3, 10],
|
||||
[3, 3, 10, 10]], dtype=np.int64)
|
||||
|
||||
S_exp = np.array([4, 5, 9, 1, 2, 8, 3, 6, 7,
|
||||
12, 13, 0, 10, 11, 14, 15],
|
||||
dtype=np.int64)
|
||||
|
||||
for img_type in [np.uint8, np.uint16, np.uint32, np.uint64]:
|
||||
img = img.astype(img_type)
|
||||
P, S = max_tree(img, connectivity=2)
|
||||
assert_array_equal(P, P_exp)
|
||||
assert_array_equal(S, S_exp)
|
||||
|
||||
for img_type in [np.int8, np.int16, np.int32, np.int64]:
|
||||
img = img.astype(img_type)
|
||||
img_shifted = img - 9
|
||||
P, S = max_tree(img_shifted, connectivity=2)
|
||||
assert_array_equal(P, P_exp)
|
||||
assert_array_equal(S, S_exp)
|
||||
|
||||
img_float = img.astype(float)
|
||||
img_float = (img_float - 8) / 2.0
|
||||
for img_type in [np.float32, np.float64]:
|
||||
img_float = img_float.astype(img_type)
|
||||
P, S = max_tree(img_float, connectivity=2)
|
||||
assert_array_equal(P, P_exp)
|
||||
assert_array_equal(S, S_exp)
|
||||
|
||||
return
|
||||
|
||||
def test_area_closing(self):
|
||||
"Test for Area Closing (2 thresholds, all types)"
|
||||
|
||||
# original image
|
||||
img = np.array(
|
||||
[[240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240],
|
||||
[240, 200, 200, 240, 200, 240, 200, 200, 240, 240, 200, 240],
|
||||
[240, 200, 40, 240, 240, 240, 240, 240, 240, 240, 40, 240],
|
||||
[240, 240, 240, 240, 100, 240, 100, 100, 240, 240, 200, 240],
|
||||
[240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240],
|
||||
[200, 200, 200, 200, 200, 200, 200, 240, 200, 200, 255, 255],
|
||||
[200, 255, 200, 200, 200, 255, 200, 240, 255, 255, 255, 40],
|
||||
[200, 200, 200, 100, 200, 200, 200, 240, 255, 255, 255, 255],
|
||||
[200, 200, 200, 100, 200, 200, 200, 240, 200, 200, 255, 255],
|
||||
[200, 200, 200, 200, 200, 40, 200, 240, 240, 100, 255, 255],
|
||||
[200, 40, 255, 255, 255, 40, 200, 255, 200, 200, 255, 255],
|
||||
[200, 200, 200, 200, 200, 200, 200, 255, 255, 255, 255, 255]],
|
||||
dtype=np.uint8)
|
||||
|
||||
# expected area closing with area 2
|
||||
expected_2 = np.array(
|
||||
[[240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240],
|
||||
[240, 200, 200, 240, 240, 240, 200, 200, 240, 240, 200, 240],
|
||||
[240, 200, 200, 240, 240, 240, 240, 240, 240, 240, 200, 240],
|
||||
[240, 240, 240, 240, 240, 240, 100, 100, 240, 240, 200, 240],
|
||||
[240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240],
|
||||
[200, 200, 200, 200, 200, 200, 200, 240, 200, 200, 255, 255],
|
||||
[200, 255, 200, 200, 200, 255, 200, 240, 255, 255, 255, 255],
|
||||
[200, 200, 200, 100, 200, 200, 200, 240, 255, 255, 255, 255],
|
||||
[200, 200, 200, 100, 200, 200, 200, 240, 200, 200, 255, 255],
|
||||
[200, 200, 200, 200, 200, 40, 200, 240, 240, 200, 255, 255],
|
||||
[200, 200, 255, 255, 255, 40, 200, 255, 200, 200, 255, 255],
|
||||
[200, 200, 200, 200, 200, 200, 200, 255, 255, 255, 255, 255]],
|
||||
dtype=np.uint8)
|
||||
|
||||
# expected diameter closing with diameter 4
|
||||
expected_4 = np.array(
|
||||
[[240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240],
|
||||
[240, 200, 200, 240, 240, 240, 240, 240, 240, 240, 240, 240],
|
||||
[240, 200, 200, 240, 240, 240, 240, 240, 240, 240, 240, 240],
|
||||
[240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240],
|
||||
[240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240],
|
||||
[200, 200, 200, 200, 200, 200, 200, 240, 240, 240, 255, 255],
|
||||
[200, 255, 200, 200, 200, 255, 200, 240, 255, 255, 255, 255],
|
||||
[200, 200, 200, 200, 200, 200, 200, 240, 255, 255, 255, 255],
|
||||
[200, 200, 200, 200, 200, 200, 200, 240, 200, 200, 255, 255],
|
||||
[200, 200, 200, 200, 200, 200, 200, 240, 240, 200, 255, 255],
|
||||
[200, 200, 255, 255, 255, 200, 200, 255, 200, 200, 255, 255],
|
||||
[200, 200, 200, 200, 200, 200, 200, 255, 255, 255, 255, 255]],
|
||||
dtype=np.uint8)
|
||||
|
||||
# _full_type_test makes a test with many image types.
|
||||
_full_type_test(img, 2, expected_2, area_closing, connectivity=2)
|
||||
_full_type_test(img, 4, expected_4, area_closing, connectivity=2)
|
||||
|
||||
P, S = max_tree(invert(img), connectivity=2)
|
||||
_full_type_test(img, 4, expected_4, area_closing,
|
||||
parent=P, tree_traverser=S)
|
||||
|
||||
def test_area_opening(self):
|
||||
"Test for Area Opening (2 thresholds, all types)"
|
||||
|
||||
# original image
|
||||
img = np.array([[15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15],
|
||||
[15, 55, 55, 15, 55, 15, 55, 55, 15, 15, 55, 15],
|
||||
[15, 55, 215, 15, 15, 15, 15, 15, 15, 15, 215, 15],
|
||||
[15, 15, 15, 15, 155, 15, 155, 155, 15, 15, 55, 15],
|
||||
[15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15],
|
||||
[55, 55, 55, 55, 55, 55, 55, 15, 55, 55, 0, 0],
|
||||
[55, 0, 55, 55, 55, 0, 55, 15, 0, 0, 0, 215],
|
||||
[55, 55, 55, 155, 55, 55, 55, 15, 0, 0, 0, 0],
|
||||
[55, 55, 55, 155, 55, 55, 55, 15, 55, 55, 0, 0],
|
||||
[55, 55, 55, 55, 55, 215, 55, 15, 15, 155, 0, 0],
|
||||
[55, 215, 0, 0, 0, 215, 55, 0, 55, 55, 0, 0],
|
||||
[55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0]],
|
||||
dtype=np.uint8)
|
||||
|
||||
# expected area closing with area 2
|
||||
expected_2 = np.array([[15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15],
|
||||
[15, 55, 55, 15, 15, 15, 55, 55, 15,
|
||||
15, 55, 15],
|
||||
[15, 55, 55, 15, 15, 15, 15, 15, 15,
|
||||
15, 55, 15],
|
||||
[15, 15, 15, 15, 15, 15, 155, 155, 15,
|
||||
15, 55, 15],
|
||||
[15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15],
|
||||
[55, 55, 55, 55, 55, 55, 55, 15, 55,
|
||||
55, 0, 0],
|
||||
[55, 0, 55, 55, 55, 0, 55, 15, 0,
|
||||
0, 0, 0],
|
||||
[55, 55, 55, 155, 55, 55, 55, 15, 0,
|
||||
0, 0, 0],
|
||||
[55, 55, 55, 155, 55, 55, 55, 15, 55,
|
||||
55, 0, 0],
|
||||
[55, 55, 55, 55, 55, 215, 55, 15, 15,
|
||||
55, 0, 0],
|
||||
[55, 55, 0, 0, 0, 215, 55, 0, 55,
|
||||
55, 0, 0],
|
||||
[55, 55, 55, 55, 55, 55, 55, 0, 0,
|
||||
0, 0, 0]],
|
||||
dtype=np.uint8)
|
||||
|
||||
# expected diameter closing with diameter 4
|
||||
expected_4 = np.array([[15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15],
|
||||
[15, 55, 55, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15],
|
||||
[15, 55, 55, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15],
|
||||
[15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15],
|
||||
[15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15],
|
||||
[55, 55, 55, 55, 55, 55, 55, 15, 15,
|
||||
15, 0, 0],
|
||||
[55, 0, 55, 55, 55, 0, 55, 15, 0,
|
||||
0, 0, 0],
|
||||
[55, 55, 55, 55, 55, 55, 55, 15, 0,
|
||||
0, 0, 0],
|
||||
[55, 55, 55, 55, 55, 55, 55, 15, 55,
|
||||
55, 0, 0],
|
||||
[55, 55, 55, 55, 55, 55, 55, 15, 15,
|
||||
55, 0, 0],
|
||||
[55, 55, 0, 0, 0, 55, 55, 0, 55,
|
||||
55, 0, 0],
|
||||
[55, 55, 55, 55, 55, 55, 55, 0, 0,
|
||||
0, 0, 0]],
|
||||
dtype=np.uint8)
|
||||
|
||||
# _full_type_test makes a test with many image types.
|
||||
_full_type_test(img, 2, expected_2, area_opening, connectivity=2)
|
||||
_full_type_test(img, 4, expected_4, area_opening, connectivity=2)
|
||||
|
||||
P, S = max_tree(img, connectivity=2)
|
||||
_full_type_test(img, 4, expected_4, area_opening,
|
||||
parent=P, tree_traverser=S)
|
||||
|
||||
def test_diameter_closing(self):
|
||||
"Test for Diameter Opening (2 thresholds, all types)"
|
||||
img = np.array([[97, 95, 93, 92, 91, 90, 90, 90, 91, 92, 93, 95],
|
||||
[95, 93, 91, 89, 88, 88, 88, 88, 88, 89, 91, 93],
|
||||
[93, 63, 63, 63, 63, 86, 86, 86, 87, 43, 43, 91],
|
||||
[92, 89, 88, 86, 85, 85, 84, 85, 85, 43, 43, 89],
|
||||
[91, 88, 87, 85, 84, 84, 83, 84, 84, 85, 87, 88],
|
||||
[90, 88, 86, 85, 84, 83, 83, 83, 84, 85, 86, 88],
|
||||
[90, 88, 86, 84, 83, 83, 82, 83, 83, 84, 86, 88],
|
||||
[90, 88, 86, 85, 84, 83, 83, 83, 84, 85, 86, 88],
|
||||
[91, 88, 87, 85, 84, 84, 83, 84, 84, 85, 87, 88],
|
||||
[92, 89, 23, 23, 85, 85, 84, 85, 85, 3, 3, 89],
|
||||
[93, 91, 23, 23, 87, 86, 86, 86, 87, 88, 3, 91],
|
||||
[95, 93, 91, 89, 88, 88, 88, 88, 88, 89, 91, 93]],
|
||||
dtype=np.uint8)
|
||||
|
||||
ex2 = np.array([[97, 95, 93, 92, 91, 90, 90, 90, 91, 92, 93, 95],
|
||||
[95, 93, 91, 89, 88, 88, 88, 88, 88, 89, 91, 93],
|
||||
[93, 63, 63, 63, 63, 86, 86, 86, 87, 43, 43, 91],
|
||||
[92, 89, 88, 86, 85, 85, 84, 85, 85, 43, 43, 89],
|
||||
[91, 88, 87, 85, 84, 84, 83, 84, 84, 85, 87, 88],
|
||||
[90, 88, 86, 85, 84, 83, 83, 83, 84, 85, 86, 88],
|
||||
[90, 88, 86, 84, 83, 83, 83, 83, 83, 84, 86, 88],
|
||||
[90, 88, 86, 85, 84, 83, 83, 83, 84, 85, 86, 88],
|
||||
[91, 88, 87, 85, 84, 84, 83, 84, 84, 85, 87, 88],
|
||||
[92, 89, 23, 23, 85, 85, 84, 85, 85, 3, 3, 89],
|
||||
[93, 91, 23, 23, 87, 86, 86, 86, 87, 88, 3, 91],
|
||||
[95, 93, 91, 89, 88, 88, 88, 88, 88, 89, 91, 93]],
|
||||
dtype=np.uint8)
|
||||
|
||||
ex4 = np.array([[97, 95, 93, 92, 91, 90, 90, 90, 91, 92, 93, 95],
|
||||
[95, 93, 91, 89, 88, 88, 88, 88, 88, 89, 91, 93],
|
||||
[93, 63, 63, 63, 63, 86, 86, 86, 87, 84, 84, 91],
|
||||
[92, 89, 88, 86, 85, 85, 84, 85, 85, 84, 84, 89],
|
||||
[91, 88, 87, 85, 84, 84, 83, 84, 84, 85, 87, 88],
|
||||
[90, 88, 86, 85, 84, 83, 83, 83, 84, 85, 86, 88],
|
||||
[90, 88, 86, 84, 83, 83, 83, 83, 83, 84, 86, 88],
|
||||
[90, 88, 86, 85, 84, 83, 83, 83, 84, 85, 86, 88],
|
||||
[91, 88, 87, 85, 84, 84, 83, 84, 84, 85, 87, 88],
|
||||
[92, 89, 84, 84, 85, 85, 84, 85, 85, 84, 84, 89],
|
||||
[93, 91, 84, 84, 87, 86, 86, 86, 87, 88, 84, 91],
|
||||
[95, 93, 91, 89, 88, 88, 88, 88, 88, 89, 91, 93]],
|
||||
dtype=np.uint8)
|
||||
|
||||
# _full_type_test makes a test with many image types.
|
||||
_full_type_test(img, 2, ex2, diameter_closing, connectivity=2)
|
||||
_full_type_test(img, 4, ex4, diameter_closing, connectivity=2)
|
||||
|
||||
P, S = max_tree(invert(img), connectivity=2)
|
||||
_full_type_test(img, 4, ex4, diameter_opening,
|
||||
parent=P, tree_traverser=S)
|
||||
|
||||
def test_diameter_opening(self):
|
||||
"Test for Diameter Opening (2 thresholds, all types)"
|
||||
img = np.array([[5, 7, 9, 11, 12, 12, 12, 12, 12, 11, 9, 7],
|
||||
[7, 10, 11, 13, 14, 14, 15, 14, 14, 13, 11, 10],
|
||||
[9, 40, 40, 40, 40, 16, 16, 16, 16, 60, 60, 11],
|
||||
[11, 13, 15, 16, 17, 18, 18, 18, 17, 60, 60, 13],
|
||||
[12, 14, 16, 17, 18, 19, 19, 19, 18, 17, 16, 14],
|
||||
[12, 14, 16, 18, 19, 19, 19, 19, 19, 18, 16, 14],
|
||||
[12, 15, 16, 18, 19, 19, 20, 19, 19, 18, 16, 15],
|
||||
[12, 14, 16, 18, 19, 19, 19, 19, 19, 18, 16, 14],
|
||||
[12, 14, 16, 17, 18, 19, 19, 19, 18, 17, 16, 14],
|
||||
[11, 13, 80, 80, 17, 18, 18, 18, 17, 100, 100, 13],
|
||||
[9, 11, 80, 80, 16, 16, 16, 16, 16, 15, 100, 11],
|
||||
[7, 10, 11, 13, 14, 14, 15, 14, 14, 13, 11, 10]])
|
||||
|
||||
ex2 = np.array([[5, 7, 9, 11, 12, 12, 12, 12, 12, 11, 9, 7],
|
||||
[7, 10, 11, 13, 14, 14, 15, 14, 14, 13, 11, 10],
|
||||
[9, 40, 40, 40, 40, 16, 16, 16, 16, 60, 60, 11],
|
||||
[11, 13, 15, 16, 17, 18, 18, 18, 17, 60, 60, 13],
|
||||
[12, 14, 16, 17, 18, 19, 19, 19, 18, 17, 16, 14],
|
||||
[12, 14, 16, 18, 19, 19, 19, 19, 19, 18, 16, 14],
|
||||
[12, 15, 16, 18, 19, 19, 19, 19, 19, 18, 16, 15],
|
||||
[12, 14, 16, 18, 19, 19, 19, 19, 19, 18, 16, 14],
|
||||
[12, 14, 16, 17, 18, 19, 19, 19, 18, 17, 16, 14],
|
||||
[11, 13, 80, 80, 17, 18, 18, 18, 17, 100, 100, 13],
|
||||
[9, 11, 80, 80, 16, 16, 16, 16, 16, 15, 100, 11],
|
||||
[7, 10, 11, 13, 14, 14, 15, 14, 14, 13, 11, 10]])
|
||||
|
||||
ex4 = np.array([[5, 7, 9, 11, 12, 12, 12, 12, 12, 11, 9, 7],
|
||||
[7, 10, 11, 13, 14, 14, 15, 14, 14, 13, 11, 10],
|
||||
[9, 40, 40, 40, 40, 16, 16, 16, 16, 18, 18, 11],
|
||||
[11, 13, 15, 16, 17, 18, 18, 18, 17, 18, 18, 13],
|
||||
[12, 14, 16, 17, 18, 19, 19, 19, 18, 17, 16, 14],
|
||||
[12, 14, 16, 18, 19, 19, 19, 19, 19, 18, 16, 14],
|
||||
[12, 15, 16, 18, 19, 19, 19, 19, 19, 18, 16, 15],
|
||||
[12, 14, 16, 18, 19, 19, 19, 19, 19, 18, 16, 14],
|
||||
[12, 14, 16, 17, 18, 19, 19, 19, 18, 17, 16, 14],
|
||||
[11, 13, 18, 18, 17, 18, 18, 18, 17, 18, 18, 13],
|
||||
[9, 11, 18, 18, 16, 16, 16, 16, 16, 15, 18, 11],
|
||||
[7, 10, 11, 13, 14, 14, 15, 14, 14, 13, 11, 10]])
|
||||
|
||||
# _full_type_test makes a test with many image types.
|
||||
_full_type_test(img, 2, ex2, diameter_opening, connectivity=2)
|
||||
_full_type_test(img, 4, ex4, diameter_opening, connectivity=2)
|
||||
|
||||
P, S = max_tree(img, connectivity=2)
|
||||
_full_type_test(img, 4, ex4, diameter_opening,
|
||||
parent=P, tree_traverser=S)
|
||||
|
||||
def test_local_maxima(self):
|
||||
"local maxima for various data types"
|
||||
data = np.array([[10, 11, 13, 14, 14, 15, 14, 14, 13, 11],
|
||||
[11, 13, 15, 16, 16, 16, 16, 16, 15, 13],
|
||||
[13, 15, 40, 40, 18, 18, 18, 60, 60, 15],
|
||||
[14, 16, 40, 40, 19, 19, 19, 60, 60, 16],
|
||||
[14, 16, 18, 19, 19, 19, 19, 19, 18, 16],
|
||||
[15, 16, 18, 19, 19, 20, 19, 19, 18, 16],
|
||||
[14, 16, 18, 19, 19, 19, 19, 19, 18, 16],
|
||||
[14, 16, 80, 80, 19, 19, 19, 100, 100, 16],
|
||||
[13, 15, 80, 80, 18, 18, 18, 100, 100, 15],
|
||||
[11, 13, 15, 16, 16, 16, 16, 16, 15, 13]],
|
||||
dtype=np.uint8)
|
||||
expected_result = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=np.uint64)
|
||||
for dtype in [np.uint8, np.uint64, np.int8, np.int64]:
|
||||
|
||||
test_data = data.astype(dtype)
|
||||
out = max_tree_local_maxima(test_data, connectivity=1)
|
||||
out_bin = out > 0
|
||||
assert_array_equal(expected_result, out_bin)
|
||||
assert out.dtype == expected_result.dtype
|
||||
assert np.max(out) == 5
|
||||
|
||||
P, S = max_tree(test_data)
|
||||
out = max_tree_local_maxima(test_data,
|
||||
parent=P,
|
||||
tree_traverser=S)
|
||||
|
||||
assert_array_equal(expected_result, out_bin)
|
||||
|
||||
assert out.dtype == expected_result.dtype
|
||||
assert np.max(out) == 5
|
||||
|
||||
def test_extrema_float(self):
|
||||
"specific tests for float type"
|
||||
data = np.array([[0.10, 0.11, 0.13, 0.14, 0.14, 0.15, 0.14,
|
||||
0.14, 0.13, 0.11],
|
||||
[0.11, 0.13, 0.15, 0.16, 0.16, 0.16, 0.16,
|
||||
0.16, 0.15, 0.13],
|
||||
[0.13, 0.15, 0.40, 0.40, 0.18, 0.18, 0.18,
|
||||
0.60, 0.60, 0.15],
|
||||
[0.14, 0.16, 0.40, 0.40, 0.19, 0.19, 0.19,
|
||||
0.60, 0.60, 0.16],
|
||||
[0.14, 0.16, 0.18, 0.19, 0.19, 0.19, 0.19,
|
||||
0.19, 0.18, 0.16],
|
||||
[0.15, 0.182, 0.18, 0.19, 0.204, 0.20, 0.19,
|
||||
0.19, 0.18, 0.16],
|
||||
[0.14, 0.16, 0.18, 0.19, 0.19, 0.19, 0.19,
|
||||
0.19, 0.18, 0.16],
|
||||
[0.14, 0.16, 0.80, 0.80, 0.19, 0.19, 0.19,
|
||||
4.0, 1.0, 0.16],
|
||||
[0.13, 0.15, 0.80, 0.80, 0.18, 0.18, 0.18,
|
||||
1.0, 1.0, 0.15],
|
||||
[0.11, 0.13, 0.15, 0.16, 0.16, 0.16, 0.16,
|
||||
0.16, 0.15, 0.13]],
|
||||
dtype=np.float32)
|
||||
|
||||
expected_result = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=np.uint8)
|
||||
|
||||
# test for local maxima
|
||||
out = max_tree_local_maxima(data, connectivity=1)
|
||||
out_bin = out > 0
|
||||
assert_array_equal(expected_result, out_bin)
|
||||
assert np.max(out) == 6
|
||||
|
||||
def test_3d(self):
|
||||
"""tests the detection of maxima in 3D."""
|
||||
img = np.zeros((8, 8, 8), dtype=np.uint8)
|
||||
local_maxima = np.zeros((8, 8, 8), dtype=np.uint64)
|
||||
|
||||
# first maximum: only one pixel
|
||||
img[1, 1:3, 1:3] = 100
|
||||
img[2, 2, 2] = 200
|
||||
img[3, 1:3, 1:3] = 100
|
||||
local_maxima[2, 2, 2] = 1
|
||||
|
||||
# second maximum: three pixels in z-direction
|
||||
img[5:8, 1, 1] = 200
|
||||
local_maxima[5:8, 1, 1] = 1
|
||||
|
||||
# third: two maxima in 0 and 3.
|
||||
img[0, 5:8, 5:8] = 200
|
||||
img[1, 6, 6] = 100
|
||||
img[2, 5:7, 5:7] = 200
|
||||
img[0:3, 5:8, 5:8] += 50
|
||||
local_maxima[0, 5:8, 5:8] = 1
|
||||
local_maxima[2, 5:7, 5:7] = 1
|
||||
|
||||
# four : one maximum in the corner of the square
|
||||
img[6:8, 6:8, 6:8] = 200
|
||||
img[7, 7, 7] = 255
|
||||
local_maxima[7, 7, 7] = 1
|
||||
|
||||
out = max_tree_local_maxima(img)
|
||||
out_bin = out > 0
|
||||
assert_array_equal(local_maxima, out_bin)
|
||||
assert np.max(out) == 5
|
||||
225
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_misc.py
vendored
Normal file
225
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_misc.py
vendored
Normal file
@@ -0,0 +1,225 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
from skimage.morphology import remove_small_objects, remove_small_holes
|
||||
|
||||
from skimage._shared import testing
|
||||
from skimage._shared.testing import assert_array_equal, assert_equal
|
||||
from skimage._shared._warnings import expected_warnings
|
||||
|
||||
|
||||
test_image = np.array([[0, 0, 0, 1, 0],
|
||||
[1, 1, 1, 0, 0],
|
||||
[1, 1, 1, 0, 1]], bool)
|
||||
|
||||
|
||||
def test_one_connectivity():
|
||||
expected = np.array([[0, 0, 0, 0, 0],
|
||||
[1, 1, 1, 0, 0],
|
||||
[1, 1, 1, 0, 0]], bool)
|
||||
observed = remove_small_objects(test_image, min_size=6)
|
||||
assert_array_equal(observed, expected)
|
||||
|
||||
|
||||
def test_two_connectivity():
|
||||
expected = np.array([[0, 0, 0, 1, 0],
|
||||
[1, 1, 1, 0, 0],
|
||||
[1, 1, 1, 0, 0]], bool)
|
||||
observed = remove_small_objects(test_image, min_size=7, connectivity=2)
|
||||
assert_array_equal(observed, expected)
|
||||
|
||||
|
||||
def test_in_place():
|
||||
image = test_image.copy()
|
||||
observed = remove_small_objects(image, min_size=6, out=image)
|
||||
assert_equal(observed is image, True,
|
||||
"remove_small_objects in_place argument failed.")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("in_dtype", [bool, int, np.int32])
|
||||
@pytest.mark.parametrize("out_dtype", [bool, int, np.int32])
|
||||
def test_out(in_dtype, out_dtype):
|
||||
image = test_image.astype(in_dtype, copy=True)
|
||||
expected_out = np.empty_like(test_image, dtype=out_dtype)
|
||||
|
||||
if out_dtype != bool:
|
||||
# object with only 1 label will warn on non-bool output dtype
|
||||
exp_warn = ["Only one label was provided"]
|
||||
else:
|
||||
exp_warn = []
|
||||
|
||||
with expected_warnings(exp_warn):
|
||||
out = remove_small_objects(image, min_size=6, out=expected_out)
|
||||
|
||||
assert out is expected_out
|
||||
|
||||
|
||||
def test_labeled_image():
|
||||
labeled_image = np.array([[2, 2, 2, 0, 1],
|
||||
[2, 2, 2, 0, 1],
|
||||
[2, 0, 0, 0, 0],
|
||||
[0, 0, 3, 3, 3]], dtype=int)
|
||||
expected = np.array([[2, 2, 2, 0, 0],
|
||||
[2, 2, 2, 0, 0],
|
||||
[2, 0, 0, 0, 0],
|
||||
[0, 0, 3, 3, 3]], dtype=int)
|
||||
observed = remove_small_objects(labeled_image, min_size=3)
|
||||
assert_array_equal(observed, expected)
|
||||
|
||||
|
||||
def test_uint_image():
|
||||
labeled_image = np.array([[2, 2, 2, 0, 1],
|
||||
[2, 2, 2, 0, 1],
|
||||
[2, 0, 0, 0, 0],
|
||||
[0, 0, 3, 3, 3]], dtype=np.uint8)
|
||||
expected = np.array([[2, 2, 2, 0, 0],
|
||||
[2, 2, 2, 0, 0],
|
||||
[2, 0, 0, 0, 0],
|
||||
[0, 0, 3, 3, 3]], dtype=np.uint8)
|
||||
observed = remove_small_objects(labeled_image, min_size=3)
|
||||
assert_array_equal(observed, expected)
|
||||
|
||||
|
||||
def test_single_label_warning():
|
||||
image = np.array([[0, 0, 0, 1, 0],
|
||||
[1, 1, 1, 0, 0],
|
||||
[1, 1, 1, 0, 0]], int)
|
||||
with expected_warnings(['use a boolean array?']):
|
||||
remove_small_objects(image, min_size=6)
|
||||
|
||||
|
||||
def test_float_input():
|
||||
float_test = np.random.rand(5, 5)
|
||||
with testing.raises(TypeError):
|
||||
remove_small_objects(float_test)
|
||||
|
||||
|
||||
def test_negative_input():
|
||||
negative_int = np.random.randint(-4, -1, size=(5, 5))
|
||||
with testing.raises(ValueError):
|
||||
remove_small_objects(negative_int)
|
||||
|
||||
|
||||
test_holes_image = np.array([[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 0, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1]], bool)
|
||||
|
||||
|
||||
def test_one_connectivity_holes():
|
||||
expected = np.array([[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1]], bool)
|
||||
observed = remove_small_holes(test_holes_image, area_threshold=3)
|
||||
assert_array_equal(observed, expected)
|
||||
|
||||
|
||||
def test_two_connectivity_holes():
|
||||
expected = np.array([[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 0, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1]], bool)
|
||||
observed = remove_small_holes(test_holes_image, area_threshold=3,
|
||||
connectivity=2)
|
||||
assert_array_equal(observed, expected)
|
||||
|
||||
|
||||
def test_in_place_holes():
|
||||
image = test_holes_image.copy()
|
||||
observed = remove_small_holes(image, area_threshold=3, out=image)
|
||||
assert_equal(observed is image, True,
|
||||
"remove_small_holes in_place argument failed.")
|
||||
|
||||
|
||||
def test_out_remove_small_holes():
|
||||
image = test_holes_image.copy()
|
||||
expected_out = np.empty_like(image)
|
||||
out = remove_small_holes(image, area_threshold=3, out=expected_out)
|
||||
|
||||
assert out is expected_out
|
||||
|
||||
|
||||
def test_non_bool_out():
|
||||
image = test_holes_image.copy()
|
||||
expected_out = np.empty_like(image, dtype=int)
|
||||
with testing.raises(TypeError):
|
||||
remove_small_holes(image, area_threshold=3, out=expected_out)
|
||||
|
||||
|
||||
def test_labeled_image_holes():
|
||||
labeled_holes_image = np.array([[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 0, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 2, 2, 2],
|
||||
[0, 0, 0, 0, 0, 0, 0, 2, 0, 2],
|
||||
[0, 0, 0, 0, 0, 0, 0, 2, 2, 2]],
|
||||
dtype=int)
|
||||
expected = np.array([[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1]], dtype=bool)
|
||||
with expected_warnings(['returned as a boolean array']):
|
||||
observed = remove_small_holes(labeled_holes_image, area_threshold=3)
|
||||
assert_array_equal(observed, expected)
|
||||
|
||||
|
||||
def test_uint_image_holes():
|
||||
labeled_holes_image = np.array([[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 0, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 2, 2, 2],
|
||||
[0, 0, 0, 0, 0, 0, 0, 2, 0, 2],
|
||||
[0, 0, 0, 0, 0, 0, 0, 2, 2, 2]],
|
||||
dtype=np.uint8)
|
||||
expected = np.array([[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1]], dtype=bool)
|
||||
with expected_warnings(['returned as a boolean array']):
|
||||
observed = remove_small_holes(labeled_holes_image, area_threshold=3)
|
||||
assert_array_equal(observed, expected)
|
||||
|
||||
|
||||
def test_label_warning_holes():
|
||||
labeled_holes_image = np.array([[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 1, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 0, 1, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 2, 2, 2],
|
||||
[0, 0, 0, 0, 0, 0, 0, 2, 0, 2],
|
||||
[0, 0, 0, 0, 0, 0, 0, 2, 2, 2]],
|
||||
dtype=int)
|
||||
with expected_warnings(['use a boolean array?']):
|
||||
remove_small_holes(labeled_holes_image, area_threshold=3)
|
||||
remove_small_holes(labeled_holes_image.astype(bool), area_threshold=3)
|
||||
|
||||
|
||||
def test_float_input_holes():
|
||||
float_test = np.random.rand(5, 5)
|
||||
with testing.raises(TypeError):
|
||||
remove_small_holes(float_test)
|
||||
152
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_reconstruction.py
vendored
Normal file
152
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_reconstruction.py
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
import math
|
||||
import numpy as np
|
||||
import pytest
|
||||
from numpy.testing import assert_array_almost_equal
|
||||
|
||||
from skimage._shared.utils import _supported_float_type
|
||||
from skimage.morphology.grayreconstruct import reconstruction
|
||||
|
||||
|
||||
def test_zeros():
|
||||
"""Test reconstruction with image and mask of zeros"""
|
||||
assert_array_almost_equal(
|
||||
reconstruction(np.zeros((5, 7)), np.zeros((5, 7))), 0)
|
||||
|
||||
|
||||
def test_image_equals_mask():
|
||||
"""Test reconstruction where the image and mask are the same"""
|
||||
assert_array_almost_equal(
|
||||
reconstruction(np.ones((7, 5)), np.ones((7, 5))), 1)
|
||||
|
||||
|
||||
def test_image_less_than_mask():
|
||||
"""Test reconstruction where the image is uniform and less than mask"""
|
||||
image = np.ones((5, 5))
|
||||
mask = np.ones((5, 5)) * 2
|
||||
assert_array_almost_equal(reconstruction(image, mask), 1)
|
||||
|
||||
|
||||
def test_one_image_peak():
|
||||
"""Test reconstruction with one peak pixel"""
|
||||
image = np.ones((5, 5))
|
||||
image[2, 2] = 2
|
||||
mask = np.ones((5, 5)) * 3
|
||||
assert_array_almost_equal(reconstruction(image, mask), 2)
|
||||
|
||||
|
||||
# minsize chosen to test sizes covering use of 8, 16 and 32-bit integers
|
||||
# internally
|
||||
@pytest.mark.parametrize('minsize', [None, 200, 20000, 40000, 80000])
|
||||
@pytest.mark.parametrize('dtype', [np.uint8, np.float32])
|
||||
def test_two_image_peaks(minsize, dtype):
|
||||
"""Test reconstruction with two peak pixels isolated by the mask"""
|
||||
image = np.array([[1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 2, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 3, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1]], dtype=dtype)
|
||||
|
||||
mask = np.array([[4, 4, 4, 1, 1, 1, 1, 1, 1],
|
||||
[4, 4, 4, 1, 1, 1, 1, 1, 1],
|
||||
[4, 4, 4, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 4, 4, 4, 1],
|
||||
[1, 1, 1, 1, 1, 4, 4, 4, 1],
|
||||
[1, 1, 1, 1, 1, 4, 4, 4, 1]], dtype=dtype)
|
||||
|
||||
expected = np.array([[2, 2, 2, 1, 1, 1, 1, 1, 1],
|
||||
[2, 2, 2, 1, 1, 1, 1, 1, 1],
|
||||
[2, 2, 2, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 3, 3, 3, 1],
|
||||
[1, 1, 1, 1, 1, 3, 3, 3, 1],
|
||||
[1, 1, 1, 1, 1, 3, 3, 3, 1]], dtype=dtype)
|
||||
if minsize is not None:
|
||||
# increase data size by tiling (done to test various int types)
|
||||
nrow = math.ceil(math.sqrt(minsize / image.size))
|
||||
ncol = math.ceil(minsize / (image.size * nrow))
|
||||
image = np.tile(image, (nrow, ncol))
|
||||
mask = np.tile(mask, (nrow, ncol))
|
||||
expected = np.tile(expected, (nrow, ncol))
|
||||
out = reconstruction(image, mask)
|
||||
assert out.dtype == _supported_float_type(mask.dtype)
|
||||
assert_array_almost_equal(out, expected)
|
||||
|
||||
|
||||
def test_zero_image_one_mask():
|
||||
"""Test reconstruction with an image of all zeros and a mask that's not"""
|
||||
result = reconstruction(np.zeros((10, 10)), np.ones((10, 10)))
|
||||
assert_array_almost_equal(result, 0)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('dtype', [np.int8, np.uint8, np.int16, np.uint16,
|
||||
np.int32, np.uint32, np.int64, np.uint64,
|
||||
np.float16, np.float32, np.float64])
|
||||
def test_fill_hole(dtype):
|
||||
"""Test reconstruction by erosion, which should fill holes in mask."""
|
||||
seed = np.array([0, 8, 8, 8, 8, 8, 8, 8, 8, 0], dtype=dtype)
|
||||
mask = np.array([0, 3, 6, 2, 1, 1, 1, 4, 2, 0], dtype=dtype)
|
||||
result = reconstruction(seed, mask, method='erosion')
|
||||
assert result.dtype == _supported_float_type(mask.dtype)
|
||||
expected = np.array([0, 3, 6, 4, 4, 4, 4, 4, 2, 0], dtype=dtype)
|
||||
assert_array_almost_equal(result, expected)
|
||||
|
||||
|
||||
def test_invalid_seed():
|
||||
seed = np.ones((5, 5))
|
||||
mask = np.ones((5, 5))
|
||||
with pytest.raises(ValueError):
|
||||
reconstruction(seed * 2, mask,
|
||||
method='dilation')
|
||||
with pytest.raises(ValueError):
|
||||
reconstruction(seed * 0.5, mask,
|
||||
method='erosion')
|
||||
|
||||
|
||||
def test_invalid_footprint():
|
||||
seed = np.ones((5, 5))
|
||||
mask = np.ones((5, 5))
|
||||
with pytest.raises(ValueError):
|
||||
reconstruction(seed, mask,
|
||||
footprint=np.ones((4, 4)))
|
||||
with pytest.raises(ValueError):
|
||||
reconstruction(seed, mask,
|
||||
footprint=np.ones((3, 4)))
|
||||
reconstruction(seed, mask, footprint=np.ones((3, 3)))
|
||||
|
||||
|
||||
def test_invalid_method():
|
||||
seed = np.array([0, 8, 8, 8, 8, 8, 8, 8, 8, 0])
|
||||
mask = np.array([0, 3, 6, 2, 1, 1, 1, 4, 2, 0])
|
||||
with pytest.raises(ValueError):
|
||||
reconstruction(seed, mask, method='foo')
|
||||
|
||||
|
||||
def test_invalid_offset_not_none():
|
||||
"""Test reconstruction with invalid not None offset parameter"""
|
||||
image = np.array([[1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 2, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 1, 3, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1]])
|
||||
|
||||
mask = np.array([[4, 4, 4, 1, 1, 1, 1, 1],
|
||||
[4, 4, 4, 1, 1, 1, 1, 1],
|
||||
[4, 4, 4, 1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1, 4, 4, 4],
|
||||
[1, 1, 1, 1, 1, 4, 4, 4],
|
||||
[1, 1, 1, 1, 1, 4, 4, 4]])
|
||||
with pytest.raises(ValueError):
|
||||
reconstruction(image, mask, method='dilation',
|
||||
footprint=np.ones((3, 3)), offset=np.array([3, 0]))
|
||||
|
||||
|
||||
def test_offset_not_none():
|
||||
"""Test reconstruction with valid offset parameter"""
|
||||
seed = np.array([0, 3, 6, 2, 1, 1, 1, 4, 2, 0])
|
||||
mask = np.array([0, 8, 6, 8, 8, 8, 8, 4, 4, 0])
|
||||
expected = np.array([0, 3, 6, 6, 6, 6, 6, 4, 4, 0])
|
||||
|
||||
assert_array_almost_equal(
|
||||
reconstruction(seed, mask, method='dilation',
|
||||
footprint=np.ones(3), offset=np.array([0])), expected)
|
||||
229
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_skeletonize.py
vendored
Normal file
229
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_skeletonize.py
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
from numpy.testing import assert_array_equal
|
||||
from scipy.ndimage import correlate
|
||||
|
||||
from skimage import draw
|
||||
from skimage._shared.testing import fetch
|
||||
from skimage.io import imread
|
||||
from skimage.morphology import medial_axis, skeletonize, thin
|
||||
from skimage.morphology._skeletonize import (_generate_thin_luts,
|
||||
G123_LUT, G123P_LUT)
|
||||
|
||||
|
||||
class TestSkeletonize():
|
||||
def test_skeletonize_no_foreground(self):
|
||||
im = np.zeros((5, 5))
|
||||
result = skeletonize(im)
|
||||
assert_array_equal(result, np.zeros((5, 5)))
|
||||
|
||||
def test_skeletonize_wrong_dim1(self):
|
||||
im = np.zeros(5)
|
||||
with pytest.raises(ValueError):
|
||||
skeletonize(im)
|
||||
|
||||
def test_skeletonize_wrong_dim2(self):
|
||||
im = np.zeros((5, 5, 5))
|
||||
with pytest.raises(ValueError):
|
||||
skeletonize(im, method='zhang')
|
||||
|
||||
def test_skeletonize_all_foreground(self):
|
||||
im = np.ones((3, 4))
|
||||
skeletonize(im)
|
||||
|
||||
def test_skeletonize_single_point(self):
|
||||
im = np.zeros((5, 5), np.uint8)
|
||||
im[3, 3] = 1
|
||||
result = skeletonize(im)
|
||||
assert_array_equal(result, im)
|
||||
|
||||
def test_skeletonize_already_thinned(self):
|
||||
im = np.zeros((5, 5), np.uint8)
|
||||
im[3, 1:-1] = 1
|
||||
im[2, -1] = 1
|
||||
im[4, 0] = 1
|
||||
result = skeletonize(im)
|
||||
assert_array_equal(result, im)
|
||||
|
||||
def test_skeletonize_output(self):
|
||||
im = imread(fetch("data/bw_text.png"), as_gray=True)
|
||||
|
||||
# make black the foreground
|
||||
im = (im == 0)
|
||||
result = skeletonize(im)
|
||||
|
||||
expected = np.load(fetch("data/bw_text_skeleton.npy"))
|
||||
assert_array_equal(result, expected)
|
||||
|
||||
def test_skeletonize_num_neighbors(self):
|
||||
# an empty image
|
||||
image = np.zeros((300, 300))
|
||||
|
||||
# foreground object 1
|
||||
image[10:-10, 10:100] = 1
|
||||
image[-100:-10, 10:-10] = 1
|
||||
image[10:-10, -100:-10] = 1
|
||||
|
||||
# foreground object 2
|
||||
rs, cs = draw.line(250, 150, 10, 280)
|
||||
for i in range(10):
|
||||
image[rs + i, cs] = 1
|
||||
rs, cs = draw.line(10, 150, 250, 280)
|
||||
for i in range(20):
|
||||
image[rs + i, cs] = 1
|
||||
|
||||
# foreground object 3
|
||||
ir, ic = np.indices(image.shape)
|
||||
circle1 = (ic - 135)**2 + (ir - 150)**2 < 30**2
|
||||
circle2 = (ic - 135)**2 + (ir - 150)**2 < 20**2
|
||||
image[circle1] = 1
|
||||
image[circle2] = 0
|
||||
result = skeletonize(image)
|
||||
|
||||
# there should never be a 2x2 block of foreground pixels in a skeleton
|
||||
mask = np.array([[1, 1],
|
||||
[1, 1]], np.uint8)
|
||||
blocks = correlate(result, mask, mode='constant')
|
||||
assert not np.any(blocks == 4)
|
||||
|
||||
def test_lut_fix(self):
|
||||
im = np.zeros((6, 6), np.uint8)
|
||||
im[1, 2] = 1
|
||||
im[2, 2] = 1
|
||||
im[2, 3] = 1
|
||||
im[3, 3] = 1
|
||||
im[3, 4] = 1
|
||||
im[4, 4] = 1
|
||||
im[4, 5] = 1
|
||||
result = skeletonize(im)
|
||||
expected = np.array([[0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 0, 0, 1, 0],
|
||||
[0, 0, 0, 0, 0, 1],
|
||||
[0, 0, 0, 0, 0, 0]], dtype=np.uint8)
|
||||
assert np.all(result == expected)
|
||||
|
||||
|
||||
class TestThin():
|
||||
@property
|
||||
def input_image(self):
|
||||
"""image to test thinning with"""
|
||||
ii = np.array([[0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0],
|
||||
[0, 1, 0, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0]], dtype=np.uint8)
|
||||
return ii
|
||||
|
||||
def test_zeros(self):
|
||||
assert np.all(thin(np.zeros((10, 10))) == False)
|
||||
|
||||
def test_iter_1(self):
|
||||
result = thin(self.input_image, 1).astype(np.uint8)
|
||||
expected = np.array([[0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 0, 0, 0, 0],
|
||||
[0, 1, 0, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0]], dtype=np.uint8)
|
||||
assert_array_equal(result, expected)
|
||||
|
||||
def test_noiter(self):
|
||||
result = thin(self.input_image).astype(np.uint8)
|
||||
expected = np.array([[0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 0, 0, 0, 0],
|
||||
[0, 1, 0, 1, 0, 0, 0],
|
||||
[0, 0, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0]], dtype=np.uint8)
|
||||
assert_array_equal(result, expected)
|
||||
|
||||
def test_baddim(self):
|
||||
for ii in [np.zeros(3), np.zeros((3, 3, 3))]:
|
||||
with pytest.raises(ValueError):
|
||||
thin(ii)
|
||||
|
||||
def test_lut_generation(self):
|
||||
g123, g123p = _generate_thin_luts()
|
||||
|
||||
assert_array_equal(g123, G123_LUT)
|
||||
assert_array_equal(g123p, G123P_LUT)
|
||||
|
||||
|
||||
class TestMedialAxis():
|
||||
def test_00_00_zeros(self):
|
||||
'''Test skeletonize on an array of all zeros'''
|
||||
result = medial_axis(np.zeros((10, 10), bool))
|
||||
assert np.all(result == False)
|
||||
|
||||
def test_00_01_zeros_masked(self):
|
||||
'''Test skeletonize on an array that is completely masked'''
|
||||
result = medial_axis(np.zeros((10, 10), bool),
|
||||
np.zeros((10, 10), bool))
|
||||
assert np.all(result == False)
|
||||
|
||||
def test_vertical_line(self):
|
||||
'''Test a thick vertical line, issue #3861'''
|
||||
img = np.zeros((9, 9))
|
||||
img[:, 2] = 1
|
||||
img[:, 3] = 1
|
||||
img[:, 4] = 1
|
||||
|
||||
expected = np.full(img.shape, False)
|
||||
expected[:, 3] = True
|
||||
|
||||
result = medial_axis(img)
|
||||
assert_array_equal(result, expected)
|
||||
|
||||
def test_01_01_rectangle(self):
|
||||
'''Test skeletonize on a rectangle'''
|
||||
image = np.zeros((9, 15), bool)
|
||||
image[1:-1, 1:-1] = True
|
||||
#
|
||||
# The result should be four diagonals from the
|
||||
# corners, meeting in a horizontal line
|
||||
#
|
||||
expected = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=bool)
|
||||
result = medial_axis(image)
|
||||
assert np.all(result == expected)
|
||||
result, distance = medial_axis(image, return_distance=True)
|
||||
assert distance.max() == 4
|
||||
|
||||
def test_01_02_hole(self):
|
||||
'''Test skeletonize on a rectangle with a hole in the middle'''
|
||||
image = np.zeros((9, 15), bool)
|
||||
image[1:-1, 1:-1] = True
|
||||
image[4, 4:-4] = False
|
||||
expected = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=bool)
|
||||
result = medial_axis(image)
|
||||
assert np.all(result == expected)
|
||||
|
||||
def test_narrow_image(self):
|
||||
"""Test skeletonize on a 1-pixel thin strip"""
|
||||
image = np.zeros((1, 5), bool)
|
||||
image[:, 1:-1] = True
|
||||
result = medial_axis(image)
|
||||
assert np.all(result == image)
|
||||
185
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_skeletonize_3d.py
vendored
Normal file
185
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_skeletonize_3d.py
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
import numpy as np
|
||||
import scipy.ndimage as ndi
|
||||
|
||||
from skimage import io, draw
|
||||
from skimage.data import binary_blobs
|
||||
from skimage.util import img_as_ubyte
|
||||
from skimage.morphology import skeletonize, skeletonize_3d
|
||||
|
||||
from skimage._shared import testing
|
||||
from skimage._shared.testing import assert_equal, assert_, parametrize, fetch
|
||||
|
||||
# basic behavior tests (mostly copied over from 2D skeletonize)
|
||||
|
||||
def test_skeletonize_wrong_dim():
|
||||
im = np.zeros(5, dtype=np.uint8)
|
||||
with testing.raises(ValueError):
|
||||
skeletonize(im, method='lee')
|
||||
|
||||
im = np.zeros((5, 5, 5, 5), dtype=np.uint8)
|
||||
with testing.raises(ValueError):
|
||||
skeletonize(im, method='lee')
|
||||
|
||||
|
||||
def test_skeletonize_1D_old_api():
|
||||
# a corner case of an image of a shape(1, N)
|
||||
im = np.ones((5, 1), dtype=np.uint8)
|
||||
res = skeletonize_3d(im)
|
||||
assert_equal(res, im)
|
||||
|
||||
|
||||
def test_skeletonize_1D():
|
||||
# a corner case of an image of a shape(1, N)
|
||||
im = np.ones((5, 1), dtype=np.uint8)
|
||||
res = skeletonize(im, method='lee')
|
||||
assert_equal(res, im)
|
||||
|
||||
|
||||
def test_skeletonize_no_foreground():
|
||||
im = np.zeros((5, 5), dtype=np.uint8)
|
||||
result = skeletonize(im, method='lee')
|
||||
assert_equal(result, im)
|
||||
|
||||
|
||||
def test_skeletonize_all_foreground():
|
||||
im = np.ones((3, 4), dtype=np.uint8)
|
||||
assert_equal(skeletonize(im, method='lee'),
|
||||
np.array([[0, 0, 0, 0],
|
||||
[1, 1, 1, 1],
|
||||
[0, 0, 0, 0]], dtype=np.uint8))
|
||||
|
||||
|
||||
def test_skeletonize_single_point():
|
||||
im = np.zeros((5, 5), dtype=np.uint8)
|
||||
im[3, 3] = 1
|
||||
result = skeletonize(im, method='lee')
|
||||
assert_equal(result, im)
|
||||
|
||||
|
||||
def test_skeletonize_already_thinned():
|
||||
im = np.zeros((5, 5), dtype=np.uint8)
|
||||
im[3, 1:-1] = 1
|
||||
im[2, -1] = 1
|
||||
im[4, 0] = 1
|
||||
result = skeletonize(im, method='lee')
|
||||
assert_equal(result, im)
|
||||
|
||||
|
||||
def test_dtype_conv():
|
||||
# check that the operation does the right thing with floats etc
|
||||
# also check non-contiguous input
|
||||
img = np.random.random((16, 16))[::2, ::2]
|
||||
img[img < 0.5] = 0
|
||||
|
||||
orig = img.copy()
|
||||
res = skeletonize(img, method='lee')
|
||||
img_max = img_as_ubyte(img).max()
|
||||
|
||||
assert_equal(res.dtype, np.uint8)
|
||||
assert_equal(img, orig) # operation does not clobber the original
|
||||
assert_equal(res.max(), img_max) # the intensity range is preserved
|
||||
|
||||
|
||||
@parametrize("img", [
|
||||
np.ones((8, 8), dtype=float), np.ones((4, 8, 8), dtype=float)
|
||||
])
|
||||
def test_input_with_warning(img):
|
||||
# check that the input is not clobbered
|
||||
# for 2D and 3D images of varying dtypes
|
||||
check_input(img)
|
||||
|
||||
|
||||
@parametrize("img", [
|
||||
np.ones((8, 8), dtype=np.uint8), np.ones((4, 8, 8), dtype=np.uint8),
|
||||
np.ones((8, 8), dtype=bool), np.ones((4, 8, 8), dtype=bool)
|
||||
])
|
||||
def test_input_without_warning(img):
|
||||
# check that the input is not clobbered
|
||||
# for 2D and 3D images of varying dtypes
|
||||
check_input(img)
|
||||
|
||||
|
||||
def check_input(img):
|
||||
orig = img.copy()
|
||||
skeletonize(img, method='lee')
|
||||
assert_equal(img, orig)
|
||||
|
||||
|
||||
def test_skeletonize_num_neighbors():
|
||||
# an empty image
|
||||
image = np.zeros((300, 300))
|
||||
|
||||
# foreground object 1
|
||||
image[10:-10, 10:100] = 1
|
||||
image[-100:-10, 10:-10] = 1
|
||||
image[10:-10, -100:-10] = 1
|
||||
|
||||
# foreground object 2
|
||||
rs, cs = draw.line(250, 150, 10, 280)
|
||||
for i in range(10):
|
||||
image[rs + i, cs] = 1
|
||||
rs, cs = draw.line(10, 150, 250, 280)
|
||||
for i in range(20):
|
||||
image[rs + i, cs] = 1
|
||||
|
||||
# foreground object 3
|
||||
ir, ic = np.indices(image.shape)
|
||||
circle1 = (ic - 135)**2 + (ir - 150)**2 < 30**2
|
||||
circle2 = (ic - 135)**2 + (ir - 150)**2 < 20**2
|
||||
image[circle1] = 1
|
||||
image[circle2] = 0
|
||||
result = skeletonize(image, method='lee')
|
||||
|
||||
# there should never be a 2x2 block of foreground pixels in a skeleton
|
||||
mask = np.array([[1, 1],
|
||||
[1, 1]], np.uint8)
|
||||
blocks = ndi.correlate(result, mask, mode='constant')
|
||||
assert_(not np.any(blocks == 4))
|
||||
|
||||
|
||||
def test_two_hole_image():
|
||||
# test a simple 2D image against FIJI
|
||||
img_o = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0],
|
||||
[0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0],
|
||||
[0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0],
|
||||
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=np.uint8)
|
||||
img_f = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
|
||||
dtype=np.uint8)
|
||||
res = skeletonize(img_o, method='lee')
|
||||
assert_equal(res, img_f)
|
||||
|
||||
|
||||
def test_3d_vs_fiji():
|
||||
# generate an image with blobs and compate its skeleton to
|
||||
# the skeleton generated by FIJI (Plugins>Skeleton->Skeletonize)
|
||||
img = binary_blobs(32, 0.05, n_dim=3, seed=1234)
|
||||
img = img[:-2, ...]
|
||||
img = img.astype(np.uint8)*255
|
||||
|
||||
img_s = skeletonize(img)
|
||||
img_f = io.imread(fetch("data/_blobs_3d_fiji_skeleton.tif"))
|
||||
assert_equal(img_s, img_f)
|
||||
126
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_util.py
vendored
Normal file
126
.CondaPkg/env/Lib/site-packages/skimage/morphology/tests/test_util.py
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
"""Tests for `_util`."""
|
||||
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
from numpy.testing import assert_array_equal
|
||||
|
||||
from skimage.morphology import _util
|
||||
|
||||
|
||||
@pytest.mark.parametrize("image_shape", [
|
||||
(111,), (33, 44), (22, 55, 11), (6, 5, 4, 3)
|
||||
])
|
||||
@pytest.mark.parametrize("order", ["C", "F"])
|
||||
def test_offsets_to_raveled_neighbors_highest_connectivity(image_shape, order):
|
||||
"""
|
||||
Check scenarios where footprint is always of the highest connectivity
|
||||
and all dimensions are > 2.
|
||||
"""
|
||||
footprint = np.ones((3,) * len(image_shape), dtype=bool)
|
||||
center = (1,) * len(image_shape)
|
||||
offsets = _util._offsets_to_raveled_neighbors(
|
||||
image_shape, footprint, center, order
|
||||
)
|
||||
|
||||
# Assert only neighbors are present, center was removed
|
||||
assert len(offsets) == footprint.sum() - 1
|
||||
assert 0 not in offsets
|
||||
# Assert uniqueness
|
||||
assert len(set(offsets)) == offsets.size
|
||||
# offsets form pairs of with same value but different signs
|
||||
# if footprint is symmetric around center
|
||||
assert all(-x in offsets for x in offsets)
|
||||
|
||||
# Construct image whose values are the Manhattan distance to its center
|
||||
image_center = tuple(s // 2 for s in image_shape)
|
||||
coords = [
|
||||
np.abs(np.arange(s, dtype=np.intp) - c)
|
||||
for s, c in zip(image_shape, image_center)
|
||||
]
|
||||
grid = np.meshgrid(*coords, indexing="ij")
|
||||
image = np.sum(grid, axis=0)
|
||||
|
||||
image_raveled = image.ravel(order)
|
||||
image_center_raveled = np.ravel_multi_index(
|
||||
image_center, image_shape, order=order
|
||||
)
|
||||
|
||||
# Sample raveled image around its center
|
||||
samples = []
|
||||
for offset in offsets:
|
||||
index = image_center_raveled + offset
|
||||
samples.append(image_raveled[index])
|
||||
|
||||
# Assert that center with value 0 wasn't selected
|
||||
assert np.min(samples) == 1
|
||||
# Assert that only neighbors where selected
|
||||
# (highest value == connectivity)
|
||||
assert np.max(samples) == len(image_shape)
|
||||
# Assert that nearest neighbors are selected first
|
||||
assert list(sorted(samples)) == samples
|
||||
|
||||
|
||||
@pytest.mark.parametrize("image_shape", [
|
||||
(2,), (2, 2), (2, 1, 2), (2, 2, 1, 2), (0, 2, 1, 2)
|
||||
])
|
||||
@pytest.mark.parametrize("order", ["C", "F"])
|
||||
def test_offsets_to_raveled_neighbors_footprint_smaller_image(image_shape,
|
||||
order):
|
||||
"""
|
||||
Test if a dimension indicated by `image_shape` is smaller than in
|
||||
`footprint`.
|
||||
"""
|
||||
footprint = np.ones((3,) * len(image_shape), dtype=bool)
|
||||
center = (1,) * len(image_shape)
|
||||
offsets = _util._offsets_to_raveled_neighbors(
|
||||
image_shape, footprint, center, order
|
||||
)
|
||||
|
||||
# Assert only neighbors are present, center and duplicates (possible
|
||||
# for this scenario) where removed
|
||||
assert len(offsets) <= footprint.sum() - 1
|
||||
assert 0 not in offsets
|
||||
# Assert uniqueness
|
||||
assert len(set(offsets)) == offsets.size
|
||||
# offsets form pairs of with same value but different signs
|
||||
# if footprint is symmetric around center
|
||||
assert all(-x in offsets for x in offsets)
|
||||
|
||||
|
||||
def test_offsets_to_raveled_neighbors_explicit_0():
|
||||
"""Check reviewed example."""
|
||||
image_shape = (100, 200, 3)
|
||||
footprint = np.ones((3, 3, 3), dtype=bool)
|
||||
center = (1, 1, 1)
|
||||
offsets = _util._offsets_to_raveled_neighbors(
|
||||
image_shape, footprint, center
|
||||
)
|
||||
|
||||
desired = np.array([
|
||||
3, -600, 1, -1, 600, -3, 4, 2, 603, -2, -4,
|
||||
-597, 601, -599, -601, -603, 599, 597, 602, -604, 596, -596,
|
||||
-598, -602, 598, 604
|
||||
])
|
||||
assert_array_equal(offsets, desired)
|
||||
|
||||
|
||||
def test_offsets_to_raveled_neighbors_explicit_1():
|
||||
"""Check reviewed example where footprint is larger in last dimension."""
|
||||
image_shape = (10, 9, 8, 3)
|
||||
footprint = np.ones((3, 3, 3, 4), dtype=bool)
|
||||
center = (1, 1, 1, 1)
|
||||
offsets = _util._offsets_to_raveled_neighbors(
|
||||
image_shape, footprint, center
|
||||
)
|
||||
|
||||
desired = np.array([
|
||||
216, 24, -24, 3, -216, 1, -1, -3, 215, -27, -25, -23, -21, -2,
|
||||
-192, 192, 2, 4, 21, 23, 25, 27, -4, 217, 213, -219, 219, -217,
|
||||
-213, -215, 240, -240, 193, 239, -237, 241, -239, 218, -220, 22,
|
||||
-241, 243, 189, 26, -243, 191, 20, -218, 195, -193, 220, -191,
|
||||
-212, -189, 214, 28, -195, -214, -28, 212, -22, 237, -20, -26, 236,
|
||||
196, 190, 242, 238, 194, 188, -244, -188, -196, -194, -190, -238,
|
||||
-236, 244, -242, 5, 221, -211, -19, 29, -235, -187, 197, 245
|
||||
])
|
||||
assert_array_equal(offsets, desired)
|
||||
Reference in New Issue
Block a user