mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-30 20:54:26 +08:00
Add scharr edge filter
This commit is contained in:
@@ -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
@@ -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
|
||||
-----
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user