边缘检测与轮廓提取:Canny算子、霍夫变换、轮廓分析完整指南

引言

边缘检测与轮廓提取是计算机视觉中的基础而重要的技术,它们能够帮助我们从图像中提取出关键的几何结构信息。边缘代表了图像中亮度或颜色发生急剧变化的区域,而轮廓则是连接连续点(沿边界)的曲线。这些技术在目标检测、形状分析、图像分割等领域有着广泛应用。

📂 所属阶段:第一阶段 — 图像处理基石(传统 CV 篇)
🔗 相关章节:图像增强与滤波 · 特征匹配实战


1. 边缘检测基础概念

1.1 什么是边缘?

边缘是图像中像素值发生显著变化的地方,通常对应于:

  • 物体的边界
  • 纹理的变化
  • 阴影与光照变化
  • 颜色过渡区域

1.2 边缘检测的意义

边缘检测在计算机视觉中扮演着重要角色:

  • 特征提取:提取图像中的关键结构信息
  • 目标定位:帮助定位和识别图像中的物体
  • 图像分割:为后续的图像分割提供基础
  • 形状分析:用于分析物体的形状特征

1.3 边缘检测的数学原理

边缘检测本质上是寻找图像梯度的局部最大值:

"""
边缘检测的数学原理:

梯度 = 图像亮度变化的速率
- 梯度幅值:衡量变化的强度
- 梯度方向:指示变化的方向

主要算子:
1. Sobel算子:一阶导数,检测边缘方向
2. Laplacian算子:二阶导数,检测零交叉点
3. Canny算子:多阶段算法,最优边缘检测
"""

import numpy as np
import cv2

def compute_gradients(image):
    """
    计算图像的梯度
    """
    # Sobel算子计算x和y方向的梯度
    grad_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
    grad_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
    
    # 计算梯度幅值和方向
    magnitude = np.sqrt(grad_x**2 + grad_y**2)
    direction = np.arctan2(grad_y, grad_x)
    
    return magnitude, direction, grad_x, grad_y

# 梯度可视化
def visualize_gradients(image_path):
    """
    可视化图像梯度
    """
    img = cv2.imread(image_path, 0)
    mag, dir, grad_x, grad_y = compute_gradients(img)
    
    # 显示不同梯度分量
    cv2.imshow("Original", img)
    cv2.imshow("Gradient X", np.abs(grad_x))
    cv2.imshow("Gradient Y", np.abs(grad_y))
    cv2.imshow("Magnitude", mag.astype(np.uint8))
    cv2.waitKey(0)
    cv2.destroyAllWindows()

2. Canny边缘检测详解

2.1 Canny算法原理

Canny边缘检测是John F. Canny在1986年提出的多阶段边缘检测算法,被认为是边缘检测的黄金标准。其算法包含四个主要步骤:

  1. 高斯滤波:去除噪声
  2. 计算梯度:找出边缘强度和方向
  3. 非极大值抑制:细化边缘
  4. 滞后阈值:确定真正的边缘
def canny_algorithm_detailed(image_path):
    """
    Canny算法详细实现(演示原理)
    """
    img = cv2.imread(image_path, 0)
    
    # 步骤1:高斯滤波
    blurred = cv2.GaussianBlur(img, (5, 5), 1.4)
    
    # 步骤2:计算梯度
    grad_x = cv2.Sobel(blurred, cv2.CV_64F, 1, 0, ksize=3)
    grad_y = cv2.Sobel(blurred, cv2.CV_64F, 0, 1, ksize=3)
    
    # 梯度幅值和方向
    magnitude = np.sqrt(grad_x**2 + grad_y**2)
    direction = np.arctan2(grad_y, grad_x)
    
    # 步骤3:非极大值抑制(简化版)
    # 实际的非极大值抑制更复杂,这里只是概念演示
    suppressed = magnitude.copy()
    
    # 步骤4:滞后阈值
    # OpenCV内置的Canny函数
    edges = cv2.Canny(blurred, 50, 150)
    
    return {
        'original': img,
        'blurred': blurred,
        'magnitude': magnitude.astype(np.uint8),
        'edges': edges
    }

def canny_parameter_analysis(image_path):
    """
    分析Canny参数的影响
    """
    img = cv2.imread(image_path, 0)
    
    # 不同阈值的影响
    edges_low = cv2.Canny(img, 30, 100)    # 低阈值,更多边缘
    edges_medium = cv2.Canny(img, 100, 200) # 中等阈值
    edges_high = cv2.Canny(img, 200, 300)   # 高阈值,较少边缘
    
    # 不同高斯核的影响
    img_blur_1 = cv2.GaussianBlur(img, (3, 3), 1.0)
    img_blur_2 = cv2.GaussianBlur(img, (5, 5), 1.4)
    img_blur_3 = cv2.GaussianBlur(img, (7, 7), 2.0)
    
    edges_blur_1 = cv2.Canny(img_blur_1, 100, 200)
    edges_blur_2 = cv2.Canny(img_blur_2, 100, 200)
    edges_blur_3 = cv2.Canny(img_blur_3, 100, 200)
    
    return {
        'low_threshold': edges_low,
        'medium_threshold': edges_medium,
        'high_threshold': edges_high,
        'blur_3x3': edges_blur_1,
        'blur_5x5': edges_blur_2,
        'blur_7x7': edges_blur_3
    }

2.2 Canny参数详解

def canny_best_practices():
    """
    Canny边缘检测最佳实践
    """
    # 参数说明:
    # image: 输入图像(通常是灰度图)
    # threshold1: 滞后阈值的下限
    # threshold2: 滞后阈值的上限
    # apertureSize: Sobel算子的孔径大小(默认3)
    # L2gradient: 是否使用更精确的L2范数计算梯度
    
    """
    参数选择指南:
    
    1. threshold1 和 threshold2 的关系:
       - 通常 threshold2 = 2-3 * threshold1
       - 阈值比值在 1:2 到 1:3 之间效果较好
    
    2. 阈值选择策略:
       - 低阈值:检测弱边缘,但可能引入噪声
       - 高阈值:减少噪声,但可能丢失边缘
       
    3. 预处理建议:
       - 先进行高斯滤波去除噪声
       - 考虑使用双边滤波保留边缘
    """
    
    # 自动阈值选择方法
    def auto_canny(image, sigma=0.33):
        """
        自动选择Canny阈值
        """
        # 计算图像的中值
        v = np.median(image)
        
        # 根据中值自动计算阈值
        lower = int(max(0, (1.0 - sigma) * v))
        upper = int(min(255, (1.0 + sigma) * v))
        
        return cv2.Canny(image, lower, upper)
    
    return auto_canny

def canny_comparison_techinques(image_path):
    """
    不同边缘检测技术比较
    """
    img = cv2.imread(image_path, 0)
    
    # Sobel边缘检测
    sobel_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
    sobel_y = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
    sobel_combined = np.sqrt(sobel_x**2 + sobel_y**2).astype(np.uint8)
    
    # Scharr边缘检测(更精确的Sobel)
    scharr_x = cv2.Scharr(img, cv2.CV_64F, 1, 0)
    scharr_y = cv2.Scharr(img, cv2.CV_64F, 0, 1)
    scharr_combined = np.sqrt(scharr_x**2 + scharr_y**2).astype(np.uint8)
    
    # Laplacian边缘检测
    laplacian = cv2.Laplacian(img, cv2.CV_64F).astype(np.uint8)
    
    # Canny边缘检测
    canny_edges = cv2.Canny(img, 100, 200)
    
    return {
        'original': img,
        'sobel': sobel_combined,
        'scharr': scharr_combined,
        'laplacian': laplacian,
        'canny': canny_edges
    }

3. 霍夫变换详解

3.1 霍夫变换原理

霍夫变换是一种特征提取技术,用于检测图像中的几何形状(如直线、圆等)。

def hough_transform_principle():
    """
    霍夫变换原理说明
    """
    """
    直线霍夫变换原理:
    
    1. 直角坐标系中的直线:y = mx + b
    2. 参数空间:(m, b) 表示所有可能的直线
    3. 图像空间中的点 (x₀, y₀) 对应参数空间中的一条线:b = -x₀*m + y₀
    4. 多个共线的点在参数空间中对应的线会相交于一点
    5. 交点的坐标就是直线的参数
    
    极坐标形式(更常用):
    ρ = x*cos(θ) + y*sin(θ)
    参数空间:(ρ, θ),避免垂直线的问题
    """
    
    # 实际应用中,我们使用OpenCV的函数
    pass

def line_detection_detailed(image_path):
    """
    详细的直线检测实现
    """
    img = cv2.imread(image_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 边缘检测
    edges = cv2.Canny(gray, 50, 150, apertureSize=3)
    
    # 标准霍夫变换
    lines_standard = cv2.HoughLines(edges, 1, np.pi/180, threshold=100)
    
    # 概率霍夫变换(更实用)
    lines_prob = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=100, 
                                minLineLength=50, maxLineGap=10)
    
    # 在原图上绘制直线
    img_lines = img.copy()
    if lines_prob is not None:
        for line in lines_prob:
            x1, y1, x2, y2 = line[0]
            cv2.line(img_lines, (x1, y1), (x2, y2), (0, 255, 0), 2)
    
    return {
        'original': img,
        'edges': edges,
        'detected_lines': img_lines,
        'lines_data': lines_prob
    }

def circle_detection_detailed(image_path):
    """
    详细的圆检测实现
    """
    img = cv2.imread(image_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 高斯模糊
    gray_blur = cv2.GaussianBlur(gray, (9, 9), 2, 2)
    
    # 霍夫圆检测
    circles = cv2.HoughCircles(
        gray_blur,
        cv2.HOUGH_GRADIENT,
        dp=1,           # 累加器分辨率
        minDist=20,     # 圆心之间的最小距离
        param1=50,      # Canny边缘检测的高阈值
        param2=30,      # 中心检测阈值,值越小检测到的圆越多
        minRadius=5,    # 最小半径
        maxRadius=100   # 最大半径
    )
    
    # 绘制检测到的圆
    img_circles = img.copy()
    if circles is not None:
        circles = np.round(circles[0, :]).astype("int")
        for (x, y, r) in circles:
            # 绘制圆心
            cv2.circle(img_circles, (x, y), 1, (0, 100, 255), 3)
            # 绘制圆
            cv2.circle(img_circles, (x, y), r, (0, 255, 0), 2)
    
    return {
        'original': img,
        'gray_blur': gray_blur,
        'detected_circles': img_circles,
        'circles_data': circles
    }

3.2 霍夫变换参数详解

def hough_parameters_guide():
    """
    霍夫变换参数详细指南
    """
    """
    HoughLines 参数:
    - image: 边缘检测后的二值图像
    - rho: 距离精度(像素)
    - theta: 角度精度(弧度)
    - threshold: 累加器阈值,直线上的点数超过此值才认为是直线
    - srn, stn: 多尺度参数(通常为0)
    
    HoughLinesP 参数:
    - image: 边缘检测后的二值图像
    - rho: 距离精度
    - theta: 角度精度
    - threshold: 累加器阈值
    - minLineLength: 最小线段长度
    - maxLineGap: 同一直线上两点间的最大间隙
    
    HoughCircles 参数:
    - image: 输入图像(通常是灰度图)
    - method: 检测方法(通常使用cv2.HOUGH_GRADIENT)
    - dp: 累加器分辨率,值越大分辨率越低
    - minDist: 检测到的圆心之间的最小距离
    - param1: Canny边缘检测的高阈值
    - param2: 中心检测阈值,值越小检测到的圆越多
    - minRadius: 最小半径
    - maxRadius: 最大半径
    """

def advanced_hough_techniques(image_path):
    """
    高级霍夫变换技术
    """
    img = cv2.imread(image_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 预处理:提高检测效果
    # 1. 高斯模糊
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    
    # 2. 形态学操作
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
    morphed = cv2.morphologyEx(blurred, cv2.MORPH_CLOSE, kernel)
    
    # 3. 边缘检测
    edges = cv2.Canny(morphed, 50, 150)
    
    # 针对不同场景的参数调整
    # 场景1:检测较长的直线
    lines_long = cv2.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength=100, maxLineGap=10)
    
    # 场景2:检测较短的直线段
    lines_short = cv2.HoughLinesP(edges, 1, np.pi/180, 30, minLineLength=10, maxLineGap=5)
    
    # 场景3:检测密集的圆
    circles_dense = cv2.HoughCircles(
        blurred, cv2.HOUGH_GRADIENT, 1, 10, param1=50, param2=20, minRadius=5, maxRadius=50
    )
    
    # 场景4:检测稀疏的大圆
    circles_sparse = cv2.HoughCircles(
        blurred, cv2.HOUGH_GRADIENT, 2, 100, param1=100, param2=50, minRadius=30, maxRadius=200
    )
    
    return {
        'original': img,
        'preprocessed': morphed,
        'edges': edges,
        'long_lines': lines_long,
        'short_lines': lines_short,
        'dense_circles': circles_dense,
        'sparse_circles': circles_sparse
    }

4. 轮廓提取与分析

4.1 轮廓提取基础

def contour_extraction_basics(image_path):
    """
    轮廓提取基础操作
    """
    img = cv2.imread(image_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 二值化
    _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
    
    # 查找轮廓
    # cv2.findContours 返回: 轮廓列表, 层次结构
    contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    
    # 在原图上绘制所有轮廓
    img_contours = img.copy()
    cv2.drawContours(img_contours, contours, -1, (0, 255, 0), 2)
    
    # 绘制特定轮廓(比如最大的)
    if contours:
        largest_contour = max(contours, key=cv2.contourArea)
        cv2.drawContours(img_contours, [largest_contour], -1, (0, 0, 255), 3)
    
    return {
        'original': img,
        'binary': binary,
        'all_contours': img_contours,
        'contour_count': len(contours),
        'hierarchy': hierarchy
    }

def contour_modes_comparison(image_path):
    """
    不同轮廓检索模式比较
    """
    img = cv2.imread(image_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
    
    # RETR_EXTERNAL: 只检测外轮廓
    contours_external, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    # RETR_LIST: 检测所有轮廓,不建立等级关系
    contours_list, _ = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    
    # RETR_CCOMP: 检测所有轮廓,建立两层等级关系
    contours_ccomp, hierarchy_ccomp = cv2.findContours(binary, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
    
    # RETR_TREE: 检测所有轮廓,建立完整的等级关系
    contours_tree, hierarchy_tree = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    
    # 绘制不同模式的结果
    def draw_contours_with_color(img, contours, color):
        img_copy = img.copy()
        cv2.drawContours(img_copy, contours, -1, color, 2)
        return img_copy
    
    return {
        'external': draw_contours_with_color(img, contours_external, (255, 0, 0)),
        'list': draw_contours_with_color(img, contours_list, (0, 255, 0)),
        'ccomp': draw_contours_with_color(img, contours_ccomp, (0, 0, 255)),
        'tree': draw_contours_with_color(img, contours_tree, (255, 255, 0)),
        'counts': {
            'external': len(contours_external),
            'list': len(contours_list),
            'ccomp': len(contours_ccomp),
            'tree': len(contours_tree)
        }
    }

4.2 轮廓特征分析

def contour_features_analysis(image_path):
    """
    轮廓特征分析
    """
    img = cv2.imread(image_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
    contours, _ = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    
    # 轮廓分析函数
    analysis_results = []
    
    for i, contour in enumerate(contours):
        if cv2.contourArea(contour) < 100:  # 过滤小轮廓
            continue
            
        # 基本特征
        area = cv2.contourArea(contour)
        perimeter = cv2.arcLength(contour, True)
        
        # 边界矩形
        x, y, w, h = cv2.boundingRect(contour)
        aspect_ratio = float(w) / h
        extent = float(area) / (w * h)
        
        # 最小包围圆
        (cx, cy), radius = cv2.minEnclosingCircle(contour)
        circularity = 4 * np.pi * area / (perimeter * perimeter)
        
        # 凸包
        hull = cv2.convexHull(contour)
        hull_area = cv2.contourArea(hull)
        solidity = float(area) / hull_area if hull_area > 0 else 0
        
        # 拟合椭圆
        if len(contour) >= 5:  # 至少需要5个点才能拟合椭圆
            ellipse = cv2.fitEllipse(contour)
            (ex, ey), (ma, MA), angle = ellipse
        else:
            ellipse = None
            ex = ey = ma = MA = angle = None
        
        analysis_results.append({
            'index': i,
            'area': area,
            'perimeter': perimeter,
            'aspect_ratio': aspect_ratio,
            'extent': extent,
            'circularity': circularity,
            'solidity': solidity,
            'bounding_rect': (x, y, w, h),
            'min_enclosing_circle': ((int(cx), int(cy)), int(radius)),
            'ellipse': ellipse
        })
    
    return analysis_results

def contour_approximation(image_path):
    """
    轮廓近似
    """
    img = cv2.imread(image_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
    contours, _ = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    
    img_approx = img.copy()
    
    for contour in contours:
        if cv2.contourArea(contour) < 100:
            continue
            
        # 不同精度的轮廓近似
        epsilon_1 = 0.01 * cv2.arcLength(contour, True)
        epsilon_5 = 0.05 * cv2.arcLength(contour, True)
        epsilon_10 = 0.1 * cv2.arcLength(contour, True)
        
        approx_1 = cv2.approxPolyDP(contour, epsilon_1, True)
        approx_5 = cv2.approxPolyDP(contour, epsilon_5, True)
        approx_10 = cv2.approxPolyDP(contour, epsilon_10, True)
        
        # 绘制不同近似的轮廓
        cv2.drawContours(img_approx, [approx_1], -1, (255, 0, 0), 2)  # 蓝色:高精度
        cv2.drawContours(img_approx, [approx_5], -1, (0, 255, 0), 2)  # 绿色:中等精度
        cv2.drawContours(img_approx, [approx_10], -1, (0, 0, 255), 2) # 红色:低精度
    
    return {
        'original': img,
        'approximated': img_approx,
        'precision_levels': [epsilon_1, epsilon_5, epsilon_10]
    }

5. 实战项目:形状检测器

class ShapeDetector:
    """
    形状检测器
    """
    
    def __init__(self):
        pass
    
    def detect_shape(self, contour):
        """
        检测轮廓的形状
        """
        # 计算轮廓面积
        area = cv2.contourArea(contour)
        
        # 轮廓近似
        perimeter = cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, 0.04 * perimeter, True)
        vertices = len(approx)
        
        # 计算长宽比
        x, y, w, h = cv2.boundingRect(approx)
        aspect_ratio = float(w) / h
        
        # 计算圆度
        circularity = 0
        if perimeter > 0:
            circularity = 4 * np.pi * area / (perimeter * perimeter)
        
        # 形状判断逻辑
        if vertices == 3:
            shape = "Triangle"
        elif vertices == 4:
            # 检查是否为正方形或矩形
            if aspect_ratio >= 0.95 and aspect_ratio <= 1.05:
                shape = "Square"
            else:
                shape = "Rectangle"
        elif vertices == 5:
            shape = "Pentagon"
        elif vertices == 6:
            shape = "Hexagon"
        elif circularity > 0.8:
            shape = "Circle"
        else:
            shape = "Polygon"
        
        return {
            'shape': shape,
            'vertices': vertices,
            'aspect_ratio': aspect_ratio,
            'circularity': circularity,
            'area': area
        }
    
    def detect_shapes_in_image(self, image_path):
        """
        在图像中检测所有形状
        """
        img = cv2.imread(image_path)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        
        # 预处理
        blurred = cv2.GaussianBlur(gray, (5, 5), 0)
        edged = cv2.Canny(blurred, 50, 150)
        
        # 轮廓检测
        contours, _ = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        
        # 绘制结果
        result_img = img.copy()
        shapes_info = []
        
        for contour in contours:
            # 过滤小轮廓
            if cv2.contourArea(contour) < 100:
                continue
            
            # 获取形状信息
            shape_info = self.detect_shape(contour)
            
            # 获取轮廓中心点
            M = cv2.moments(contour)
            if M["m00"] != 0:
                cX = int(M["m10"] / M["m00"])
                cY = int(M["m01"] / M["m00"])
            else:
                cX, cY = 0, 0
            
            # 绘制轮廓和标签
            cv2.drawContours(result_img, [contour], -1, (0, 255, 0), 2)
            cv2.putText(result_img, shape_info['shape'], (cX - 20, cY - 20),
                       cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
            
            shapes_info.append({
                'info': shape_info,
                'center': (cX, cY),
                'contour': contour
            })
        
        return {
            'original': img,
            'result': result_img,
            'shapes': shapes_info
        }

def lane_detection_example(image_path):
    """
    车道线检测示例(综合应用)
    """
    img = cv2.imread(image_path)
    
    # 预处理
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (5, 5), 0)
    
    # 边缘检测
    edges = cv2.Canny(blur, 50, 150)
    
    # ROI(感兴趣区域)掩码
    height, width = edges.shape
    roi_vertices = np.array([[
        (0, height),
        (width//2 - 50, height//2 + 30),
        (width//2 + 50, height//2 + 30),
        (width, height)
    ]], dtype=np.int32)
    
    mask = np.zeros_like(edges)
    cv2.fillPoly(mask, roi_vertices, 255)
    masked_edges = cv2.bitwise_and(edges, mask)
    
    # 霍夫直线检测
    lines = cv2.HoughLinesP(
        masked_edges,
        rho=1,
        theta=np.pi/180,
        threshold=20,
        minLineLength=20,
        maxLineGap=300
    )
    
    # 绘制车道线
    lane_img = img.copy()
    if lines is not None:
        for line in lines:
            x1, y1, x2, y2 = line[0]
            cv2.line(lane_img, (x1, y1), (x2, y2), (0, 255, 0), 3)
    
    return {
        'original': img,
        'edges': edges,
        'masked_edges': masked_edges,
        'lane_detection': lane_img
    }

相关教程

边缘检测和轮廓提取是计算机视觉的基础技能,建议多实践不同参数组合的效果,理解每种方法的适用场景和局限性。

6. 总结

边缘检测与轮廓提取是计算机视觉中的关键技术,它们为后续的高级视觉任务提供了重要的几何结构信息:

核心技术总结:

  1. Canny边缘检测:最优边缘检测算法,多阶段处理
  2. 霍夫变换:检测直线、圆等几何形状
  3. 轮廓提取:获取对象边界,进行形状分析

应用场景:

  • 目标检测:通过边缘和轮廓定位物体
  • 形状识别:基于轮廓特征识别几何形状
  • 图像分割:利用边缘信息进行区域划分
  • 测量应用:通过轮廓进行尺寸测量

💡 重要提醒:边缘检测是许多计算机视觉任务的前置步骤,选择合适的参数对最终结果有重要影响。

🔗 扩展阅读