Added quantile_threshold option to canny edge detection

This allows you to specify the high and low thresholds as quantiles of the edge magnitude
image, rather than as absolute edge magnitude values
This commit is contained in:
Robin Wilson
2015-08-28 22:30:42 +01:00
parent 13b2170dfd
commit b29ad8ef6d
2 changed files with 40 additions and 1 deletions
+13 -1
View File
@@ -50,7 +50,8 @@ def smooth_with_function_and_mask(image, function, mask):
return output_image
def canny(image, sigma=1., low_threshold=None, high_threshold=None, mask=None):
def canny(image, sigma=1., low_threshold=None, high_threshold=None, mask=None,
quantile_threshold=False):
"""Edge filter an image using the Canny algorithm.
Parameters
@@ -67,6 +68,9 @@ def canny(image, sigma=1., low_threshold=None, high_threshold=None, mask=None):
If None, high_threshold is set to 20% of dtype's max.
mask : array, dtype=bool, optional
Mask to limit the application of Canny to a certain area.
quantile_threshold : bool, optional
If True then treat low_threshold and high_threshold as quantiles of the
edge magnitude image, rather than absolute edge magnitude values.
Returns
-------
@@ -246,6 +250,14 @@ def canny(image, sigma=1., low_threshold=None, high_threshold=None, mask=None):
c2 = magnitude[1:, :-1][pts[:-1, 1:]]
c_minus = c2 * w + c1 * (1 - w) <= m
local_maxima[pts] = c_plus & c_minus
#
#---- If quantile_threshold is set then calculate the thresholds to use
#
if quantile_threshold:
high_threshold = np.percentile(magnitude, 100.0 * high_threshold)
low_threshold = np.percentile(magnitude, 100.0 * low_threshold)
#
#---- Create two masks at the two thresholds.
#
+27
View File
@@ -1,7 +1,10 @@
import unittest
import numpy as np
from numpy.testing import assert_equal
from scipy.ndimage import binary_dilation, binary_erosion
import skimage.feature as F
from skimage import filters, data
from skimage import img_as_float
class TestCanny(unittest.TestCase):
@@ -66,3 +69,27 @@ class TestCanny(unittest.TestCase):
result1 = F.canny(np.zeros((20, 20)), 4, 0, 0, np.ones((20, 20), bool))
result2 = F.canny(np.zeros((20, 20)), 4, 0, 0)
self.assertTrue(np.all(result1 == result2))
def test_quantile_threshold():
image = img_as_float(data.camera()[::50,::50])
# Correct output produced manually with quantiles
# of 0.8 and 0.6 for high and low respectively
correct_output = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=bool)
result = F.canny(image, low_threshold=0.6, high_threshold=0.8, quantile_threshold=True)
assert_equal(result, correct_output)