mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-23 13:10:18 +08:00
Update edge detectors to produce values in [0, 1] and clean up tests
This commit is contained in:
+19
-11
@@ -82,7 +82,9 @@ def sobel(image, mask=None):
|
||||
has to be further processed to perform edge detection.
|
||||
"""
|
||||
assert_nD(image, 2)
|
||||
return np.sqrt(hsobel(image, mask)**2 + vsobel(image, mask)**2)
|
||||
out = np.sqrt(hsobel(image, mask)**2 + vsobel(image, mask)**2)
|
||||
out /= np.sqrt(2)
|
||||
return out
|
||||
|
||||
|
||||
def hsobel(image, mask=None):
|
||||
@@ -176,11 +178,13 @@ def scharr(image, mask=None):
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] D. Kroon, 2009, Short Paper University Twente, Numerical Optimization
|
||||
of Kernel Based Image Derivatives.
|
||||
.. [1] D. Kroon, 2009, Short Paper University Twente, Numerical
|
||||
Optimization of Kernel Based Image Derivatives.
|
||||
|
||||
"""
|
||||
return np.sqrt(hscharr(image, mask)**2 + vscharr(image, mask)**2)
|
||||
out = np.sqrt(hscharr(image, mask)**2 + vscharr(image, mask)**2)
|
||||
out /= np.sqrt(2)
|
||||
return out
|
||||
|
||||
|
||||
def hscharr(image, mask=None):
|
||||
@@ -211,8 +215,8 @@ def hscharr(image, mask=None):
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] D. Kroon, 2009, Short Paper University Twente, Numerical Optimization
|
||||
of Kernel Based Image Derivatives.
|
||||
.. [1] D. Kroon, 2009, Short Paper University Twente, Numerical
|
||||
Optimization of Kernel Based Image Derivatives.
|
||||
|
||||
"""
|
||||
assert_nD(image, 2)
|
||||
@@ -249,8 +253,8 @@ def vscharr(image, mask=None):
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] D. Kroon, 2009, Short Paper University Twente, Numerical Optimization
|
||||
of Kernel Based Image Derivatives.
|
||||
.. [1] D. Kroon, 2009, Short Paper University Twente, Numerical
|
||||
Optimization of Kernel Based Image Derivatives.
|
||||
|
||||
"""
|
||||
assert_nD(image, 2)
|
||||
@@ -282,7 +286,9 @@ def prewitt(image, mask=None):
|
||||
and vertical Prewitt transforms.
|
||||
"""
|
||||
assert_nD(image, 2)
|
||||
return np.sqrt(hprewitt(image, mask)**2 + vprewitt(image, mask)**2)
|
||||
out = np.sqrt(hprewitt(image, mask)**2 + vprewitt(image, mask)**2)
|
||||
out /= np.sqrt(2)
|
||||
return out
|
||||
|
||||
|
||||
def hprewitt(image, mask=None):
|
||||
@@ -369,8 +375,10 @@ def roberts(image, mask=None):
|
||||
The Roberts' Cross edge map.
|
||||
"""
|
||||
assert_nD(image, 2)
|
||||
return np.sqrt(roberts_positive_diagonal(image, mask)**2 +
|
||||
roberts_negative_diagonal(image, mask)**2)
|
||||
out = np.sqrt(roberts_positive_diagonal(image, mask)**2 +
|
||||
roberts_negative_diagonal(image, mask)**2)
|
||||
out /= np.sqrt(2)
|
||||
return out
|
||||
|
||||
|
||||
def roberts_positive_diagonal(image, mask=None):
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import numpy as np
|
||||
from numpy.testing import assert_array_almost_equal as assert_close
|
||||
from numpy.testing import (assert_array_almost_equal as assert_close,
|
||||
assert_, assert_allclose)
|
||||
|
||||
import skimage.filter as F
|
||||
from skimage.filter.edges import _mask_filter_result
|
||||
@@ -49,10 +50,10 @@ def test_sobel_horizontal():
|
||||
"""Sobel on a horizontal edge should be a horizontal line."""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (i >= 0).astype(float)
|
||||
result = F.sobel(image)
|
||||
result = F.sobel(image) * np.sqrt(2)
|
||||
# Fudge the eroded points
|
||||
i[np.abs(j) == 5] = 10000
|
||||
assert (np.all(result[i == 0] == 1))
|
||||
assert_allclose(result[i == 0], 1)
|
||||
assert (np.all(result[np.abs(i) > 1] == 0))
|
||||
|
||||
|
||||
@@ -60,7 +61,7 @@ def test_sobel_vertical():
|
||||
"""Sobel on a vertical edge should be a vertical line."""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (j >= 0).astype(float)
|
||||
result = F.sobel(image)
|
||||
result = F.sobel(image) * np.sqrt(2)
|
||||
j[np.abs(i) == 5] = 10000
|
||||
assert (np.all(result[j == 0] == 1))
|
||||
assert (np.all(result[np.abs(j) > 1] == 0))
|
||||
@@ -94,15 +95,15 @@ def test_hsobel_horizontal():
|
||||
def test_hsobel_vertical():
|
||||
"""Horizontal Sobel on a vertical edge should be zero."""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (j >= 0).astype(float)
|
||||
image = (j >= 0).astype(float) * np.sqrt(2)
|
||||
result = F.hsobel(image)
|
||||
assert (np.all(result == 0))
|
||||
assert_allclose(result, 0, atol=1e-10)
|
||||
|
||||
|
||||
def test_vsobel_zeros():
|
||||
"""Vertical sobel on an array of all zeros."""
|
||||
result = F.vsobel(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_vsobel_mask():
|
||||
@@ -110,7 +111,7 @@ def test_vsobel_mask():
|
||||
np.random.seed(0)
|
||||
result = F.vsobel(np.random.uniform(size=(10, 10)),
|
||||
np.zeros((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_vsobel_vertical():
|
||||
@@ -129,32 +130,31 @@ def test_vsobel_horizontal():
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (i >= 0).astype(float)
|
||||
result = F.vsobel(image)
|
||||
eps = .000001
|
||||
assert (np.all(np.abs(result) < eps))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_scharr_zeros():
|
||||
"""Scharr on an array of all zeros."""
|
||||
result = F.scharr(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
assert (np.all(result < 1e-16))
|
||||
|
||||
|
||||
def test_scharr_mask():
|
||||
"""Scharr on a masked array should be zero."""
|
||||
np.random.seed(0)
|
||||
result = F.scharr(np.random.uniform(size=(10, 10)),
|
||||
np.zeros((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
np.zeros((10, 10), bool))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_scharr_horizontal():
|
||||
"""Scharr on an edge should be a horizontal line."""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (i >= 0).astype(float)
|
||||
result = F.scharr(image)
|
||||
result = F.scharr(image) * np.sqrt(2)
|
||||
# Fudge the eroded points
|
||||
i[np.abs(j) == 5] = 10000
|
||||
assert (np.all(result[i == 0] == 1))
|
||||
assert_allclose(result[i == 0], 1)
|
||||
assert (np.all(result[np.abs(i) > 1] == 0))
|
||||
|
||||
|
||||
@@ -162,24 +162,24 @@ def test_scharr_vertical():
|
||||
"""Scharr on a vertical edge should be a vertical line."""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (j >= 0).astype(float)
|
||||
result = F.scharr(image)
|
||||
result = F.scharr(image) * np.sqrt(2)
|
||||
j[np.abs(i) == 5] = 10000
|
||||
assert (np.all(result[j == 0] == 1))
|
||||
assert_allclose(result[j == 0], 1)
|
||||
assert (np.all(result[np.abs(j) > 1] == 0))
|
||||
|
||||
|
||||
def test_hscharr_zeros():
|
||||
"""Horizontal Scharr on an array of all zeros."""
|
||||
result = F.hscharr(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_hscharr_mask():
|
||||
"""Horizontal Scharr on a masked array should be zero."""
|
||||
np.random.seed(0)
|
||||
result = F.hscharr(np.random.uniform(size=(10, 10)),
|
||||
np.zeros((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
np.zeros((10, 10), bool))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_hscharr_horizontal():
|
||||
@@ -198,21 +198,21 @@ def test_hscharr_vertical():
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (j >= 0).astype(float)
|
||||
result = F.hscharr(image)
|
||||
assert (np.all(result == 0))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_vscharr_zeros():
|
||||
"""Vertical Scharr on an array of all zeros."""
|
||||
result = F.vscharr(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_vscharr_mask():
|
||||
"""Vertical Scharr on a masked array should be zero."""
|
||||
np.random.seed(0)
|
||||
result = F.vscharr(np.random.uniform(size=(10, 10)),
|
||||
np.zeros((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
np.zeros((10, 10), bool))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_vscharr_vertical():
|
||||
@@ -231,14 +231,13 @@ def test_vscharr_horizontal():
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (i >= 0).astype(float)
|
||||
result = F.vscharr(image)
|
||||
eps = .000001
|
||||
assert (np.all(np.abs(result) < eps))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_prewitt_zeros():
|
||||
"""Prewitt on an array of all zeros."""
|
||||
result = F.prewitt(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_prewitt_mask():
|
||||
@@ -246,37 +245,34 @@ def test_prewitt_mask():
|
||||
np.random.seed(0)
|
||||
result = F.prewitt(np.random.uniform(size=(10, 10)),
|
||||
np.zeros((10, 10), bool))
|
||||
eps = .000001
|
||||
assert (np.all(np.abs(result) < eps))
|
||||
assert_allclose(np.abs(result), 0)
|
||||
|
||||
|
||||
def test_prewitt_horizontal():
|
||||
"""Prewitt on an edge should be a horizontal line."""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (i >= 0).astype(float)
|
||||
result = F.prewitt(image)
|
||||
result = F.prewitt(image) * np.sqrt(2)
|
||||
# Fudge the eroded points
|
||||
i[np.abs(j) == 5] = 10000
|
||||
eps = .000001
|
||||
assert (np.all(result[i == 0] == 1))
|
||||
assert (np.all(np.abs(result[np.abs(i) > 1]) < eps))
|
||||
assert_allclose(result[np.abs(i) > 1], 0, atol=1e-10)
|
||||
|
||||
|
||||
def test_prewitt_vertical():
|
||||
"""Prewitt on a vertical edge should be a vertical line."""
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (j >= 0).astype(float)
|
||||
result = F.prewitt(image)
|
||||
eps = .000001
|
||||
result = F.prewitt(image) * np.sqrt(2)
|
||||
j[np.abs(i) == 5] = 10000
|
||||
assert (np.all(result[j == 0] == 1))
|
||||
assert (np.all(np.abs(result[np.abs(j) > 1]) < eps))
|
||||
assert_allclose(result[j == 0], 1)
|
||||
assert_allclose(result[np.abs(j) > 1], 0, atol=1e-10)
|
||||
|
||||
|
||||
def test_hprewitt_zeros():
|
||||
"""Horizontal prewitt on an array of all zeros."""
|
||||
result = F.hprewitt(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_hprewitt_mask():
|
||||
@@ -284,8 +280,7 @@ def test_hprewitt_mask():
|
||||
np.random.seed(0)
|
||||
result = F.hprewitt(np.random.uniform(size=(10, 10)),
|
||||
np.zeros((10, 10), bool))
|
||||
eps = .000001
|
||||
assert (np.all(np.abs(result) < eps))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_hprewitt_horizontal():
|
||||
@@ -295,9 +290,8 @@ def test_hprewitt_horizontal():
|
||||
result = F.hprewitt(image)
|
||||
# Fudge the eroded points
|
||||
i[np.abs(j) == 5] = 10000
|
||||
eps = .000001
|
||||
assert (np.all(result[i == 0] == 1))
|
||||
assert (np.all(np.abs(result[np.abs(i) > 1]) < eps))
|
||||
assert_allclose(result[np.abs(i) > 1], 0, atol=1e-10)
|
||||
|
||||
|
||||
def test_hprewitt_vertical():
|
||||
@@ -305,14 +299,13 @@ def test_hprewitt_vertical():
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (j >= 0).astype(float)
|
||||
result = F.hprewitt(image)
|
||||
eps = .000001
|
||||
assert (np.all(np.abs(result) < eps))
|
||||
assert_allclose(result, 0, atol=1e-10)
|
||||
|
||||
|
||||
def test_vprewitt_zeros():
|
||||
"""Vertical prewitt on an array of all zeros."""
|
||||
result = F.vprewitt(np.zeros((10, 10)), np.ones((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_vprewitt_mask():
|
||||
@@ -320,7 +313,7 @@ def test_vprewitt_mask():
|
||||
np.random.seed(0)
|
||||
result = F.vprewitt(np.random.uniform(size=(10, 10)),
|
||||
np.zeros((10, 10), bool))
|
||||
assert (np.all(result == 0))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_vprewitt_vertical():
|
||||
@@ -331,8 +324,7 @@ def test_vprewitt_vertical():
|
||||
# Fudge the eroded points
|
||||
j[np.abs(i) == 5] = 10000
|
||||
assert (np.all(result[j == 0] == 1))
|
||||
eps = .000001
|
||||
assert (np.all(np.abs(result[np.abs(j) > 1]) < eps))
|
||||
assert_allclose(result[np.abs(j) > 1], 0, atol=1e-10)
|
||||
|
||||
|
||||
def test_vprewitt_horizontal():
|
||||
@@ -340,21 +332,20 @@ def test_vprewitt_horizontal():
|
||||
i, j = np.mgrid[-5:6, -5:6]
|
||||
image = (i >= 0).astype(float)
|
||||
result = F.vprewitt(image)
|
||||
eps = .000001
|
||||
assert (np.all(np.abs(result) < eps))
|
||||
assert_allclose(result, 0)
|
||||
|
||||
|
||||
def test_horizontal_mask_line():
|
||||
"""Horizontal edge filters mask pixels surrounding input mask."""
|
||||
vgrad, _ = np.mgrid[:1:11j, :1:11j] # vertical gradient with spacing 0.1
|
||||
vgrad[5, :] = 1 # bad horizontal line
|
||||
vgrad, _ = np.mgrid[:1:11j, :1:11j] # vertical gradient with spacing 0.1
|
||||
vgrad[5, :] = 1 # bad horizontal line
|
||||
|
||||
mask = np.ones_like(vgrad)
|
||||
mask[5, :] = 0 # mask bad line
|
||||
mask[5, :] = 0 # mask bad line
|
||||
|
||||
expected = np.zeros_like(vgrad)
|
||||
expected[1:-1, 1:-1] = 0.2 # constant gradient for most of image,
|
||||
expected[4:7, 1:-1] = 0 # but line and neighbors masked
|
||||
expected[1:-1, 1:-1] = 0.2 # constant gradient for most of image,
|
||||
expected[4:7, 1:-1] = 0 # but line and neighbors masked
|
||||
|
||||
for grad_func in (F.hprewitt, F.hsobel, F.hscharr):
|
||||
result = grad_func(vgrad, mask)
|
||||
@@ -363,21 +354,36 @@ def test_horizontal_mask_line():
|
||||
|
||||
def test_vertical_mask_line():
|
||||
"""Vertical edge filters mask pixels surrounding input mask."""
|
||||
_, hgrad = np.mgrid[:1:11j, :1:11j] # horizontal gradient with spacing 0.1
|
||||
hgrad[:, 5] = 1 # bad vertical line
|
||||
_, hgrad = np.mgrid[:1:11j, :1:11j] # horizontal gradient with spacing 0.1
|
||||
hgrad[:, 5] = 1 # bad vertical line
|
||||
|
||||
mask = np.ones_like(hgrad)
|
||||
mask[:, 5] = 0 # mask bad line
|
||||
mask[:, 5] = 0 # mask bad line
|
||||
|
||||
expected = np.zeros_like(hgrad)
|
||||
expected[1:-1, 1:-1] = 0.2 # constant gradient for most of image,
|
||||
expected[1:-1, 4:7] = 0 # but line and neighbors masked
|
||||
expected[1:-1, 1:-1] = 0.2 # constant gradient for most of image,
|
||||
expected[1:-1, 4:7] = 0 # but line and neighbors masked
|
||||
|
||||
for grad_func in (F.vprewitt, F.vsobel, F.vscharr):
|
||||
result = grad_func(hgrad, mask)
|
||||
yield assert_close, result, expected
|
||||
|
||||
|
||||
def test_range():
|
||||
"""Output of edge detection should be in [0, 1]"""
|
||||
image = np.random.random((100, 100))
|
||||
for detector in (F.sobel, F.scharr, F.prewitt, F.roberts):
|
||||
out = detector(image)
|
||||
assert_(out.min() >= 0,
|
||||
"Minimum of `{0}` is smaller than zero".format(
|
||||
detector.__name__)
|
||||
)
|
||||
assert_(out.max() <= 1,
|
||||
"Maximum of `{0}` is larger than 1".format(
|
||||
detector.__name__)
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from numpy import testing
|
||||
testing.run_module_suite()
|
||||
|
||||
Reference in New Issue
Block a user