From 29c657e344b87634a2819caf42cbcf53b8ff5aca Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Sun, 23 Aug 2009 12:42:31 -0700 Subject: [PATCH] Add Hough transform. --- scikits/image/transform/__init__.py | 1 + scikits/image/transform/hough_transform.py | 95 +++++++++++++++++++ .../transform/tests/test_hough_transform.py | 18 ++++ 3 files changed, 114 insertions(+) create mode 100644 scikits/image/transform/__init__.py create mode 100644 scikits/image/transform/hough_transform.py create mode 100644 scikits/image/transform/tests/test_hough_transform.py diff --git a/scikits/image/transform/__init__.py b/scikits/image/transform/__init__.py new file mode 100644 index 00000000..4cf1ac42 --- /dev/null +++ b/scikits/image/transform/__init__.py @@ -0,0 +1 @@ +from hough_transform import * diff --git a/scikits/image/transform/hough_transform.py b/scikits/image/transform/hough_transform.py new file mode 100644 index 00000000..c2e880a8 --- /dev/null +++ b/scikits/image/transform/hough_transform.py @@ -0,0 +1,95 @@ +## Copyright (C) 2006 Stefan van der Walt +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## +## THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +## IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +## DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +## INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +## (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +## STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +## IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +## POSSIBILITY OF SUCH DAMAGE. + +__all__ = ['hough'] + +import numpy as np + +itype = np.uint16 # See ticket 225 + +def hough(img, angles=None): + """Perform a straight line Hough transform. + + Parameters + ---------- + img : (M, N) bool ndarray + Thresholded input image. + angles : ndarray or list + Angles at which to compute the transform. + + Returns + ------- + H : 2-D ndarray + Hough transform coefficients. + distances : ndarray + Distance values. + angles : ndarray + Angle values. + + Examples + -------- + # Generate a test image + img = np.zeros((100, 150), dtype=bool) + img[30, :] = 1 + img[:, 65] = 1 + img[35:45, 35:50] = 1 + for i in range(90): + img[i, i] = 1 + img += np.random.random(img.shape) > 0.95 + + out, angles, d = houghtf(img) + + import matplotlib.pyplot as plt + plt.imshow(out, cmap=plt.cm.bone) + plt.xlabel('Angle (degree)') + plt.ylabel('Distance %d (pixel)' % d[0]) + plt.show() + """ + if img.ndim != 2: + raise ValueError("Input must be a two-dimensional array") + + img = img.astype(bool) + + if not angles: + angles = np.linspace(-90,90,180) + + theta = angles / 180. * np.pi + d = np.ceil(np.hypot(*img.shape)) + nr_bins = 2*d - 1 + bins = np.linspace(-d, d, nr_bins) + out = np.zeros((nr_bins, len(theta)), dtype=itype) + + rows, cols = img.shape + x,y = np.mgrid[:rows, :cols] + + for i, (cT, sT) in enumerate(zip(np.cos(theta), np.sin(theta))): + rho = np.round_(cT * x[img] + sT * y[img]) - bins[0] + 1 + rho = rho.astype(itype) + rho[(rho < 0) | (rho > nr_bins)] = 0 + bc = np.bincount(rho.flat)[1:] + out[:len(bc), i] = bc + + return out, angles, bins + diff --git a/scikits/image/transform/tests/test_hough_transform.py b/scikits/image/transform/tests/test_hough_transform.py new file mode 100644 index 00000000..3bc1e6c9 --- /dev/null +++ b/scikits/image/transform/tests/test_hough_transform.py @@ -0,0 +1,18 @@ +import numpy as np +from numpy.testing import * + +from scikits.image.transform import * + +def test_hough(): + # Generate a test image + img = np.zeros((100, 150), dtype=bool) + img[30, :] = 1 + img[:, 65] = 1 + img[35:45, 35:50] = 1 + for i in range(90): + img[i, i] = 1 + + out, angles, d = hough(img) + + assert_equal(out.max(), 100) + assert_equal(len(angles), 180)