根据anny算法的原理自定义一个my_canny函数来实现边缘检测
时间: 2024-06-12 18:06:52 浏览: 17
以下是一个基于anny算法实现的my_canny函数,用于边缘检测:
```python
import numpy as np
import cv2
def my_canny(image, low_threshold, high_threshold, aperture_size=3):
# 1. 首先进行灰度化处理
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 2. 对图像进行高斯滤波
blurred = cv2.GaussianBlur(gray, (aperture_size, aperture_size), 0)
# 3. 计算图像边缘的梯度和方向
grad_x = cv2.Sobel(blurred, cv2.CV_16S, 1, 0)
grad_y = cv2.Sobel(blurred, cv2.CV_16S, 0, 1)
gradient = cv2.addWeighted(np.abs(grad_x), 0.5, np.abs(grad_y), 0.5, 0)
theta = np.arctan2(grad_y, grad_x)
theta = np.rad2deg(theta) % 180
# 4. 计算图像中的非极大值点
rows, cols = gradient.shape
non_max_sup = np.zeros((rows, cols), dtype=np.uint8)
for i in range(1, rows-1):
for j in range(1, cols-1):
if (0 <= theta[i,j] < 22.5) or (157.5 <= theta[i,j] <= 180):
if (gradient[i,j] >= gradient[i,j-1]) and (gradient[i,j] >= gradient[i,j+1]):
non_max_sup[i,j] = gradient[i,j]
elif (22.5 <= theta[i,j] < 67.5):
if (gradient[i,j] >= gradient[i-1,j-1]) and (gradient[i,j] >= gradient[i+1,j+1]):
non_max_sup[i,j] = gradient[i,j]
elif (67.5 <= theta[i,j] < 112.5):
if (gradient[i,j] >= gradient[i-1,j]) and (gradient[i,j] >= gradient[i+1,j]):
non_max_sup[i,j] = gradient[i,j]
else:
if (gradient[i,j] >= gradient[i-1,j+1]) and (gradient[i,j] >= gradient[i+1,j-1]):
non_max_sup[i,j] = gradient[i,j]
# 5. 使用双阈值算法进行边缘检测
thresholded = np.zeros((rows, cols), dtype=np.uint8)
strong_edges = (non_max_sup > high_threshold)
thresholded[strong_edges] = 255
weak_edges = (non_max_sup >= low_threshold) & (non_max_sup <= high_threshold)
thresholded[weak_edges] = 127
# 使用连通性分析来增强弱边缘
_, contours, hierarchy = cv2.findContours(thresholded, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
if cv2.contourArea(contour) < 100:
continue
contour = contour.reshape(-1, 2)
for x, y in contour:
if thresholded[y, x] == 127:
thresholded[y, x] = 255
# 6. 返回检测到的边缘图像
return thresholded
```
上述函数中,使用的参数和方法与anny算法中的一致:
- aperture_size表示高斯滤波的卷积核大小,一般设置为3;
- low_threshold和high_threshold表示双阈值算法的两个阈值;
- 在计算非极大值点时,根据梯度方向来判断当前像素是否为非极大值点;
- 在进行弱边缘的增强时,先使用cv2.findContours函数找到所有的轮廓,然后对每个轮廓进行面积大小的判断,只有面积大于一定值的轮廓才会被认为是真正的边缘。