<< Chapter < Page | Chapter >> Page > |
Code
def detect_edge(img, thresh, blursize):
"""Detects edges in an image
:param img: image to detect edges in:param thresh: minimum magnitude of gradient before it's considered an edge
:param blursize: size of Gaussian blur filter:return: boolean matrix of edges in image
"""# =============================
# "Generate Sobel kernel"# =============================
img = blur(img, blursize)sobelx = np.array([[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]])sobely = np.array([[-1, -2, -1],[0, 0, 0],[1, 2, 1]])# find partial derivatives of image by convolving with Sobel kernels
gradImgx = np.copy(img)gradImgy = np.copy(img)
gradImgy = signal.convolve2d(gradImgy, sobely, mode = "same")/4.0gradImgx = signal.convolve2d(gradImgx, sobelx, mode = "same")/4.0# =============================
# "Calculate gradient angle and magnitude at each pixel"# =============================
angleGrad = np.arctan2(gradImgy, gradImgx)magGrad = np.sqrt(np.square(gradImgy) + np.square(gradImgx))
isEdge = np.greater_equal(magGrad, thresh)return isEdge, angleGrad
A circle can be represented as a center and a radius, and the Hough circle transform transforms a image from (x, y) points to (radius, center) as shown in equation 2.6 and 2.7 and figure (Fig #).
Fig 2.5 Visual of the Hough transform
Since the center and radius are both unknowns, the Hough transform tests r = from a minimum radius radMin to maximum radius radMax.
def hough_circle(colorImg, img, isEdge, angleGrad, radMin, radMax, distMin, votesMin):
"""Uses the Hough circle transform to detect circles in image
:param img: Image to be operated on. size rows x cols. cv2 image format:param isEdge: rows x col size boolean matrix. True if pixel is edge pixel.
:param angleGrad: rows x col size float matrix. gradient direction at each pixel.:param radMin: int, minimum radius of circles detected
:param radMax: int, maximum radius of circles detected:param distMin: int, minimum distance between circles detected
:param votesMin: int, minimum threshold for accumulator value. The higher this value is,the less false circles detected
:return: numpy array of circles detected. Stored as a = [[radii], [rows], [cols]]where
a[0][i] is the radius of the ith circlea[1][i]is the row where the center of the ith circle is located
a[2][i] is the col where the center of the ith circle is located"""
rows, cols = img.shape# Initialize accumulator matrix
param_votes = np.zeros((radMax, rows, cols), dtype = int)# Initialize accumulator matrix of local maximums
param_maxes = np.zeros((radMax, rows, cols), dtype = int)# Perform Hough transform on each edge point with radii ranging from radMin to radMax
for r in range(0, rows):for c in range(0, cols):
# Get gradient angle at pixel (r,c)# (r, c) is the proposed center for the circle
theta = angleGrad[r][c]
if isEdge[r][c]:for rad in range(radMin, radMax):
# For each proposed, center,# Test each possible radius and give a vote to the resulting (rad, center) coordinates
xstar = round(c - rad * math.cos(theta))ystar = round(r - rad * math.sin(theta))
if xstar>=0 and xstar<cols and ystar>=0 and ystar<rows:
param_votes[rad][ystar][xstar]+= 1
# Add pi to the gradient angle so the angle also points in the other direction because# who knows is the gradient is pointing towards or away from the center of the circle.
theta = theta + math.pixstar = round(c - rad * math.cos(theta))
ystar = round(r - rad * math.sin(theta))# Add a vote to (rad, center) if the center is within the bounds of the image
if xstar>=0 and xstar<cols and ystar>=0 and ystar<rows:
param_votes[rad][ystar][xstar]+= 1
# Find local maximums in the accumulator matrix.param_votes[param_votes<votesMin] = 0param_max = filter.maximum_filter(param_votes, size = (distMin, distMin, distMin))
param_max = np.logical_and(param_votes, param_max)# Find indices of maximums
circle_indices = np.where(param_max)# Will most likely find too many circles, so use helper function to average clusters of circles
# Also removes false positivescircle_indices = reduce_circles(circle_indices, distMin, param_votes)
total_circles = len(circle_indices[0])
# draw detected circles onto imgfor i in range(0, total_circles):
rad = circle_indices[0][i]
r = circle_indices[1][i]
c = circle_indices[2][i]
cv2.circle(colorImg, (c, r), rad, (0,255,0), thickness = 3)cv2.circle(colorImg, (c, r), 1, (0, 255, 0), thickness = 2)
return colorImg, circle_indices
Notification Switch
Would you like to follow the 'Hough transform object detection' conversation and receive update notifications?