big clean-up!

This commit is contained in:
François Boulogne
2013-03-24 15:11:55 +01:00
parent caee53c83c
commit a68434b330
4 changed files with 90 additions and 171 deletions
+3
View File
@@ -1,3 +1,6 @@
from ._hough_transform import hough_circle,
hough_line,
probabilistic_hough_line
from .hough_transform import *
from .radon_transform import *
from .finite_radon_transform import *
+74 -3
View File
@@ -20,7 +20,7 @@ cdef inline Py_ssize_t round(double r):
return <Py_ssize_t>((r + 0.5) if (r > 0.0) else (r - 0.5))
def _hough_circle(cnp.ndarray img,
def hough_circle(cnp.ndarray img,
cnp.ndarray[ndim=1, dtype=cnp.intp_t] radius,
char normalize=True):
"""Perform a circular Hough transform.
@@ -88,8 +88,51 @@ def _hough_circle(cnp.ndarray img,
return acc
def _hough(cnp.ndarray img, cnp.ndarray[ndim=1, dtype=cnp.double_t] theta=None):
def hough_line(cnp.ndarray img, cnp.ndarray[ndim=1, dtype=cnp.double_t] theta=None):
"""Perform a straight line Hough transform.
Parameters
----------
img : (M, N) ndarray
Input image with nonzero values representing edges.
theta : 1D ndarray of double
Angles at which to compute the transform, in radians.
Defaults to -pi/2 .. pi/2
Returns
-------
H : 2-D ndarray of uint64
Hough transform accumulator.
theta : ndarray
Angles at which the transform was computed, in radians.
distances : ndarray
Distance values.
Notes
-----
The origin is the top left corner of the original image.
X and Y axis are horizontal and vertical edges respectively.
The distance is the minimal algebraic distance from the origin to the detected line.
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
Apply the Hough transform:
>>> out, angles, d = hough_line(img)
.. plot:: hough_tf.py
"""
if img.ndim != 2:
raise ValueError('The input image must be 2D.')
@@ -131,10 +174,38 @@ def _hough(cnp.ndarray img, cnp.ndarray[ndim=1, dtype=cnp.double_t] theta=None):
return accum, theta, bins
def _probabilistic_hough(cnp.ndarray img, int value_threshold,
def probabilistic_hough_line(cnp.ndarray img, int value_threshold,
int line_length, int line_gap,
cnp.ndarray[ndim=1, dtype=cnp.double_t] theta=None):
"""Return lines from a progressive probabilistic line Hough transform.
Parameters
----------
img : (M, N) ndarray
Input image with nonzero values representing edges.
threshold : int
Threshold
line_length : int, optional (default 50)
Minimum accepted length of detected lines.
Increase the parameter to extract longer lines.
line_gap : int, optional, (default 10)
Maximum gap between pixels to still form a line.
Increase the parameter to merge broken lines more aggresively.
theta : 1D ndarray, dtype=double, optional, default (-pi/2 .. pi/2)
Angles at which to compute the transform, in radians.
Returns
-------
lines : list
List of lines identified, lines in format ((x0, y0), (x1, y0)), indicating
line start and end.
References
----------
.. [1] C. Galamhos, J. Matas and J. Kittler, "Progressive probabilistic
Hough transform for line detection", in IEEE Computer Society
Conference on Computer Vision and Pattern Recognition, 1999.
"""
if img.ndim != 2:
raise ValueError('The input image must be 2D.')
+13 -159
View File
@@ -1,179 +1,32 @@
__all__ = ['hough', 'hough_line', 'hough_circle', 'hough_peaks', 'probabilistic_hough']
__all__ = ['hough_peaks']
from itertools import izip as zip
import numpy as np
from scipy import ndimage
from ._hough_transform import _probabilistic_hough
from skimage import measure, morphology
def _hough(img, theta=None):
if img.ndim != 2:
raise ValueError('The input image must be 2-D')
if theta is None:
theta = np.linspace(-np.pi / 2, np.pi / 2, 180)
# compute the vertical bins (the distances)
d = np.ceil(np.hypot(*img.shape))
nr_bins = 2 * d
bins = np.linspace(-d, d, nr_bins)
# allocate the output image
out = np.zeros((nr_bins, len(theta)), dtype=np.uint64)
# precompute the sin and cos of the angles
cos_theta = np.cos(theta)
sin_theta = np.sin(theta)
# find the indices of the non-zero values in
# the input image
y, x = np.nonzero(img)
# x and y can be large, so we can't just broadcast to 2D
# arrays as we may run out of memory. Instead we process
# one vertical slice at a time.
for i, (cT, sT) in enumerate(zip(cos_theta, sin_theta)):
# compute the base distances
distances = x * cT + y * sT
# round the distances to the nearest integer
# and shift them to a nonzero bin
shifted = np.round(distances) - bins[0]
# cast the shifted values to ints to use as indices
indices = shifted.astype(np.int)
# use bin count to accumulate the coefficients
bincount = np.bincount(indices)
# finally assign the proper values to the out array
out[:len(bincount), i] = bincount
return out, theta, bins
_py_hough = _hough
# try to import and use the faster Cython version if it exists
try:
from ._hough_transform import _hough
except ImportError:
pass
def probabilistic_hough(img, threshold=10, line_length=50, line_gap=10,
theta=None):
"""Return lines from a progressive probabilistic line Hough transform.
Parameters
----------
img : (M, N) ndarray
Input image with nonzero values representing edges.
threshold : int
Threshold
line_length : int, optional (default 50)
Minimum accepted length of detected lines.
Increase the parameter to extract longer lines.
line_gap : int, optional, (default 10)
Maximum gap between pixels to still form a line.
Increase the parameter to merge broken lines more aggresively.
theta : 1D ndarray, dtype=double, optional, default (-pi/2 .. pi/2)
Angles at which to compute the transform, in radians.
Returns
-------
lines : list
List of lines identified, lines in format ((x0, y0), (x1, y0)), indicating
line start and end.
References
----------
.. [1] C. Galamhos, J. Matas and J. Kittler, "Progressive probabilistic
Hough transform for line detection", in IEEE Computer Society
Conference on Computer Vision and Pattern Recognition, 1999.
"""
return _probabilistic_hough(img, threshold, line_length, line_gap, theta)
from ._hough_transform import hough_line, probabilistic_hough_line
from skimage._shared.utils import deprecated
@deprecated('hough_line')
def hough(img, theta=None):
return hough_line(img, theta)
from ._hough_transform import _hough_circle
def hough_line(img, theta=None):
"""Perform a straight line Hough transform.
Parameters
----------
img : (M, N) ndarray
Input image with nonzero values representing edges.
theta : 1D ndarray of double
Angles at which to compute the transform, in radians.
Defaults to -pi/2 .. pi/2
Returns
-------
H : 2-D ndarray of uint64
Hough transform accumulator.
theta : ndarray
Angles at which the transform was computed, in radians.
distances : ndarray
Distance values.
Notes
-----
The origin is the top left corner of the original image.
X and Y axis are horizontal and vertical edges respectively.
The distance is the minimal algebraic distance from the origin to the detected line.
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
Apply the Hough transform:
>>> out, angles, d = hough_line(img)
.. plot:: hough_tf.py
"""
return _hough(img, theta)
def hough_circle(img, radius, normalize=True):
"""Perform a circular Hough transform.
Parameters
----------
img : (M, N) ndarray
Input image with nonzero values representing edges.
radius : ndarray
Radii at which to compute the Hough transform.
normalize : boolean, optional
Normalize the accumulator with the number
of pixels used to draw the radius
Returns
-------
H : 3D ndarray (radius index, (M, N) ndarray)
Hough transform accumulator for each radius
"""
return _hough_circle(img, radius.astype(np.intp), normalize)
@deprecated('probabilistic_hough')
def probabilistic_hough(img, threshold=10, line_length=50, line_gap=10,
theta=None):
return probabilistic_hough_line(img, threshold, line_length, line_gap, theta)
@deprecated('hough_peaks')
def hough_peaks(hspace, angles, dists, min_distance=10, min_angle=10,
threshold=None, num_peaks=np.inf):
return hough_line_peaks(hspace, angles, dists, min_distance, min_angle,
threshold, num_peaks)
def hough_line_peaks(hspace, angles, dists, min_distance=10, min_angle=10,
threshold=None, num_peaks=np.inf):
"""Return peaks in hough transform.
Identifies most prominent lines separated by a certain angle and distance in
@@ -187,6 +40,7 @@ def hough_peaks(hspace, angles, dists, min_distance=10, min_angle=10,
Hough space returned by the `hough_line` function.
angles : (M,) array
Angles returned by the `hough_line` function. Assumed to be continuous.
(`angles[-1] - angles[0] == PI`).
dists : (N, ) array
Distances returned by the `hough_line` function.
min_distance : int
@@ -41,15 +41,6 @@ def test_hough_line_angles():
assert_equal(len(angles), 10)
def test_py_hough():
ht._hough, fast_hough = ht._py_hough, ht._hough
yield append_desc(test_hough_line, '_python')
yield append_desc(test_hough_line_angles, '_python')
tf._hough = fast_hough
def test_probabilistic_hough():
# Generate a test image
img = np.zeros((100, 100), dtype=int)