边缘检测(Edge Detection)

本文深入探讨了边缘检测在图像处理中的重要性,介绍了Roberts、Prewitt、Sobel等经典边缘检测算子的工作原理及应用,同时讲解了图像梯度、高斯滤波和平滑处理等关键概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

个人博客:wyxogo.top

边缘提取

在大多数时候图像的边缘可以承载大部分的信息,并且提取边缘可以除去很多干扰信息,提高处理数据的效率

目标:

识别图像中的突然变化(不连续)

  • 图像的大部分语义信息和形状信息都可以编码在边缘上
  • 理想:艺术家使用线条勾勒画(但艺术家也使用对象层次的知识)

边缘的种类

  • 表面形状的突变
  • 深度方向的不连续
  • 表面颜色的突变
  • 光线阴影的不连续

边缘的特征

边缘是图像强度函数中快速变化的地方,变化的地方就存在梯度,对灰度值求导,导数为0的点即为边界点

卷积的导数

  • 偏导数公式:

∂ f ( x , y ) ∂ x = lim ⁡ ε → 0 f ( x + ε , y ) − f ( x , y ) ε \frac {\partial f(x,y)}{\partial x} = \lim_{\varepsilon \rightarrow 0} \frac{f(x+\varepsilon ,y)-f(x,y)}{\varepsilon} xf(x,y)=ε0limεf(x+ε,y)f(x,y)

  • 在卷积中为描述数据,采取 近似化处理:
    ∂ f ( x , y ) ∂ x ≈ f ( x + 1 , y ) − f ( x , y ) 1 \frac {\partial f(x,y)}{\partial x} \approx \frac{f(x+1,y)-f(x,y)}{1} xf(x,y)1f(x+1,y)f(x,y)

显然在x方向的导数就是与该像素自身与右边相邻像素的差值

卷积描述偏导

使用卷积核处理


对灰度图的x和y方向分别处理后的效果如下图:

有限差分滤波器(卷积核)

  • Roberts 算子
    Roberts 算子是一种最简单的算子,是一种利用局部差分算子寻找边缘的算子。他采用对角线方向相邻两象素之差近似梯度幅值检测边缘。检测垂直边缘的效果好于斜向边缘,定位精度高,对噪声敏感,无法抑制噪声的影响。
    1963年, Roberts 提出了这种寻找边缘的算子。 Roberts 边缘算子是一个 2x2 的模版,采用的是对角方向相邻的两个像素之差。
    Roberts 算子的模板分为水平方向和垂直方向,如下所示,从其模板可以看出, Roberts 算子能较好的增强正负 45 度的图像边缘。

d x = [ − 1 0 0 1 ] dx = \left[ \begin{matrix} -1 & 0\\ 0 & 1 \\ \end{matrix} \right] dx=[1001]
d y = [ 0 − 1 1 0 ] dy = \left[ \begin{matrix} 0 & -1\\ 1 & 0 \\ \end{matrix} \right] dy=[0110]

  • Prewitt算子
    Prewitt 算子是一种一阶微分算子的边缘检测,利用像素点上下、左右邻点的灰度差,在边缘处达到极值检测边缘,去掉部分伪边缘,对噪声具有平滑作用。Prewitt算子适合用来识别噪声较多、灰度渐变的图像。
    d x = [ 1 0 − 1 1 0 − 1 1 0 − 1 ] dx = \left[ \begin{matrix} 1 & 0 & -1\\ 1 & 0 & -1\\ 1 & 0 & -1\\ \end{matrix} \right] dx=111000111
    d y = [ − 1 − 1 − 1 0 0 0 1 1 1 ] dy = \left[ \begin{matrix} -1 & -1 & -1\\ 0 & 0 & 0\\ 1 & 1 & 1\\ \end{matrix} \right] dy=101101101

  • Sobel算子
    Sobel算子是一种用于边缘检测的离散微分算子,它结合了高斯平滑和微分求导。Sobel 算子在 Prewitt 算子的基础上增加了权重的概念,认为相邻点的距离远近对当前像素点的影响是不同的,距离越近的像素点对应当前像素的影响越大,从而实现图像锐化并突出边缘轮廓。
    d x = [ 1 0 − 1 2 0 − 2 1 0 − 1 ] dx = \left[ \begin{matrix} 1 & 0 & -1\\ 2 & 0 & -2\\ 1 & 0 & -1\\ \end{matrix} \right] dx=121000121
    d y = [ − 1 − 2 − 1 0 0 0 1 2 1 ] dy = \left[ \begin{matrix} -1 & -2 & -1\\ 0 & 0 & 0\\ 1 & 2 & 1\\ \end{matrix} \right] dy=101202101

图像梯度

∇ f = [ ∂ f ∂ x , ∂ f ∂ y ] \nabla f=[\frac{\partial f}{\partial x},\frac{\partial f}{\partial y}] f=[xf,yf]

  • 梯度指向强度增长最快的方向

  • 梯度的角度
    边的方向与梯度方向垂直
    θ = t a n − 1 ( ∂ f ∂ y / ∂ f ∂ x ) \theta = tan^{-1} (\frac{\partial f}{\partial y}/\frac{\partial f}{\partial x}) θ=tan1(yf/xf)

  • 梯度的模长(幅值)
    可以说明是边缘的可能性大小
    ∣ ∣ ∇ f ∣ ∣ = ( ∂ f ∂ x ) 2 + ( ∂ f ∂ y ) 2 ||\nabla f|| = \sqrt{(\frac{\partial f}{\partial x})^2+(\frac{\partial f}{\partial y})^2} f=(xf)2+(yf)2

  • 处理图像后:

高斯滤波器

当图像的像素存在大量噪点时,相邻的像素差异大,所求梯度也会偏大,无法提取边缘信息。

解决方案

  1. 平滑处理:使用平滑滤波器去噪,使图像信号变得平滑

  2. 再对处理后的信号求导,取极值

  3. 根据卷积的计算性质: d d x ( f ∗ g ) = f ∗ d d x g \frac{d}{dx}(f*g) = f*\frac{d}{dx}g dxd(fg)=fdxdg,先对平滑核求导,再进行卷积相乘来简化运算,减少运算量

高斯滤波器

高斯滤波器的导数

参数选择的越小则保留的细节越多

Candy 边缘检测

门限化

经过处理后,可以得到边缘图,但存在很多高频噪点,通过设置更高的门限,过滤噪点,使得到的边缘更“纯粹”

非最大化抑制

在通过高斯滤波后可以得到图像的大致轮廓线,由于图像的像素变换通常是缓慢改变的, 在处理后的图像中仍然存在大量的粗的“


方案

  1. 检查像素是否沿梯度方向为局部最大值,选择沿边缘宽度的最大值作为边缘
  2. 处理后

    经过上面的处理后,已经可以较为粗糙的得到图像的边缘图,但仍然存在问题,在有些部分的边 缘不连续,失去了很多信息如上图的 黄色区域 ,这是由于在门限化的过程中,设置过小,导致将需要的边缘滤除。

双门限法

  1. 先使用高门限将较粗的边检测出来,这些边都是比较鲁棒的,是噪声的可能性极低
  2. 再降低门限,将较细的边显现出来
  3. 将与高门限过滤出的边连接的低门限边保留,滤除没有连接的(不连续的)噪声

  1. 处理后可以得到更好的边缘效果

学习资源:北京邮电大学计算机视觉——鲁鹏

<think>好的,我现在要解决用户的问题,关于如何在工具中实现阈值分割和边缘检测,以及相关的替代方法和库推荐。首先,我需要回忆一下用户提到的引用内容,看看有没有相关的信息可以引用。用户提供了五个引用,其中引用[1]提到了传统图像处理方法,包括边缘检测和颜色分割,这应该和边缘检测以及阈值分割相关。引用[3]提到Harris角点检测,属于特征检测,可能和边缘检测有关联。引用[4]提到轮廓检测的方法,这可能和边缘检测后的处理步骤有关,比如轮廓分组或活动轮廓模型。 接下来,我需要整理阈值分割和边缘检测的基本概念和常用方法。阈值分割包括全局阈值、自适应阈值、Otsu方法等。边缘检测常用Sobel、Canny、Laplacian等算法。用户可能想知道如何在Python中实现这些,特别是使用OpenCV和skimage库,因为引用[1]中提到了这两个库。 然后,我需要考虑代码示例。例如,使用OpenCV的cv2.threshold进行阈值分割,cv2.Canny进行边缘检测。同时,skimage库也有相应的函数,比如skimage.filters.threshold_otsu,或者skimage.feature.canny。可能还需要提到替代方法,比如引用[3]中的Harris角点检测,虽然主要用于角点,但也可以作为边缘检测的补充。 另外,用户可能对优化方法或替代方案感兴趣,比如引用[2]中的特征选择方法,虽然主要用于机器学习,但可能在图像处理中特征提取后有用。引用[5]提到的区域推荐和语义分割可能涉及到更高级的方法,如深度学习,但用户目前可能更关注传统方法。 需要注意用户的问题中提到“阈值分类(threshold classification)”,这可能是指阈值分割后进行分类,或者可能是一个术语混淆,需要确认正确的术语是阈值分割(threshold segmentation)。在回答中应明确这一点,避免误解。 还需要检查引用是否正确。例如,引用[1]提到传统方法包括边缘检测和颜色分割,所以可以用于支持阈值分割和边缘检测的应用。引用[4]关于轮廓检测的方法,可以关联到边缘检测后的轮廓处理步骤。 最后,生成相关问题时要围绕阈值分割和边缘检测的应用、优化、比较等方向提问,比如替代方法、参数调优、与传统方法的比较等。</think>### 阈值分割与边缘检测实现方法 #### 一、阈值分割(Threshold Segmentation) 阈值分割是通过设定灰度阈值将图像分为前景和背景。常用方法及实现如下: 1. **全局阈值** ```python import cv2 img = cv2.imread('image.jpg', 0) # 读取灰度图 _, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 手动设定阈值127 ``` 2. **自适应阈值**(适合光照不均图像) ```python adaptive = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) ``` 3. **Otsu算法**(自动计算最优阈值)[^1] ```python from skimage.filters import threshold_otsu thresh = threshold_otsu(img) binary = img > thresh ``` #### 二、边缘检测Edge Detection边缘检测通过梯度变化定位物体边界,常用方法包括: 1. **Canny边缘检测**(多阶段优化算法) ```python edges = cv2.Canny(img, threshold1=100, threshold2=200) # 双阈值控制 ``` 2. **Sobel算子**(方向性边缘检测) ```python sobel_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) sobel_y = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) edges = np.sqrt(sobel_x**2 + sobel_y**2) ``` 3. **Laplacian算子**(二阶导数检测) ```python laplacian = cv2.Laplacian(img, cv2.CV_64F) #### 三、替代方法与库推荐 1. **替代方法** - **轮廓检测**:结合边缘检测结果提取物体轮廓(`cv2.findContours`)[^4] - **区域分割**:如分水岭算法(`cv2.watershed`) - **角点检测**:如Harris角点检测(`cv2.cornerHarris`)[^3] 2. **推荐工具库** - **OpenCV**:提供完整的图像处理函数链 - **scikit-image**:支持更灵活的阈值算法(如`threshold_multiotsu`) - **Matplotlib**:可视化中间结果(如梯度图、直方图) #### 四、参数调优与效果对比 - **阈值分割**:通过直方图分析(`plt.hist(img.ravel(), 256)`)观察灰度分布选择阈值 - **Canny检测**:调整`threshold1`和`threshold2`平衡噪声抑制与边缘连续性 - **性能优化**:使用高斯滤波预处理(`cv2.GaussianBlur`)减少噪声干扰 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值