ENH: Minor clean-ups to edge-detection patch.

This commit is contained in:
Stefan van der Walt
2011-04-19 14:57:11 +02:00
parent f3dd496d1f
commit cbb84d5588
2 changed files with 98 additions and 90 deletions
+64 -56
View File
@@ -12,15 +12,15 @@ import numpy as np
from scipy.ndimage import convolve, binary_erosion, generate_binary_structure
def sobel(image, mask=None):
"""Calculate the absolute magnitude Sobel to find the edges.
"""Calculate the absolute magnitude Sobel to find edges.
Parameters
----------
image : array_like, dtype=float
Image to process
Image to process.
mask : array_like, dtype=bool, optional
An optional mask to limit the application to a certain area
An optional mask to limit the application to a certain area.
Returns
-------
output : ndarray
@@ -31,34 +31,36 @@ def sobel(image, mask=None):
Take the square root of the sum of the squares of the horizontal and
vertical Sobels to get a magnitude that's somewhat insensitive to
direction.
Note that scipy's Sobel returns a directional Sobel which isn't
useful for edge detection in its raw form.
Note that ``scipy.ndimage.sobel`` returns a directional Sobel which
has to be further processed to perform edge detection.
"""
return np.sqrt(hsobel(image,mask)**2 + vsobel(image,mask)**2)
return np.sqrt(hsobel(image, mask)**2 + vsobel(image, mask)**2)
def hsobel(image, mask=None):
"""Find the horizontal edges of an image using the Sobel transform
"""Find the horizontal edges of an image using the Sobel transform.
Parameters
----------
image : array_like, dtype=float
Image to process
Image to process.
mask : array_like, dtype=bool, optional
An optional mask to limit the application to a certain area.
Returns
-------
output : ndarray
The Sobel edge map.
Notes
-----
We use the following kernel and return the absolute value of the
result at each point:
1 2 1
0 0 0
-1 -2 -1
result at each point::
1 2 1
0 0 0
-1 -2 -1
"""
if mask is None:
mask = np.ones(image.shape, bool)
@@ -73,88 +75,92 @@ def hsobel(image, mask=None):
def vsobel(image, mask=None):
"""Find the vertical edges of an image using the Sobel transform.
Parameters
----------
image : array_like, dtype=float
Image to process
mask : array_like, dtype=bool, optional
An optional mask to limit the application to a certain area
Returns
-------
output : ndarray
The Sobel edge map.
Notes
-----
We use the following kernel and return the absolute value of the
result at each point:
1 0 -1
2 0 -2
1 0 -1
result at each point::
1 0 -1
2 0 -2
1 0 -1
"""
if mask is None:
mask = np.ones(image.shape, bool)
big_mask = binary_erosion(mask,
generate_binary_structure(2, 2),
border_value = 0)
result = np.abs(convolve(image, np.array([[ 1, 0,-1],
[ 2, 0,-2],
[ 1, 0,-1]]).astype(float) / 4.0))
border_value=0)
result = np.abs(convolve(image, np.array([[1, 0, -1],
[2, 0, -2],
[1, 0, -1]]).astype(float) / 4.0))
result[big_mask == False] = 0
return result
def prewitt(image, mask=None):
"""Find the edge magnitude using the Prewitt transform.
Parameters
----------
image : array_like, dtype=float
Image to process
Image to process.
mask : array_like, dtype=bool, optional
An optional mask to limit the application to a certain area
An optional mask to limit the application to a certain area.
Returns
-------
output : ndarray
The Prewitt edge map.
Notes
-----
Return the square root of the sum of squares of the horizontal
and vertical Prewitt transforms.
"""
return np.sqrt(hprewitt(image, mask) ** 2 + vprewitt(image, mask) ** 2)
def hprewitt(image, mask=None):
"""Find the horizontal edges of an image using the Prewitt transform.
Parameters
----------
image : array_like, dtype=float
Image to process
Image to process.
mask : array_like, dtype=bool, optional
An optional mask to limit the application to a certain area
An optional mask to limit the application to a certain area.
Returns
-------
output : ndarray
The Prewitt edge map.
Notes
-----
We use the following kernel and return the absolute value of the
result at each point:
1 1 1
0 0 0
-1 -1 -1
result at each point::
1 1 1
0 0 0
-1 -1 -1
"""
if mask is None:
mask = np.ones(image.shape, bool)
big_mask = binary_erosion(mask,
generate_binary_structure(2, 2),
border_value = 0)
border_value=0)
result = np.abs(convolve(image, np.array([[ 1, 1, 1],
[ 0, 0, 0],
[-1,-1,-1]]).astype(float) / 3.0))
@@ -163,34 +169,36 @@ def hprewitt(image, mask=None):
def vprewitt(image, mask=None):
"""Find the vertical edges of an image using the Prewitt transform.
Parameters
----------
image : array_like, dtype=float
Image to process
Image to process.
mask : array_like, dtype=bool, optional
An optional mask to limit the application to a certain area
An optional mask to limit the application to a certain area.
Returns
-------
output : ndarray
The Prewitt edge map.
Notes
-----
We use the following kernel and return the absolute value of the
result at each point:
1 0 -1
1 0 -1
1 0 -1
result at each point::
1 0 -1
1 0 -1
1 0 -1
"""
if mask is None:
mask = np.ones(image.shape, bool)
big_mask = binary_erosion(mask,
generate_binary_structure(2, 2),
border_value=0)
result = np.abs(convolve(image, np.array([[ 1, 0,-1],
[ 1, 0,-1],
[ 1, 0,-1]]).astype(float) / 3.0))
result = np.abs(convolve(image, np.array([[1, 0, -1],
[1, 0, -1],
[1, 0, -1]]).astype(float) / 3.0))
result[big_mask == False] = 0
return result
+34 -34
View File
@@ -8,11 +8,11 @@ class TestSobel():
"""Sobel on an array of all zeros"""
result = F.sobel(np.zeros((10, 10)), np.ones((10, 10), bool))
assert (np.all(result == 0))
def test_00_01_mask(self):
"""Sobel on a masked array should be zero"""
np.random.seed(0)
result = F.sobel(np.random.uniform(size=(10, 10)),
result = F.sobel(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
assert (np.all(result == 0))
@@ -25,10 +25,10 @@ class TestSobel():
i[np.abs(j) == 5] = 10000
assert (np.all(result[i == 0] == 1))
assert (np.all(result[np.abs(i) > 1] == 0))
def test_01_02_vertical(self):
"""Sobel on a vertical edge should be a vertical line"""
i,j = np.mgrid[-5:6, -5:6]
i, j = np.mgrid[-5:6, -5:6]
image = (j >= 0).astype(float)
result = F.sobel(image)
j[np.abs(i) == 5] = 10000
@@ -40,27 +40,27 @@ class TestHSobel():
"""Horizontal sobel on an array of all zeros"""
result = F.hsobel(np.zeros((10, 10)), np.ones((10, 10), bool))
assert (np.all(result == 0))
def test_00_01_mask(self):
"""Horizontal Sobel on a masked array should be zero"""
np.random.seed(0)
result = F.hsobel(np.random.uniform(size=(10, 10)),
result = F.hsobel(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
assert (np.all(result == 0))
def test_01_01_horizontal(self):
"""Horizontal Sobel on an edge should be a horizontal line"""
i,j = np.mgrid[-5:6, -5:6]
i, j = np.mgrid[-5:6, -5:6]
image = (i >= 0).astype(float)
result = F.hsobel(image)
# Fudge the eroded points
i[np.abs(j) == 5] = 10000
assert (np.all(result[i == 0] == 1))
assert (np.all(result[np.abs(i) > 1] == 0))
def test_01_02_vertical(self):
"""Horizontal Sobel on a vertical edge should be zero"""
i,j = np.mgrid[-5:6, -5:6]
i, j = np.mgrid[-5:6, -5:6]
image = (j >= 0).astype(float)
result = F.hsobel(image)
assert (np.all(result == 0))
@@ -70,27 +70,27 @@ class TestVSobel():
"""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))
def test_00_01_mask(self):
"""Vertical Sobel on a masked array should be zero"""
np.random.seed(0)
result = F.vsobel(np.random.uniform(size=(10, 10)),
result = F.vsobel(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
assert (np.all(result == 0))
def test_01_01_vertical(self):
"""Vertical Sobel on an edge should be a vertical line"""
i,j = np.mgrid[-5:6, -5:6]
i, j = np.mgrid[-5:6, -5:6]
image = (j >= 0).astype(float)
result = F.vsobel(image)
# Fudge the eroded points
j[np.abs(i) == 5] = 10000
assert (np.all(result[j == 0] == 1))
assert (np.all(result[np.abs(j) > 1] == 0))
def test_01_02_horizontal(self):
"""vertical Sobel on a horizontal edge should be zero"""
i,j = np.mgrid[-5:6, -5:6]
i, j = np.mgrid[-5:6, -5:6]
image = (i >= 0).astype(float)
result = F.vsobel(image)
eps = .000001
@@ -101,18 +101,18 @@ class TestPrewitt():
"""Prewitt on an array of all zeros"""
result = F.prewitt(np.zeros((10, 10)), np.ones((10, 10), bool))
assert (np.all(result == 0))
def test_00_01_mask(self):
"""Prewitt on a masked array should be zero"""
np.random.seed(0)
result = F.prewitt(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
result = F.prewitt(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
eps = .000001
assert (np.all(np.abs(result) < eps))
def test_01_01_horizontal(self):
"""Prewitt on an edge should be a horizontal line"""
i,j = np.mgrid[-5:6, -5:6]
i, j = np.mgrid[-5:6, -5:6]
image = (i >= 0).astype(float)
result = F.prewitt(image)
# Fudge the eroded points
@@ -120,10 +120,10 @@ class TestPrewitt():
eps = .000001
assert (np.all(result[i == 0] == 1))
assert (np.all(np.abs(result[np.abs(i) > 1]) < eps))
def test_01_02_vertical(self):
"""Prewitt on a vertical edge should be a vertical line"""
i,j = np.mgrid[-5:6, -5:6]
i, j = np.mgrid[-5:6, -5:6]
image = (j >= 0).astype(float)
result = F.prewitt(image)
eps = .000001
@@ -136,18 +136,18 @@ class TestHPrewitt():
"""Horizontal sobel on an array of all zeros"""
result = F.hprewitt(np.zeros((10, 10)), np.ones((10, 10), bool))
assert (np.all(result == 0))
def test_00_01_mask(self):
"""Horizontal prewitt on a masked array should be zero"""
np.random.seed(0)
result = F.hprewitt(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
result = F.hprewitt(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
eps = .000001
assert (np.all(np.abs(result) < eps))
def test_01_01_horizontal(self):
"""Horizontal prewitt on an edge should be a horizontal line"""
i,j = np.mgrid[-5:6, -5:6]
i, j = np.mgrid[-5:6, -5:6]
image = (i >= 0).astype(float)
result = F.hprewitt(image)
# Fudge the eroded points
@@ -155,10 +155,10 @@ class TestHPrewitt():
eps = .000001
assert (np.all(result[i == 0] == 1))
assert (np.all(np.abs(result[np.abs(i) > 1]) < eps))
def test_01_02_vertical(self):
"""Horizontal prewitt on a vertical edge should be zero"""
i,j = np.mgrid[-5:6, -5:6]
i, j = np.mgrid[-5:6, -5:6]
image = (j >= 0).astype(float)
result = F.hprewitt(image)
eps = .000001
@@ -169,17 +169,17 @@ class TestVPrewitt():
"""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))
def test_00_01_mask(self):
"""Vertical prewitt on a masked array should be zero"""
np.random.seed(0)
result = F.vprewitt(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
result = F.vprewitt(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
assert (np.all(result == 0))
def test_01_01_vertical(self):
"""Vertical prewitt on an edge should be a vertical line"""
i,j = np.mgrid[-5:6, -5:6]
i, j = np.mgrid[-5:6, -5:6]
image = (j >= 0).astype(float)
result = F.vprewitt(image)
# Fudge the eroded points
@@ -187,15 +187,15 @@ class TestVPrewitt():
assert (np.all(result[j == 0] == 1))
eps = .000001
assert (np.all(np.abs(result[np.abs(j) > 1]) < eps))
def test_01_02_horizontal(self):
"""Vertical prewitt on a horizontal edge should be zero"""
i,j = np.mgrid[-5:6, -5:6]
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))
if __name__ == "__main__":
run_module_suite()