Merge pull request #1240 from ahojnnes/edge-sign

Signed edge operators
This commit is contained in:
Steven Silvester
2014-11-28 09:14:24 -06:00
4 changed files with 349 additions and 79 deletions
+7 -2
View File
@@ -3,9 +3,14 @@ Remember to list any API changes below in `doc/source/api_changes.txt`.
Version 0.13
------------
* Remove deprecated `None` defaults for `skimage.exposure.rescale_intensity`
* Remove deprecated `skimage.filters.canny` import in filters/__init__.py file (canny is now in `skimage.feature.canny`).
* Don't forget to complete api_changes.txt. (`GitHub discuss <https://github.com/scikit-image/scikit-image/pull/1113>`__ )
* Remove deprecated `skimage.filters.canny` import in `filters/__init__.py`
file (canny is now in `skimage.feature.canny`).
* Don't forget to complete api_changes.txt.
(`GitHub discuss <https://github.com/scikit-image/scikit-image/pull/1113>`__ )
* Remove deprecated ``skimage.filter`` module.
* Remove deprecated edge filters `hsobel`, `vsobel`, `hscharr`, `vscharr`,
`hprewitt`, `vprewitt`, `roberts_positive_diagonal`,
`roberts_negative_diagonal` in `skimage/filters/edges.py`
Version 0.12
------------
+14 -3
View File
@@ -1,8 +1,11 @@
from .lpi_filter import inverse, wiener, LPIFilter2D
from ._gaussian import gaussian_filter
from .edges import (sobel, hsobel, vsobel, scharr, hscharr, vscharr, prewitt,
hprewitt, vprewitt, roberts, roberts_positive_diagonal,
roberts_negative_diagonal)
from .edges import (sobel, hsobel, vsobel, sobel_h, sobel_v,
scharr, hscharr, vscharr, scharr_h, scharr_v,
prewitt, hprewitt, vprewitt, prewitt_h, prewitt_v,
roberts, roberts_positive_diagonal,
roberts_negative_diagonal, roberts_pos_diag,
roberts_neg_diag)
from ._rank_order import rank_order
from ._gabor import gabor_kernel, gabor_filter
from .thresholding import (threshold_adaptive, threshold_otsu, threshold_yen,
@@ -34,15 +37,23 @@ __all__ = ['inverse',
'sobel',
'hsobel',
'vsobel',
'sobel_h',
'sobel_v',
'scharr',
'hscharr',
'vscharr',
'scharr_h',
'scharr_v',
'prewitt',
'hprewitt',
'vprewitt',
'prewitt_h',
'prewitt_v',
'roberts',
'roberts_positive_diagonal',
'roberts_negative_diagonal',
'roberts_pos_diag',
'roberts_neg_diag',
'denoise_tv_chambolle',
'denoise_bilateral',
'denoise_tv_bregman',
+296 -42
View File
@@ -11,7 +11,7 @@ Original author: Lee Kamentsky
"""
import numpy as np
from skimage import img_as_float
from skimage._shared.utils import assert_nD
from skimage._shared.utils import assert_nD, deprecated
from scipy.ndimage import convolve, binary_erosion, generate_binary_structure
@@ -82,12 +82,12 @@ def sobel(image, mask=None):
has to be further processed to perform edge detection.
"""
assert_nD(image, 2)
out = np.sqrt(hsobel(image, mask)**2 + vsobel(image, mask)**2)
out = np.sqrt(sobel_h(image, mask)**2 + sobel_v(image, mask)**2)
out /= np.sqrt(2)
return out
def hsobel(image, mask=None):
def sobel_h(image, mask=None):
"""Find the horizontal edges of an image using the Sobel transform.
Parameters
@@ -106,8 +106,7 @@ def hsobel(image, mask=None):
Notes
-----
We use the following kernel and return the absolute value of the
result at each point::
We use the following kernel::
1 2 1
0 0 0
@@ -116,10 +115,74 @@ def hsobel(image, mask=None):
"""
assert_nD(image, 2)
image = img_as_float(image)
result = np.abs(convolve(image, HSOBEL_WEIGHTS))
result = convolve(image, HSOBEL_WEIGHTS)
return _mask_filter_result(result, mask)
def sobel_v(image, mask=None):
"""Find the vertical edges of an image using the Sobel transform.
Parameters
----------
image : 2-D array
Image to process.
mask : 2-D array, 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 : 2-D array
The Sobel edge map.
Notes
-----
We use the following kernel::
1 0 -1
2 0 -2
1 0 -1
"""
assert_nD(image, 2)
image = img_as_float(image)
result = convolve(image, VSOBEL_WEIGHTS)
return _mask_filter_result(result, mask)
@deprecated("skimage.filters.sobel_h")
def hsobel(image, mask=None):
"""Find the horizontal edges of an image using the Sobel transform.
Parameters
----------
image : 2-D array
Image to process.
mask : 2-D array, 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 : 2-D array
The absolute 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
"""
return np.abs(sobel_h(image, mask))
@deprecated("skimage.filters.sobel_v")
def vsobel(image, mask=None):
"""Find the vertical edges of an image using the Sobel transform.
@@ -128,14 +191,14 @@ def vsobel(image, mask=None):
image : 2-D array
Image to process
mask : 2-D array, optional
An optional mask to limit the application to a certain area
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 : 2-D array
The Sobel edge map.
The absolute Sobel edge map.
Notes
-----
@@ -147,10 +210,7 @@ def vsobel(image, mask=None):
1 0 -1
"""
assert_nD(image, 2)
image = img_as_float(image)
result = np.abs(convolve(image, VSOBEL_WEIGHTS))
return _mask_filter_result(result, mask)
return np.abs(sobel_v(image, mask))
def scharr(image, mask=None):
@@ -182,12 +242,12 @@ def scharr(image, mask=None):
Optimization of Kernel Based Image Derivatives.
"""
out = np.sqrt(hscharr(image, mask)**2 + vscharr(image, mask)**2)
out = np.sqrt(scharr_h(image, mask)**2 + scharr_v(image, mask)**2)
out /= np.sqrt(2)
return out
def hscharr(image, mask=None):
def scharr_h(image, mask=None):
"""Find the horizontal edges of an image using the Scharr transform.
Parameters
@@ -206,8 +266,7 @@ def hscharr(image, mask=None):
Notes
-----
We use the following kernel and return the absolute value of the
result at each point::
We use the following kernel::
3 10 3
0 0 0
@@ -221,10 +280,84 @@ def hscharr(image, mask=None):
"""
assert_nD(image, 2)
image = img_as_float(image)
result = np.abs(convolve(image, HSCHARR_WEIGHTS))
result = convolve(image, HSCHARR_WEIGHTS)
return _mask_filter_result(result, mask)
def scharr_v(image, mask=None):
"""Find the vertical edges of an image using the Scharr transform.
Parameters
----------
image : 2-D array
Image to process
mask : 2-D array, 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 : 2-D array
The Scharr edge map.
Notes
-----
We use the following kernel::
3 0 -3
10 0 -10
3 0 -3
References
----------
.. [1] D. Kroon, 2009, Short Paper University Twente, Numerical
Optimization of Kernel Based Image Derivatives.
"""
assert_nD(image, 2)
image = img_as_float(image)
result = convolve(image, VSCHARR_WEIGHTS)
return _mask_filter_result(result, mask)
@deprecated("skimage.filters.scharr_h")
def hscharr(image, mask=None):
"""Find the horizontal edges of an image using the Scharr transform.
Parameters
----------
image : 2-D array
Image to process.
mask : 2-D array, 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 : 2-D array
The absolute 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
References
----------
.. [1] D. Kroon, 2009, Short Paper University Twente, Numerical
Optimization of Kernel Based Image Derivatives.
"""
return np.abs(scharr_h(image, mask))
@deprecated("skimage.filters.scharr_v")
def vscharr(image, mask=None):
"""Find the vertical edges of an image using the Scharr transform.
@@ -233,14 +366,14 @@ def vscharr(image, mask=None):
image : 2-D array
Image to process
mask : 2-D array, optional
An optional mask to limit the application to a certain area
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 : 2-D array
The Scharr edge map.
The absolute Scharr edge map.
Notes
-----
@@ -257,10 +390,7 @@ def vscharr(image, mask=None):
Optimization of Kernel Based Image Derivatives.
"""
assert_nD(image, 2)
image = img_as_float(image)
result = np.abs(convolve(image, VSCHARR_WEIGHTS))
return _mask_filter_result(result, mask)
return np.abs(scharr_v(image, mask))
def prewitt(image, mask=None):
@@ -286,12 +416,12 @@ def prewitt(image, mask=None):
and vertical Prewitt transforms.
"""
assert_nD(image, 2)
out = np.sqrt(hprewitt(image, mask)**2 + vprewitt(image, mask)**2)
out = np.sqrt(prewitt_h(image, mask)**2 + prewitt_v(image, mask)**2)
out /= np.sqrt(2)
return out
def hprewitt(image, mask=None):
def prewitt_h(image, mask=None):
"""Find the horizontal edges of an image using the Prewitt transform.
Parameters
@@ -310,8 +440,7 @@ def hprewitt(image, mask=None):
Notes
-----
We use the following kernel and return the absolute value of the
result at each point::
We use the following kernel::
1 1 1
0 0 0
@@ -320,11 +449,11 @@ def hprewitt(image, mask=None):
"""
assert_nD(image, 2)
image = img_as_float(image)
result = np.abs(convolve(image, HPREWITT_WEIGHTS))
result = convolve(image, HPREWITT_WEIGHTS)
return _mask_filter_result(result, mask)
def vprewitt(image, mask=None):
def prewitt_v(image, mask=None):
"""Find the vertical edges of an image using the Prewitt transform.
Parameters
@@ -343,8 +472,7 @@ def vprewitt(image, mask=None):
Notes
-----
We use the following kernel and return the absolute value of the
result at each point::
We use the following kernel::
1 0 -1
1 0 -1
@@ -353,10 +481,72 @@ def vprewitt(image, mask=None):
"""
assert_nD(image, 2)
image = img_as_float(image)
result = np.abs(convolve(image, VPREWITT_WEIGHTS))
result = convolve(image, VPREWITT_WEIGHTS)
return _mask_filter_result(result, mask)
@deprecated("skimage.filters.prewitt_h")
def hprewitt(image, mask=None):
"""Find the horizontal edges of an image using the Prewitt transform.
Parameters
----------
image : 2-D array
Image to process.
mask : 2-D array, 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 : 2-D array
The absolute 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
"""
return np.abs(prewitt_h(image, mask))
@deprecated("skimage.filters.prewitt_v")
def vprewitt(image, mask=None):
"""Find the vertical edges of an image using the Prewitt transform.
Parameters
----------
image : 2-D array
Image to process.
mask : 2-D array, 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 : 2-D array
The absolute 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
"""
return np.abs(prewitt_v(image, mask))
def roberts(image, mask=None):
"""Find the edge magnitude using Roberts' cross operator.
@@ -375,13 +565,13 @@ def roberts(image, mask=None):
The Roberts' Cross edge map.
"""
assert_nD(image, 2)
out = np.sqrt(roberts_positive_diagonal(image, mask)**2 +
roberts_negative_diagonal(image, mask)**2)
out = np.sqrt(roberts_pos_diag(image, mask)**2 +
roberts_neg_diag(image, mask)**2)
out /= np.sqrt(2)
return out
def roberts_positive_diagonal(image, mask=None):
def roberts_pos_diag(image, mask=None):
"""Find the cross edges of an image using Roberts' cross operator.
The kernel is applied to the input image to produce separate measurements
@@ -403,8 +593,7 @@ def roberts_positive_diagonal(image, mask=None):
Notes
-----
We use the following kernel and return the absolute value of the
result at each point::
We use the following kernel::
1 0
0 -1
@@ -412,11 +601,11 @@ def roberts_positive_diagonal(image, mask=None):
"""
assert_nD(image, 2)
image = img_as_float(image)
result = np.abs(convolve(image, ROBERTS_PD_WEIGHTS))
result = convolve(image, ROBERTS_PD_WEIGHTS)
return _mask_filter_result(result, mask)
def roberts_negative_diagonal(image, mask=None):
def roberts_neg_diag(image, mask=None):
"""Find the cross edges of an image using the Roberts' Cross operator.
The kernel is applied to the input image to produce separate measurements
@@ -438,8 +627,7 @@ def roberts_negative_diagonal(image, mask=None):
Notes
-----
We use the following kernel and return the absolute value of the
result at each point::
We use the following kernel::
0 1
-1 0
@@ -447,5 +635,71 @@ def roberts_negative_diagonal(image, mask=None):
"""
assert_nD(image, 2)
image = img_as_float(image)
result = np.abs(convolve(image, ROBERTS_ND_WEIGHTS))
result = convolve(image, ROBERTS_ND_WEIGHTS)
return _mask_filter_result(result, mask)
@deprecated("skimage.filters.roberts_pos_diag")
def roberts_positive_diagonal(image, mask=None):
"""Find the cross edges of an image using Roberts' cross operator.
The kernel is applied to the input image to produce separate measurements
of the gradient component one orientation.
Parameters
----------
image : 2-D array
Image to process.
mask : 2-D array, 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 : 2-D array
The absolute Robert's edge map.
Notes
-----
We use the following kernel and return the absolute value of the
result at each point::
1 0
0 -1
"""
return np.abs(roberts_pos_diag(image, mask))
@deprecated("skimage.filters.roberts_neg_diag")
def roberts_negative_diagonal(image, mask=None):
"""Find the cross edges of an image using the Roberts' Cross operator.
The kernel is applied to the input image to produce separate measurements
of the gradient component one orientation.
Parameters
----------
image : 2-D array
Image to process.
mask : 2-D array, 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 : 2-D array
The absolute Robert's edge map.
Notes
-----
We use the following kernel and return the absolute value of the
result at each point::
0 1
-1 0
"""
return np.abs(roberts_neg_diag(image, mask))
+32 -32
View File
@@ -69,15 +69,15 @@ def test_sobel_vertical():
def test_hsobel_zeros():
"""Horizontal sobel on an array of all zeros."""
result = filters.hsobel(np.zeros((10, 10)), np.ones((10, 10), bool))
result = filters.sobel_h(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)
result = filters.hsobel(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
result = filters.sobel_h(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
assert (np.all(result == 0))
@@ -85,7 +85,7 @@ def test_hsobel_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 = filters.hsobel(image)
result = filters.sobel_h(image)
# Fudge the eroded points
i[np.abs(j) == 5] = 10000
assert (np.all(result[i == 0] == 1))
@@ -96,21 +96,21 @@ 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) * np.sqrt(2)
result = filters.hsobel(image)
result = filters.sobel_h(image)
assert_allclose(result, 0, atol=1e-10)
def test_vsobel_zeros():
"""Vertical sobel on an array of all zeros."""
result = filters.vsobel(np.zeros((10, 10)), np.ones((10, 10), bool))
result = filters.sobel_v(np.zeros((10, 10)), np.ones((10, 10), bool))
assert_allclose(result, 0)
def test_vsobel_mask():
"""Vertical Sobel on a masked array should be zero."""
np.random.seed(0)
result = filters.vsobel(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
result = filters.sobel_v(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
assert_allclose(result, 0)
@@ -118,7 +118,7 @@ def test_vsobel_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 = filters.vsobel(image)
result = filters.sobel_v(image)
# Fudge the eroded points
j[np.abs(i) == 5] = 10000
assert (np.all(result[j == 0] == 1))
@@ -129,7 +129,7 @@ def test_vsobel_horizontal():
"""vertical Sobel on a horizontal edge should be zero."""
i, j = np.mgrid[-5:6, -5:6]
image = (i >= 0).astype(float)
result = filters.vsobel(image)
result = filters.sobel_v(image)
assert_allclose(result, 0)
@@ -170,15 +170,15 @@ def test_scharr_vertical():
def test_hscharr_zeros():
"""Horizontal Scharr on an array of all zeros."""
result = filters.hscharr(np.zeros((10, 10)), np.ones((10, 10), bool))
result = filters.scharr_h(np.zeros((10, 10)), np.ones((10, 10), bool))
assert_allclose(result, 0)
def test_hscharr_mask():
"""Horizontal Scharr on a masked array should be zero."""
np.random.seed(0)
result = filters.hscharr(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
result = filters.scharr_h(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
assert_allclose(result, 0)
@@ -186,7 +186,7 @@ def test_hscharr_horizontal():
"""Horizontal Scharr on an edge should be a horizontal line."""
i, j = np.mgrid[-5:6, -5:6]
image = (i >= 0).astype(float)
result = filters.hscharr(image)
result = filters.scharr_h(image)
# Fudge the eroded points
i[np.abs(j) == 5] = 10000
assert (np.all(result[i == 0] == 1))
@@ -197,21 +197,21 @@ def test_hscharr_vertical():
"""Horizontal Scharr on a vertical edge should be zero."""
i, j = np.mgrid[-5:6, -5:6]
image = (j >= 0).astype(float)
result = filters.hscharr(image)
result = filters.scharr_h(image)
assert_allclose(result, 0)
def test_vscharr_zeros():
"""Vertical Scharr on an array of all zeros."""
result = filters.vscharr(np.zeros((10, 10)), np.ones((10, 10), bool))
result = filters.scharr_v(np.zeros((10, 10)), np.ones((10, 10), bool))
assert_allclose(result, 0)
def test_vscharr_mask():
"""Vertical Scharr on a masked array should be zero."""
np.random.seed(0)
result = filters.vscharr(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
result = filters.scharr_v(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
assert_allclose(result, 0)
@@ -219,7 +219,7 @@ def test_vscharr_vertical():
"""Vertical Scharr on an edge should be a vertical line."""
i, j = np.mgrid[-5:6, -5:6]
image = (j >= 0).astype(float)
result = filters.vscharr(image)
result = filters.scharr_v(image)
# Fudge the eroded points
j[np.abs(i) == 5] = 10000
assert (np.all(result[j == 0] == 1))
@@ -230,7 +230,7 @@ def test_vscharr_horizontal():
"""vertical Scharr on a horizontal edge should be zero."""
i, j = np.mgrid[-5:6, -5:6]
image = (i >= 0).astype(float)
result = filters.vscharr(image)
result = filters.scharr_v(image)
assert_allclose(result, 0)
@@ -271,15 +271,15 @@ def test_prewitt_vertical():
def test_hprewitt_zeros():
"""Horizontal prewitt on an array of all zeros."""
result = filters.hprewitt(np.zeros((10, 10)), np.ones((10, 10), bool))
result = filters.prewitt_h(np.zeros((10, 10)), np.ones((10, 10), bool))
assert_allclose(result, 0)
def test_hprewitt_mask():
"""Horizontal prewitt on a masked array should be zero."""
np.random.seed(0)
result = filters.hprewitt(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
result = filters.prewitt_h(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
assert_allclose(result, 0)
@@ -287,7 +287,7 @@ def test_hprewitt_horizontal():
"""Horizontal prewitt on an edge should be a horizontal line."""
i, j = np.mgrid[-5:6, -5:6]
image = (i >= 0).astype(float)
result = filters.hprewitt(image)
result = filters.prewitt_h(image)
# Fudge the eroded points
i[np.abs(j) == 5] = 10000
assert (np.all(result[i == 0] == 1))
@@ -298,21 +298,21 @@ def test_hprewitt_vertical():
"""Horizontal prewitt on a vertical edge should be zero."""
i, j = np.mgrid[-5:6, -5:6]
image = (j >= 0).astype(float)
result = filters.hprewitt(image)
result = filters.prewitt_h(image)
assert_allclose(result, 0, atol=1e-10)
def test_vprewitt_zeros():
"""Vertical prewitt on an array of all zeros."""
result = filters.vprewitt(np.zeros((10, 10)), np.ones((10, 10), bool))
result = filters.prewitt_v(np.zeros((10, 10)), np.ones((10, 10), bool))
assert_allclose(result, 0)
def test_vprewitt_mask():
"""Vertical prewitt on a masked array should be zero."""
np.random.seed(0)
result = filters.vprewitt(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
result = filters.prewitt_v(np.random.uniform(size=(10, 10)),
np.zeros((10, 10), bool))
assert_allclose(result, 0)
@@ -320,7 +320,7 @@ def test_vprewitt_vertical():
"""Vertical prewitt on an edge should be a vertical line."""
i, j = np.mgrid[-5:6, -5:6]
image = (j >= 0).astype(float)
result = filters.vprewitt(image)
result = filters.prewitt_v(image)
# Fudge the eroded points
j[np.abs(i) == 5] = 10000
assert (np.all(result[j == 0] == 1))
@@ -331,7 +331,7 @@ def test_vprewitt_horizontal():
"""Vertical prewitt on a horizontal edge should be zero."""
i, j = np.mgrid[-5:6, -5:6]
image = (i >= 0).astype(float)
result = filters.vprewitt(image)
result = filters.prewitt_v(image)
assert_allclose(result, 0)
@@ -347,7 +347,7 @@ def test_horizontal_mask_line():
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 (filters.hprewitt, filters.hsobel, filters.hscharr):
for grad_func in (filters.prewitt_h, filters.sobel_h, filters.scharr_h):
result = grad_func(vgrad, mask)
yield assert_close, result, expected
@@ -364,7 +364,7 @@ def test_vertical_mask_line():
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 (filters.vprewitt, filters.vsobel, filters.vscharr):
for grad_func in (filters.prewitt_v, filters.sobel_v, filters.scharr_v):
result = grad_func(hgrad, mask)
yield assert_close, result, expected