From debd4d54d6d81e491f3ca712b8da4d5a721c5d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Boulogne?= Date: Tue, 6 Aug 2013 16:03:42 +0200 Subject: [PATCH] ENH: use heapq to select the best match --- ...lot_circular_elliptical_hough_transform.py | 15 ++++---- skimage/transform/_hough_transform.pyx | 10 ++++-- .../transform/tests/test_hough_transform.py | 34 +++++++++++-------- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/doc/examples/plot_circular_elliptical_hough_transform.py b/doc/examples/plot_circular_elliptical_hough_transform.py index ca30b136..d500be79 100755 --- a/doc/examples/plot_circular_elliptical_hough_transform.py +++ b/doc/examples/plot_circular_elliptical_hough_transform.py @@ -119,14 +119,15 @@ edges = filter.canny(image_gray, sigma=2.0, # The accuracy corresponds to the bin size of a major axis. # The value is chosen in order to get a single high accumulator. # The threshold eliminates low accumulators -accum = hough_ellipse(edges, accuracy=10, threshold=170, min_size=50) -accum.sort(key=lambda x:x[5]) +accum = hough_ellipse(edges, accuracy=10, threshold=150, min_size=50) +# Select the highest accumulator +best = heapq.nlargest(1, accum)[0] # Estimated parameters for the ellipse -center_y = int(accum[-1][1]) -center_x = int(accum[-1][2]) -xradius = int(accum[-1][3]) -yradius = int(accum[-1][4]) -angle = np.pi - accum[-1][5] +center_y = int(best[1]) +center_x = int(best[2]) +xradius = int(best[3]) +yradius = int(best[4]) +angle = np.pi - best[5] # Draw the ellipse on the original image cx, cy = ellipse_perimeter(center_y, center_x, diff --git a/skimage/transform/_hough_transform.pyx b/skimage/transform/_hough_transform.pyx index 577313a1..958bacc4 100644 --- a/skimage/transform/_hough_transform.pyx +++ b/skimage/transform/_hough_transform.pyx @@ -3,6 +3,7 @@ #cython: nonecheck=False #cython: wraparound=False import numpy as np +import heapq cimport numpy as cnp cimport cython @@ -131,8 +132,12 @@ def hough_ellipse(cnp.ndarray img, int threshold=4, double accuracy=1, >>> img = np.zeros((25, 25), dtype=int) >>> rr, cc = draw.ellipse_perimeter(10, 10, 6, 8) >>> img[cc, rr] = 1 - >>> result = hough_ellipse(img, threshold=8) + >>> result = hough_ellipse(img, threshold=4) + >>> # extract the highest accumulator + >>> heapq.nlargest(1, result) [(10, 10.0, 10.0, 8.0, 6.0, 0.0)] + >>> # To sort them all + >>> results = [heappop(results) for i in range(len(results))] Notes ----- @@ -217,7 +222,8 @@ def hough_ellipse(cnp.ndarray img, int threshold=4, double accuracy=1, elif angle < - np.pi: angle = angle + np.pi / 2. b = sqrt(bin_edges[hist.argmax()]) - results.append((hist_max, # Accumulator + heapq.heappush(results, + (hist_max, # Accumulator x0, y0, a, diff --git a/skimage/transform/tests/test_hough_transform.py b/skimage/transform/tests/test_hough_transform.py index 6c6acb96..57d14278 100644 --- a/skimage/transform/tests/test_hough_transform.py +++ b/skimage/transform/tests/test_hough_transform.py @@ -1,4 +1,5 @@ import numpy as np +import heapq from numpy.testing import (assert_almost_equal, assert_equal, ) @@ -157,11 +158,12 @@ def test_hough_ellipse_zero_angle(): rr, cc = ellipse_perimeter(y0, x0, b, a) img[rr, cc] = 1 result = tf.hough_ellipse(img, threshold=9) - assert_equal(result[0][1], x0) - assert_equal(result[0][2], y0) - assert_almost_equal(result[0][3], b, decimal=1) - assert_almost_equal(result[0][4], a, decimal=1) - assert_equal(result[0][5], angle) + best = heapq.nlargest(1, result)[0] + assert_equal(best[1], x0) + assert_equal(best[2], y0) + assert_almost_equal(best[3], b, decimal=1) + assert_almost_equal(best[4], a, decimal=1) + assert_equal(best[5], angle) def test_hough_ellipse_non_zero_angle(): @@ -174,11 +176,12 @@ def test_hough_ellipse_non_zero_angle(): rr, cc = ellipse_perimeter(y0, x0, b, a, orientation=angle) img[rr, cc] = 1 result = tf.hough_ellipse(img, threshold=15, accuracy=3) - assert_almost_equal(result[0][1] / 100., x0 / 100., decimal=1) - assert_almost_equal(result[0][2] / 100., y0 / 100., decimal=1) - assert_almost_equal(result[0][3] / 10., b / 10., decimal=1) - assert_almost_equal(result[0][4] / 100., a / 100., decimal=1) - assert_almost_equal(result[0][5], angle, decimal=1) + best = heapq.nlargest(1, result)[0] + assert_almost_equal(best[1] / 100., x0 / 100., decimal=1) + assert_almost_equal(best[2] / 100., y0 / 100., decimal=1) + assert_almost_equal(best[3] / 10., b / 10., decimal=1) + assert_almost_equal(best[4] / 100., a / 100., decimal=1) + assert_almost_equal(best[5], angle, decimal=1) def test_hough_ellipse_non_zero_angle2(): @@ -191,11 +194,12 @@ def test_hough_ellipse_non_zero_angle2(): rr, cc = ellipse_perimeter(y0, x0, b, a, orientation=angle) img[rr, cc] = 1 result = tf.hough_ellipse(img, threshold=15, accuracy=3) - assert_almost_equal(result[0][1] / 100., x0 / 100., decimal=1) - assert_almost_equal(result[0][2] / 100., y0 / 100., decimal=1) - assert_almost_equal(result[0][3] / 100., a / 100., decimal=1) - assert_almost_equal(result[0][3] / 100., b / 100., decimal=1) - assert_almost_equal(result[0][5], angle, decimal=1) + best = heapq.nlargest(1, result)[0] + assert_almost_equal(best[1] / 100., x0 / 100., decimal=1) + assert_almost_equal(best[2] / 100., y0 / 100., decimal=1) + assert_almost_equal(best[3] / 100., a / 100., decimal=1) + assert_almost_equal(best[3] / 100., b / 100., decimal=1) + assert_almost_equal(best[5], angle, decimal=1) if __name__ == "__main__":