文章目录
- 一、简介
- 1.边缘检测的概念
- 2.边缘检测的目的
- 二、代码实现
- 三、边缘检测的方法
- 1.1Canny边缘检测器
- 1.2.Canny代码实现
- 2.1Sobel边缘检测器
- 2.2Sobel代码实现
- 3.1Laplacian边缘检测器
- 3.2Laplacian代码实现
- 4.1Scharr边缘检测器
- 4.2Scharr代码实现
- 四、边缘检测的应用
一、简介
边缘检测是图像处理和计算机视觉中的一个基本问题,旨在标识数字图像中亮度变化明显的点,即检测图像中的边缘或不连续区域。这些边缘通常反映了图像中不同区域之间的边界或过渡区域,包含了物体的轮廓和结构信息。
1.边缘检测的概念
边缘检测是图像处理中的一个重要步骤,它通过检测图像中颜色、亮度或纹理的突然变化,提取出图像的边缘信息。这些边缘信息对于理解图像结构、提取重要特征以及进行目标识别、图像分割等后续处理至关重要。
2.边缘检测的目的
边缘检测的主要目的是捕捉图像中亮度急剧变化的区域,这些区域往往代表了图像中的重要信息,如物体的轮廓、纹理边界等。通过边缘检测,可以大幅度减少图像的数据量,并剔除不相关的信息,从而保留图像的重要结构属性。
二、代码实现
yuan = cv2.imread('yuan.png')
cv2.imshow('yuan',yuan)
cv2.waitKey(0)
# x方向上的边缘检测
yuan_x = cv2.Sobel(yuan,-1,dx=1,dy=0)
cv2.imshow('yuan_x',yuan_x)
cv2.waitKey(0)
x方向上的边缘检测:使用cv2.Sobel()函数进行x方向(水平方向)的边缘检测。-1表示输出图像与原图像相同的深度(但在这种情况下,如果原图像是8位无符号整数,输出可能会因为截断而丢失信息),dx=1和dy=0指定了x方向上的导数。显示x方向边缘检测的结果。
# x方向上的边缘,包括负数信息(右端),但显示不出来,因为范围是(0-255)
yuan_x_64 = cv2.Sobel(yuan,cv2.CV_64F,dx=1,dy=0)
cv2.imshow('yuan_x_64',yuan_x_64)
cv2.waitKey(0)
x方向边缘检测,保留负数信息:使用cv2.CV_64F作为输出图像的深度,这样可以保留边缘检测中的负数信息。
# x 方向的边缘,包括负数信息(右端),进行取绝对值操作,右端的负值信息可以显示
yuan_x_full = cv2.convertScaleAbs(yuan_x_64)
cv2.imshow('yuan_x_full',yuan_x_full)
cv2.waitKey(0)
取绝对值并显示x方向边缘:使用cv2.convertScaleAbs()函数将yuan_x_64中的所有值取绝对值,并转换为8位无符号整数以便显示。
# y方向上的边缘检测
yuan_y = cv2.Sobel(yuan,-1,dx=0,dy=1)
cv2.imshow('yuan_y',yuan_y)
cv2.waitKey(0)
# y方向上的边缘,包括负数信息(下端),但显示不出来,因为范围是(0-255)
yuan_y_64 = cv2.Sobel(yuan,cv2.CV_64F,dx=0,dy=1)
yuan_y_full = cv2.convertScaleAbs(yuan_y_64)
cv2.imshow('yuan_y_64',yuan_y_64)
cv2.imshow('yuan_y_full',yuan_y_full)
cv2.waitKey(0)
y方向上的边缘检测:与x方向类似,但使用dy=1进行y方向(垂直方向)的边缘检测。
# x,y方向上的边缘检测
yuan_xy = cv2.Sobel(yuan,-1,dx=1,dy=1)
cv2.imshow('yuan_xy',yuan_xy)
cv2.waitKey(0)
# 使用图像加权运算组合x和y方向的2个边缘
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)
x,y方向上的边缘检测(结合):使用cv2.addWeighted()函数将x和y方向上的边缘检测结果进行加权组合。这里两个方向的权重都是1,意味着它们被等权重地组合在一起。
三、边缘检测的方法
边缘检测的方法多种多样,但大体上可以分为基于查找和基于零穿越的两类。基于查找的方法通过寻找图像一阶导数中的最大和最小值来检测边界,而基于零穿越的方法则通过寻找图像二阶导数零穿越来寻找边界。以下是一些常用的边缘检测算法:
1.1Canny边缘检测器
Canny算法是一种多级边缘检测算法,它首先使用高斯滤波器平滑图像以减少噪声,然后计算图像的梯度幅度和方向,接着通过非极大值抑制来细化边缘,并使用双阈值检测和边缘连接来最终确定边缘。Canny算法被认为是边缘检测的标准算法之一,因为它能够检测到良好的边缘并且错误率较低。
1.2.Canny代码实现
jijia = cv2.imread('2.png',cv2.IMREAD_GRAYSCALE)
cv2.imshow('jijia',jijia)
cv2.waitKey(0)
jijia_canny = cv2.Canny(jijia,100,150)
cv2.imshow('jijia_canny',jijia_canny)
cv2.waitKey(0)
使用cv2.Canny()函数对灰度图像jijia进行边缘检测。Canny边缘检测是一种流行的边缘检测算法,它使用两个阈值(在这里是100和150)来检测图像中的强边缘和弱边缘,并通过连接这些边缘来形成连续的边界。
第一个阈值(100)是较低的阈值,用于检测边缘的初步候选。
第二个阈值(150)是较高的阈值,用于检测确定的边缘。
边缘检测算法会首先使用较低的阈值找到尽可能多的边缘,然后使用较高的阈值来找到其中的强边缘。最后,它会根据强边缘来连接弱边缘,从而生成最终的边缘图像。
2.1Sobel边缘检测器
Sobel算法使用两个3x3的卷积核(一个用于检测水平边缘,另一个用于检测垂直边缘)来估计图像的一阶导数。然后,通过计算这些导数的平方和的平方根来得到每个像素的边缘强度。Sobel算法对噪声有一定的平滑作用,但可能会检测到一些非边缘的像素点。
2.2Sobel代码实现
jijia = cv2.imread('2.png',cv2.IMREAD_GRAYSCALE)
jijia_x_64= cv2.Sobel(jijia,cv2.CV_64F,dx=1,dy=0)
jijia_x_full = cv2.convertScaleAbs(jijia_x_64)
jijia_y_64 = cv2.Sobel(jijia,cv2.CV_64F,dx=0,dy=1)
jijia_y_full = cv2.convertScaleAbs(jijia_y_64)
jijia_xy_sobel_full = cv2.addWeighted(jijia_x_full,1,jijia_y_full,1,0)
cv2.imshow('jijia_xy_sobel_full',jijia_xy_sobel_full)
cv2.waitKey(0)
使用Sobel算子在x、y方向上进行边缘检测 ,这里设置dx, dy表示检测该方向方向上的边缘。将边缘检测的结果转换为8位无符号整数图像。使用加权和将x方向和y方向上的边缘检测结果进行组合 ,显示组合后的边缘图像 。
3.1Laplacian边缘检测器
LoG算法首先使用高斯滤波器对图像进行平滑处理,然后计算图像的拉普拉斯算子(二阶导数)。由于拉普拉斯算子对边缘敏感,因此可以通过检测拉普拉斯算子的零交叉点来找到边缘。LoG算法能够检测到较细的边缘,并且对噪声有一定的抑制作用。
3.2Laplacian代码实现
jijia = cv2.imread('2.png',cv2.IMREAD_GRAYSCALE)
jijia_lap = cv2.Laplacian(jijia,cv2.CV_64F)
jijia_lap_full = cv2.convertScaleAbs(jijia_lap)
cv2.imshow('jijia_lap_full',jijia_lap_full)
cv2.waitKey(0)
使用Laplacian算子进行边缘检测,cv2.Laplacian 函数需要两个参数:源图像和输出图像的深度,这里设置输出图像的深度为cv2.CV_64F,即64位浮点数,将Laplacian算子的结果转换为8位无符号整数图像以便显示,显示转换后的边缘图像。
4.1Scharr边缘检测器
Scharr算子与Sobel算子类似,但它在计算梯度时使用了不同的系数。Scharr算子对于检测边缘更加敏感,因此在某些情况下可能会得到更清晰的边缘结果。
4.2Scharr代码实现
jijia = cv2.imread('2.png',cv2.IMREAD_GRAYSCALE)
jijia_x_64 = cv2.Scharr(jijia,cv2.CV_64F,dx=1,dy=0)
jijia_x_full = cv2.convertScaleAbs(jijia_x_64)
jijia_y_64 = cv2.Scharr(jijia,cv2.CV_64F,dx=0,dy=1)
jijia_y_full = cv2.convertScaleAbs(jijia_y_64)
jijia_xy_Scharr_full = cv2.addWeighted(jijia_y_full,1,jijia_y_full,1,0)
cv2.imshow('jijia_xy_Scharr_full',jijia_xy_Scharr_full)
cv2.waitKey(0)
使用Scharr算子在x,y方向上进行边缘检测,Scharr算子通常比Sobel算子提供更精确的边缘检测结果 。将边缘检测的结果转换为8位无符号整数图像以便显示,使用加权和将x方向和y方向上的边缘检测结果进行组合,显示组合后的边缘图像。
四、边缘检测的应用
边缘检测在图像处理、计算机视觉和机器视觉等领域具有广泛的应用。以下是一些典型的应用场景:
- 目标检测与识别:通过边缘检测可以提取出图像中物体的轮廓和形状信息,从而实现目标的检测和识别。
- 图像分割:边缘检测是图像分割的重要步骤之一,通过检测图像中的边缘可以将图像划分为不同的区域或对象。
- 图像增强:边缘检测可以用于图像增强处理,通过突出图像中的边缘信息使图像更加清晰和易于理解。
- 视频分析:在视频分析中,边缘检测可以用于目标的跟踪和运动分析等任务。
总之,边缘检测是图像处理和计算机视觉中的一个重要环节,它通过检测图像中的边缘信息为后续的图像处理和分析提供了重要的基础。随着技术的不断发展,边缘检测算法也在不断演进和完善以满足各种应用场景的需求。