图像边缘检测
目录
一.图像边缘检测
1.图像边缘检测概述
2.Sobel算子原理与实现
3.Scharr算子
4.Laplacian算子
5.Canny边缘检测(重点)
6.效果对比
一.图像边缘检测
1.图像边缘检测概述
2.Sobel算子原理与实现
代码是实现步骤:
- 边缘检测是图像处理和计算机视觉中的重要工具,用于检测数字图像中的明显变化、边缘或不连续区域。
- 主要方法包括:Sobel算子、scharr算子,Laplacian算子、Canny算子等。
- Sobel算子结合高斯平滑和微分求导,通过局部差分计算梯度近似值。
- 包含两组3x3矩阵(横向和纵向模板),分别用于水平和垂直方向的边缘检测。
- 横向检测:用右边像素值减去左边像素值;纵向检测:用下方像素值减去上方像素值。
- 检测时需分步进行(先横向后纵向),避免同时设置
dx=1
和dy=1
导致结果不理想(线条过细且存在空洞)。 - 横向检测:
- 使用
cv2.Sobel()
,设置dx=1
、dy=0
,数据类型为cv2.CV_64F
以保存负数梯度值。 - 对结果取绝对值(
cv2.convertScaleAbs
)将负数转为正数显示。
- 使用
- 纵向检测:
- 设置
dx=0
、dy=1
,同样使用cv2.CV_64F
并取绝对值。
- 设置
- 融合结果:通过图像加权融合(
cv2.addWeighted
)将横向和纵向检测结果合并,填补空洞。
import cv2
#1.sobel算子
yuan=cv2.imread('img.png',0)
cv2.imshow('yuan',yuan)
cv2.waitKey(0)
#x方向上的边缘
yuan_x=cv2.Sobel(yuan,-1,dx=1,dy=0)#信息范围(0~255)
cv2.imshow('yuan_x',yuan_x)
cv2.waitKey(0)
yuan_x_64=cv2.Sobel(yuan,cv2.CV_64F,dx=1,dy=0)#信息范围(-1020~1020)
cv2.imshow('yuan_x_64',yuan_x_64)
cv2.waitKey(0)
#x方向上的边缘含负数信息无法显示,所以进行取绝对值操作
yuan_x_full=cv2.convertScaleAbs(yuan_x_64)
cv2.imshow('yuan_x_full',yuan_x_full)
cv2.waitKey(0)
#y方向上的边缘
yuan_y_64=cv2.Sobel(yuan,cv2.CV_64F,dx=0,dy=1)#信息范围(-1020~1020)
cv2.imshow('yuan_y_64',yuan_y_64)
cv2.waitKey(0)
yuan_y_full=cv2.convertScaleAbs(yuan_y_64)
cv2.imshow('yuan_y_full',yuan_y_full)
cv2.waitKey(0)
#图像加权运算组合
yuan_xy_full=cv2.addWeighted(yuan_x_full,1,yuan_y_full,1,0)
cv2.imshow('yuan_xy_full',yuan_xy_full)
cv2.waitKey(0)
cv2.destroyAllWindows()
注意事项:
- 输入图像需先转换为灰度图。
- 避免直接使用
unit8
数据类型(会丢失负数梯度信息),推荐使用cv2.CV_64F
。 - 分步检测后融合的效果优于同时设置
dx=1
和dy=1
。
3.Scharr算子
- 改进:中心权重更大(中间为10,四角为3),精度更高,但线条更密集(可能包含更多伪边缘)。
- 代码实现:仅需将Sobel算子中的
cv2.Sobel
改为cv2.Scharr
。
#2.scharr算子
img=cv2.imread('img.png',0)
cv2.imshow('img',img)
cv2.waitKey(0)
img_x_64 = cv2.Scharr(img,cv2.CV_64F,dx=1,dy=0)
img_x_full=cv2.convertScaleAbs(img_x_64)
img_y_64 = cv2.Scharr(img,cv2.CV_64F,dx=0,dy=1)
img_y_full=cv2.convertScaleAbs(img_y_64)
img_xy_full=cv2.addWeighted(img_x_full,1,img_y_full,1,0)
cv2.imshow('img_xy_full',img_xy_full)
cv2.waitKey(0)
4.Laplacian算子
- 特点:不区分方向(直接计算变化率),卷积核中心为-4,四周为1,无需分步融合。
- 代码:
cv2.Laplacian
+ 取绝对值,步骤更简单,但效果较粗糙(线条断续、颜色淡)。img=cv2.imread('img.png',0) img_lap=cv2.Laplacian(img,cv2.CV_64F) img_lap_full=cv2.convertScaleAbs(img_lap) cv2.imshow('img_lap_full',img_lap_full) cv2.waitKey(0)
5.Canny边缘检测(重点)
- 原理:
- 高斯降噪:去除噪声干扰。
- 梯度计算:通过Sobel算子计算梯度幅值和方向(像素变化最剧烈的方向)。
- 非极大值抑制:保留梯度方向上最亮的点,抑制其他点。
- 双阈值筛选:
- 高阈值(如150):强边缘(保留)。
- 低阈值(如100):弱边缘(若与强边缘连接则保留,否则剔除)。
- 代码实现
#4.canny算子 img=cv2.imread('img.png',0) img_canny=cv2.Canny(img,120,180) img_canny_full=cv2.convertScaleAbs(img_canny) cv2.imshow('img_canny_full',img_canny_full) cv2.waitKey(0) cv2.destroyAllWindows()
- 优势
边缘更细、更真实(避免伪边缘)。
背景干净(纯黑),仅保留显著轮廓。
- 参数调整:阈值过高可能导致边缘断裂,过低则噪声增多。
6.效果对比
- Sobel/Scharr:检测较多细节(如花纹),但可能包含非边缘信息。
- Laplacian:线条较淡,连续性差。
- Canny:仅保留强边缘(如人物轮廓),背景纯净,适合