Canny边缘检测算法-个人记录

Canny边缘检测算法是计算机视觉中最经典和广泛使用的边缘检测算法之一,由John F. Canny在1986年提出。

核心原理

Canny算法基于以下几个关键准则:

  1. 低错误率:尽可能标识出图像中的真实边缘,同时最小化噪声产生的伪边缘
  2. 边缘定位精确:标识的边缘应尽可能接近真实边缘位置
  3. 单一响应:对于一个真实边缘,算法应只标识一次

算法步骤

  1. 高斯滤波:使用高斯滤波器平滑图像,减少噪声影响
  2. 梯度计算:计算图像梯度幅值和方向(通常使用Sobel算子)
  3. 非极大值抑制:细化边缘,确保边缘只有一个像素宽度
  4. 双阈值检测:使用高低阈值区分强边缘、弱边缘和非边缘
  5. 边缘连接:通过滞后阈值法连接边缘,保留连续的边缘结构

在复杂环境中的挑战

  • 光照变化:不均匀光照会影响边缘检测的稳定性
  • 纹理复杂:复杂纹理可能产生大量伪边缘
  • 噪声干扰:高噪声环境下容易产生虚假边缘
  • 边缘模糊:低对比度边缘难以检测

优化策略以提高复杂环境性能

1. 自适应预处理优化

# 示例:自适应高斯滤波
import cv2
import numpy as np

def adaptive_gaussian_filter(image, sigma_range=(0.5, 2.0)):
    # 根据局部方差调整滤波强度
    # 在平滑区域使用较小sigma,复杂区域使用较大sigma
    local_variance = cv2.Laplacian(image, cv2.CV_64F).var()
    adaptive_sigma = sigma_range[0] + (local_variance / 255.0) * (sigma_range[1] - sigma_range[0])
    return cv2.GaussianBlur(image, (0, 0), adaptive_sigma)

2. 多尺度边缘检测

# 多尺度Canny检测
def multiscale_canny(image, scales=[0.5, 1.0, 1.5, 2.0]):
    edges_collection = []
    for scale in scales:
        if scale != 1.0:
            # 缩放图像
            scaled = cv2.resize(image, None, fx=scale, fy=scale)
        else:
            scaled = image
            
        # 应用Canny检测
        edges = cv2.Canny(scaled, 50, 150)
        
        # 恢复到原始尺寸
        if scale != 1.0:
            edges = cv2.resize(edges, (image.shape[1], image.shape[0]))
            
        edges_collection.append(edges)
    
    # 融合多尺度结果
    final_edges = np.zeros_like(image)
    for edges in edges_collection:
        final_edges = np.maximum(final_edges, edges)
        
    return final_edges

3. 自适应阈值优化

# 基于图像特性的自适应阈值计算
def adaptive_canny_thresholds(image):
    # 使用Otsu方法计算初始阈值
    _, binary = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    
    # 计算图像梯度
    grad_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
    grad_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
    gradient_magnitude = np.sqrt(grad_x**2 + grad_y**2)
    
    # 基于梯度统计计算自适应阈值
    mean_grad = np.mean(gradient_magnitude)
    std_grad = np.std(gradient_magnitude)
    
    # 高阈值: 均值 + 1标准差
    high_threshold = min(255, mean_grad + std_grad)
    # 低阈值: 高阈值的0.4倍(经典比例)
    low_threshold = high_threshold * 0.4
    
    return int(low_threshold), int(high_threshold)

4. 改进的非极大值抑制

# 更精确的插值方法
def improved_non_maximum_suppression(gradient_magnitude, gradient_angle):
    rows, cols = gradient_magnitude.shape
    suppressed = np.zeros_like(gradient_magnitude)
    
    # 角度量化(0, 45, 90, 135度)
    angle = np.rad2deg(gradient_angle) % 180
    
    for i in range(1, rows-1):
        for j in range(1, cols-1):
            try:
                q = 255
                r = 255
                
                # 根据角度确定邻域方向
                if (0 <= angle[i,j] < 22.5) or (157.5 <= angle[i,j] <= 180):
                    # 水平方向
                    q = gradient_magnitude[i, j+1]
                    r = gradient_magnitude[i, j-1]
                elif (22.5 <= angle[i,j] < 67.5):
                    # 45度方向
                    q = gradient_magnitude[i+1, j-1]
                    r = gradient_magnitude[i-1, j+1]
                elif (67.5 <= angle[i,j] < 112.5):
                    # 垂直方向
                    q = gradient_magnitude[i+1, j]
                    r = gradient_magnitude[i-1, j]
                elif (112.5 <= angle[i,j] < 157.5):
                    # 135度方向
                    q = gradient_magnitude[i-1, j-1]
                    r = gradient_magnitude[i+1, j+1]
                
                # 非极大值抑制
                if (gradient_magnitude[i,j] >= q) and (gradient_magnitude[i,j] >= r):
                    suppressed[i,j] = gradient_magnitude[i,j]
                else:
                    suppressed[i,j] = 0
            except IndexError:
                pass
    
    return suppressed

5. 后处理优化

# 形态学操作优化边缘
def post_process_edges(edges, kernel_size=3):
    # 定义结构元素
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (kernel_size, kernel_size))
    
    # 开运算去除小的噪声点
    opened = cv2.morphologyEx(edges, cv2.MORPH_OPEN, kernel)
    
    # 闭运算连接断开的边缘
    closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, kernel)
    
    return closed

6. 综合优化的Canny实现

def optimized_canny(image, use_adaptive=True, multiscale=False):
    # 预处理
    if len(image.shape) == 3:
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    else:
        gray = image.copy()
    
    # 多尺度处理
    if multiscale:
        return multiscale_canny(gray)
    
    # 自适应阈值计算
    if use_adaptive:
        low_thresh, high_thresh = adaptive_canny_thresholds(gray)
    else:
        low_thresh, high_thresh = 50, 150
    
    # 应用Canny算法
    edges = cv2.Canny(gray, low_thresh, high_thresh)
    
    # 后处理
    edges = post_process_edges(edges)
    
    return edges
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

香蕉可乐荷包蛋

努力写有用的code

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值