Add scharr edge filter

This commit is contained in:
Johannes Schönberger
2012-10-12 19:10:46 +02:00
parent 635e75bb7d
commit f22a014ffa
3 changed files with 228 additions and 9 deletions
+2 -1
View File
@@ -1,7 +1,8 @@
from .lpi_filter import *
from .ctmf import median_filter
from ._canny import canny
from .edges import sobel, hsobel, vsobel, hprewitt, vprewitt, prewitt
from .edges import (sobel, hsobel, vsobel, scharr, hscharr, vscharr, prewitt,
hprewitt, vprewitt)
from ._tv_denoise import tv_denoise
from ._rank_order import rank_order
from .thresholding import threshold_otsu, threshold_adaptive
+106 -8
View File
@@ -1,6 +1,7 @@
"""edges.py - Sobel edge filter
"""edges.py - Edge filters
Originally part of CellProfiler, code licensed under both GPL and BSD licenses.
Sobel and Prewitt filters originally part of CellProfiler, code licensed under
both GPL and BSD licenses.
Website: http://www.cellprofiler.org
Copyright (c) 2003-2009 Massachusetts Institute of Technology
Copyright (c) 2009-2011 Broad Institute
@@ -48,7 +49,7 @@ def sobel(image, mask=None):
Returns
-------
output : ndarray
The Sobel edge map.
The Sobel edge map.
Notes
-----
@@ -77,7 +78,7 @@ def hsobel(image, mask=None):
Returns
-------
output : ndarray
The Sobel edge map.
The Sobel edge map.
Notes
-----
@@ -112,7 +113,7 @@ def vsobel(image, mask=None):
Returns
-------
output : ndarray
The Sobel edge map.
The Sobel edge map.
Notes
-----
@@ -132,6 +133,103 @@ def vsobel(image, mask=None):
return _mask_filter_result(result, mask)
def scharr(image, mask=None):
"""Calculate the absolute magnitude Scharr to find edges.
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.
Note that pixels surrounding masked regions are also masked to
prevent masked regions from affecting the result.
Returns
-------
output : ndarray
The Scharr edge map.
Notes
-----
Take the square root of the sum of the squares of the horizontal and
vertical Scharrs to get a magnitude that's somewhat insensitive to
direction.
"""
return np.sqrt(hscharr(image, mask)**2 + vscharr(image, mask)**2)
def hscharr(image, mask=None):
"""Find the horizontal edges of an image using the Scharr 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.
Note that pixels surrounding masked regions are also masked to
prevent masked regions from affecting the result.
Returns
-------
output : ndarray
The Scharr edge map.
Notes
-----
We use the following kernel and return the absolute value of the
result at each point::
3 10 3
0 0 0
-3 -10 -3
"""
image = img_as_float(image)
result = np.abs(convolve(image,
np.array([[ 3, 10, 3],
[ 0, 0, 0],
[-3, -10, -3]]).astype(float) / 16.0))
return _mask_filter_result(result, mask)
def vscharr(image, mask=None):
"""Find the vertical edges of an image using the Scharr 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
Note that pixels surrounding masked regions are also masked to
prevent masked regions from affecting the result.
Returns
-------
output : ndarray
The Scharr edge map.
Notes
-----
We use the following kernel and return the absolute value of the
result at each point::
3 0 -3
10 0 -10
3 0 -3
"""
image = img_as_float(image)
result = np.abs(convolve(image,
np.array([[ 3, 0, -3],
[10, 0, -10],
[ 3, 0, -3]]).astype(float) / 16.0))
return _mask_filter_result(result, mask)
def prewitt(image, mask=None):
"""Find the edge magnitude using the Prewitt transform.
@@ -147,7 +245,7 @@ def prewitt(image, mask=None):
Returns
-------
output : ndarray
The Prewitt edge map.
The Prewitt edge map.
Notes
-----
@@ -172,7 +270,7 @@ def hprewitt(image, mask=None):
Returns
-------
output : ndarray
The Prewitt edge map.
The Prewitt edge map.
Notes
-----
@@ -207,7 +305,7 @@ def vprewitt(image, mask=None):
Returns
-------
output : ndarray
The Prewitt edge map.
The Prewitt edge map.
Notes
-----
+120
View File
@@ -9,6 +9,7 @@ def test_sobel_zeros():
result = F.sobel(np.zeros((10, 10)), np.ones((10, 10), bool))
assert (np.all(result == 0))
def test_sobel_mask():
"""Sobel on a masked array should be zero"""
np.random.seed(0)
@@ -16,6 +17,7 @@ def test_sobel_mask():
np.zeros((10, 10), bool))
assert (np.all(result == 0))
def test_sobel_horizontal():
"""Sobel on an edge should be a horizontal line"""
i, j = np.mgrid[-5:6, -5:6]
@@ -26,6 +28,7 @@ def test_sobel_horizontal():
assert (np.all(result[i == 0] == 1))
assert (np.all(result[np.abs(i) > 1] == 0))
def test_sobel_vertical():
"""Sobel on a vertical edge should be a vertical line"""
i, j = np.mgrid[-5:6, -5:6]
@@ -41,6 +44,7 @@ def test_hsobel_zeros():
result = F.hsobel(np.zeros((10, 10)), np.ones((10, 10), bool))
assert (np.all(result == 0))
def test_hsobel_mask():
"""Horizontal Sobel on a masked array should be zero"""
np.random.seed(0)
@@ -48,6 +52,7 @@ def test_hsobel_mask():
np.zeros((10, 10), bool))
assert (np.all(result == 0))
def test_hsobel_horizontal():
"""Horizontal Sobel on an edge should be a horizontal line"""
i, j = np.mgrid[-5:6, -5:6]
@@ -58,6 +63,7 @@ def test_hsobel_horizontal():
assert (np.all(result[i == 0] == 1))
assert (np.all(result[np.abs(i) > 1] == 0))
def test_hsobel_vertical():
"""Horizontal Sobel on a vertical edge should be zero"""
i, j = np.mgrid[-5:6, -5:6]
@@ -71,6 +77,7 @@ def test_vsobel_zeros():
result = F.vsobel(np.zeros((10, 10)), np.ones((10, 10), bool))
assert (np.all(result == 0))
def test_vsobel_mask():
"""Vertical Sobel on a masked array should be zero"""
np.random.seed(0)
@@ -78,6 +85,7 @@ def test_vsobel_mask():
np.zeros((10, 10), bool))
assert (np.all(result == 0))
def test_vsobel_vertical():
"""Vertical Sobel on an edge should be a vertical line"""
i, j = np.mgrid[-5:6, -5:6]
@@ -88,6 +96,7 @@ def test_vsobel_vertical():
assert (np.all(result[j == 0] == 1))
assert (np.all(result[np.abs(j) > 1] == 0))
def test_vsobel_horizontal():
"""vertical Sobel on a horizontal edge should be zero"""
i, j = np.mgrid[-5:6, -5:6]
@@ -97,11 +106,114 @@ def test_vsobel_horizontal():
assert (np.all(np.abs(result) < eps))
def test_scharr_zeros():
"""Sobel on an array of all zeros"""
result = F.scharr(np.zeros((10, 10)), np.ones((10, 10), bool))
assert (np.all(result == 0))
def test_scharr_mask():
"""Sobel 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))
def test_scharr_horizontal():
"""Sobel 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)
# 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_scharr_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.scharr(image)
j[np.abs(i) == 5] = 10000
assert (np.all(result[j == 0] == 1))
assert (np.all(result[np.abs(j) > 1] == 0))
def test_hscharr_zeros():
"""Horizontal sobel on an array of all zeros"""
result = F.hscharr(np.zeros((10, 10)), np.ones((10, 10), bool))
assert (np.all(result == 0))
def test_hscharr_mask():
"""Horizontal Sobel 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))
def test_hscharr_horizontal():
"""Horizontal Sobel on an edge should be a horizontal line"""
i, j = np.mgrid[-5:6, -5:6]
image = (i >= 0).astype(float)
result = F.hscharr(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_hscharr_vertical():
"""Horizontal Sobel on a vertical edge should be zero"""
i, j = np.mgrid[-5:6, -5:6]
image = (j >= 0).astype(float)
result = F.hscharr(image)
assert (np.all(result == 0))
def test_vscharr_zeros():
"""Vertical sobel on an array of all zeros"""
result = F.vscharr(np.zeros((10, 10)), np.ones((10, 10), bool))
assert (np.all(result == 0))
def test_vscharr_mask():
"""Vertical Sobel 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))
def test_vscharr_vertical():
"""Vertical Sobel on an edge should be a vertical line"""
i, j = np.mgrid[-5:6, -5:6]
image = (j >= 0).astype(float)
result = F.vscharr(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_vscharr_horizontal():
"""vertical Sobel on a horizontal edge should be zero"""
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))
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))
def test_prewitt_mask():
"""Prewitt on a masked array should be zero"""
np.random.seed(0)
@@ -110,6 +222,7 @@ def test_prewitt_mask():
eps = .000001
assert (np.all(np.abs(result) < eps))
def test_prewitt_horizontal():
"""Prewitt on an edge should be a horizontal line"""
i, j = np.mgrid[-5:6, -5:6]
@@ -121,6 +234,7 @@ def test_prewitt_horizontal():
assert (np.all(result[i == 0] == 1))
assert (np.all(np.abs(result[np.abs(i) > 1]) < eps))
def test_prewitt_vertical():
"""Prewitt on a vertical edge should be a vertical line"""
i, j = np.mgrid[-5:6, -5:6]
@@ -137,6 +251,7 @@ def test_hprewitt_zeros():
result = F.hprewitt(np.zeros((10, 10)), np.ones((10, 10), bool))
assert (np.all(result == 0))
def test_hprewitt_mask():
"""Horizontal prewitt on a masked array should be zero"""
np.random.seed(0)
@@ -145,6 +260,7 @@ def test_hprewitt_mask():
eps = .000001
assert (np.all(np.abs(result) < eps))
def test_hprewitt_horizontal():
"""Horizontal prewitt on an edge should be a horizontal line"""
i, j = np.mgrid[-5:6, -5:6]
@@ -156,6 +272,7 @@ def test_hprewitt_horizontal():
assert (np.all(result[i == 0] == 1))
assert (np.all(np.abs(result[np.abs(i) > 1]) < eps))
def test_hprewitt_vertical():
"""Horizontal prewitt on a vertical edge should be zero"""
i, j = np.mgrid[-5:6, -5:6]
@@ -170,6 +287,7 @@ def test_vprewitt_zeros():
result = F.vprewitt(np.zeros((10, 10)), np.ones((10, 10), bool))
assert (np.all(result == 0))
def test_vprewitt_mask():
"""Vertical prewitt on a masked array should be zero"""
np.random.seed(0)
@@ -177,6 +295,7 @@ def test_vprewitt_mask():
np.zeros((10, 10), bool))
assert (np.all(result == 0))
def test_vprewitt_vertical():
"""Vertical prewitt on an edge should be a vertical line"""
i, j = np.mgrid[-5:6, -5:6]
@@ -188,6 +307,7 @@ def test_vprewitt_vertical():
eps = .000001
assert (np.all(np.abs(result[np.abs(j) > 1]) < eps))
def test_vprewitt_horizontal():
"""Vertical prewitt on a horizontal edge should be zero"""
i, j = np.mgrid[-5:6, -5:6]