mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-29 03:21:19 +08:00
145 lines
4.1 KiB
Python
145 lines
4.1 KiB
Python
__all__ = ['hough', 'probabilistic_hough']
|
|
|
|
from itertools import izip as zip
|
|
|
|
import numpy as np
|
|
from ._hough_transform import _probabilistic_hough
|
|
|
|
|
|
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):
|
|
"""Performs a progressive probabilistic line Hough transform and returns the detected lines.
|
|
|
|
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)
|
|
|
|
|
|
def hough(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.
|
|
distances : ndarray
|
|
Distance values.
|
|
theta : ndarray
|
|
Angles at which the transform was computed.
|
|
|
|
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(img)
|
|
|
|
Plot the results:
|
|
|
|
>>> 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()
|
|
|
|
.. plot:: hough_tf.py
|
|
|
|
"""
|
|
return _hough(img, theta)
|