霍夫圆检测几种方法准确率比较代码
时间: 2023-11-12 11:48:24 浏览: 128
用霍夫变换地方法来检测圆的代码
4星 · 用户满意度95%
霍夫圆变换是一种常用的圆形检测方法,常用于图像处理中的圆形检测。下面介绍几种常见的霍夫圆变换方法,以及它们的代码实现。
1. 基于边缘检测的霍夫圆变换
```python
import cv2
import numpy as np
img = cv2.imread('coins.jpg',0)
img = cv2.medianBlur(img,5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,20,
param1=50,param2=30,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
# draw the outer circle
cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
# draw the center of the circle
cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
cv2.imshow('detected circles',cimg)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
2. 基于积分图像的霍夫圆变换
```python
import cv2
import numpy as np
def HoughTransform(img, min_radius, max_radius):
height, width = img.shape
# Create an accumulator array to store circle votes
accu = np.zeros((height, width, max_radius - min_radius + 1), dtype=np.uint64)
# Create the radius dimension of the accumulator array
radius_range = range(min_radius, max_radius + 1)
cos_theta = np.array([np.cos(theta) for theta in np.arange(0, 360, 1) * np.pi / 180])
sin_theta = np.array([np.sin(theta) for theta in np.arange(0, 360, 1) * np.pi / 180])
num_thetas = len(cos_theta)
# Compute the integral image of the input image
int_img = np.cumsum(np.cumsum(img, axis=0), axis=1)
# Loop over all radii
for r_idx, radius in enumerate(radius_range):
# Create a circle mask
circle_pixels = np.zeros((2 * (radius + 1), 2 * (radius + 1)), dtype=np.uint8)
cv2.circle(circle_pixels, (radius, radius), radius, color=1, thickness=-1, lineType=cv2.LINE_AA)
# Compute the perimeter of the circle
num_edge_pixels = cv2.countNonZero(circle_pixels)
# Compute the (x, y) coordinates of the circle perimeter
edge_pixels = np.zeros((num_edge_pixels, 2), dtype=np.uint32)
edge_idx = 0
for i in range(circle_pixels.shape[0]):
for j in range(circle_pixels.shape[1]):
if circle_pixels[i, j] == 1:
edge_pixels[edge_idx] = np.array([i, j])
edge_idx += 1
# Loop over all (x, y) coordinates of the circle perimeter
for edge_pixel in edge_pixels:
x, y = edge_pixel
# Loop over all possible theta values
for theta_idx in range(num_thetas):
# Compute the (x, y) coordinates of the circle center
a = int(round(x - radius * cos_theta[theta_idx]))
b = int(round(y - radius * sin_theta[theta_idx]))
# Check if the circle center is inside the image
if a >= 0 and a < height and b >= 0 and b < width:
# Compute the sum of pixel intensities along the circle perimeter
sum_pixel_intensities = int_img[min(height - 1, a + radius), min(width - 1, b + radius)] \
- int_img[min(height - 1, a + radius), max(0, b - radius - 1)] \
- int_img[max(0, a - radius - 1), min(width - 1, b + radius)] \
+ int_img[max(0, a - radius - 1), max(0, b - radius - 1)]
# Accumulate the circle vote
accu[a, b, r_idx] += sum_pixel_intensities
return accu
def FindCircles(accu, min_radius, max_radius, num_circles, threshold_ratio):
height, width, num_radii = accu.shape
# Find the top num_circles circle candidates
candidate_centers = []
candidate_radii = []
candidate_votes = []
for i in range(num_circles):
idx = np.argmax(accu)
r_idx = idx % num_radii
idx = idx // num_radii
y = idx % height
x = idx // height
candidate_centers.append((x, y))
candidate_radii.append(min_radius + r_idx)
candidate_votes.append(accu[x, y, r_idx])
accu[x, y, r_idx] = 0
# Compute the circle thresholds
candidate_votes = np.array(candidate_votes)
threshold = candidate_votes.max() * threshold_ratio
# Find circles whose votes exceed the threshold
circles = []
for i in range(num_circles):
if candidate_votes[i] >= threshold:
circles.append((candidate_centers[i], candidate_radii[i]))
return circles
img = cv2.imread('coins.jpg', 0)
img = cv2.medianBlur(img, 5)
img = cv2.GaussianBlur(img, (5, 5), 0)
circles = FindCircles(HoughTransform(img, 20, 30), 20, 30, 20, 0.5)
output = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
for circle in circles:
x, y = circle[0]
r = circle[1]
cv2.circle(output, (x, y), r, (0, 255, 0), 2)
cv2.imshow('circles', output)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
3. 基于梯度方向的霍夫圆变换
```python
import cv2
import numpy as np
def HoughCircle(img, min_radius, max_radius, threshold):
height, width = img.shape
# Compute the gradient magnitude and direction
grad_x = cv2.Sobel(img, cv2.CV_32F, 1, 0, ksize=3)
grad_y = cv2.Sobel(img, cv2.CV_32F, 0, 1, ksize=3)
grad_mag = np.sqrt(grad_x ** 2 + grad_y ** 2)
grad_dir = np.arctan2(grad_y, grad_x)
# Create an accumulator array to store circle votes
accu = np.zeros((height, width, max_radius - min_radius + 1), dtype=np.uint64)
# Loop over all radii
radius_range = range(min_radius, max_radius + 1)
for r_idx, radius in enumerate(radius_range):
# Compute the (x, y) coordinates of the circle perimeter
circle_pixels = np.zeros((2 * (radius + 1), 2 * (radius + 1)), dtype=np.uint8)
cv2.circle(circle_pixels, (radius, radius), radius, color=1, thickness=-1, lineType=cv2.LINE_AA)
edge_pixels = np.argwhere(circle_pixels == 1)
edge_pixels -= np.array([radius, radius])
# Loop over all (x, y) coordinates of the circle perimeter
for edge_pixel in edge_pixels:
x, y = edge_pixel
# Compute the (x, y) coordinates of the circle center
a = int(round(x + radius))
b = int(round(y + radius))
# Check if the circle center is inside the image
if a >= 0 and a < height and b >= 0 and b < width:
# Compute the gradient direction of the edge pixel
edge_dir = grad_dir[a, b]
# Compute the orientation difference between the edge pixel and the circle
orientation_diff = np.abs(edge_dir - np.arange(0, 360, 1) * np.pi / 180)
orientation_diff = np.minimum(orientation_diff, np.abs(orientation_diff - np.pi))
# Compute the edge strength of the edge pixel
edge_strength = grad_mag[a, b]
# Compute the circle vote
vote = edge_strength * np.exp(-orientation_diff ** 2 / (2 * (np.pi / 12) ** 2))
accu[a, b, r_idx] += vote
# Find the circle centers and radii with the highest votes
centers = []
radii = []
votes = []
for r_idx, radius in enumerate(radius_range):
max_votes = np.max(accu[:, :, r_idx])
if max_votes > threshold:
idx = np.argmax(accu[:, :, r_idx])
y = idx % height
x = idx // height
centers.append((x, y))
radii.append(radius)
votes.append(max_votes)
return centers, radii, votes
img = cv2.imread('coins.jpg', 0)
img = cv2.medianBlur(img, 5)
centers, radii, votes = HoughCircle(img, 20, 30, 100)
output = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
for i in range(len(centers)):
x, y = centers[i]
r = radii[i]
cv2.circle(output, (y, x), r, (0, 255, 0), 2)
cv2.imshow('circles', output)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
以上是三种常见的霍夫圆变换方法的代码实现及比较,可以根据实际需求选择合适的方法。
阅读全文