一、定义
图像边缘检测 即 寻找图像目标的轮廓
二、图像的梯度与卷积介绍
1、数字图像表示——矩阵
2、数学中的梯度含义
函数的一维梯度——求导:of(x)/ox
函数的多维梯度——求导:of(x)/ox、of(y)/oy
3、数字图像的梯度近似——差分
差分近似梯度:
Gx=f[i,j+1]-f[i,j] Gy=f[i,j]-f[i+1,j]
(注意y轴方向是小 - 大)
5的水平梯度转化为差分:4 - 5 = -1
5的垂直梯度转化为差分:5 - 9 = -4
4、梯度的两个性质——大小与方向
记 Gx=of(x)/ox, Gy=of(y)/oy
大小:欧式距离——(Gx2+Gy2)1/2 棋盘距离——|Gx|+|Gy|
方向:arctan(Gy/Gx)
5、图像的卷积
-
输入的图像矩阵:
-
使用的卷积模板:
-
用卷积模板对5进行卷积,则卷积模板对应的元素为蓝色框
卷积计算的结果为:0*5+(-1)*4+*9+0*10=5
三、实现算子
一阶差分:Roberts算子、Prewitt算子、Sobel算子
二阶差分:拉普拉斯算子、高斯-拉普拉斯算子(LoG)、Canny算子
四、算子原理介绍
Roberts算子——交叉梯度
-
卷积模板(Gx,Gy)
-
检测方向
135°和45°
Prewitt算子
-
卷积模板(Gx,Gy)
-
检测方向
0°和90°
Sobel算子
-
卷积模板(Gx,Gy)
-
检测方向
0°和90°
拉普拉斯算子——两种模板
-
卷积模板(Gx与Gy合并)
-
梯度幅值——欧式距离 (Gx2+Gy2)1/2
Gx=f[i,j+1]-f[i,j]+f[i,j-1]-f[i,j]
Gy=f[i+1,j]-f[i,j]+f[i-1,j]-f[i,j] -
考虑对角线的卷积模板(Gx与Gy合并+两对角线模型)
-
梯度幅值——欧式距离 (Gx2+Gy2)1/2
高斯-拉普拉斯算子(LoG)
对 拉普拉斯算子 加 高斯函数 处理——如下图
Canny算子——使用最广泛
1、算法步骤
- 高斯平滑
- 计算一阶差分Gx与Gy
- 计算梯度幅值与方向
- 非极大值抑制
- 双阈值挑选边缘点
2、如何实现非极大值抑制?
- 模块梯度方向分为4个,垂直,水平,正对角线,副对角线
- 模块梯度方向离散化
-22.5~22.5为0
22.5~67.5 为1
67.5~112.5 为2
112.5~157为3
以此类推
0代表水平,1代表副对角,2代表垂直,3代表正对角 - 梯度方向两边比较
p大于自身梯度方向两邻点的梯度,则保留,否则去除;
3、如何实现双阈值挑选边缘点?
- 设置两个阈值,一个高阈值,一个低阈值
- 根据高阈值的边缘点梯度方向,进行边缘连接,找不到点去低阈值找
- 从高阈值对应的点到低阈值图像的8领域找,找到就将其选为边缘点
四、基础实验——单独实现每个算子
matlab函数介绍
所使用到的matlab中edge()函数介绍
% roberts算子
BW = edge(I,'roberts')
BW = edge(I,'roberts',THRESH)
BW = edge(I,'roberts',THRESH,DIRECTION)
BW = edge(I,'roberts',THRESH,DIRECTION,OPTIONS)
[BW,thresh] = edge(I,'roberts',...)
THRESH表示梯度幅值大于全局的多少为边缘监测点
DIRECTION可取'horizontal'、'vertical'、'both'表示45°,135°,以及两者综合
OPTIONS可取'nothinning'、'thinning'表示不使用边缘细化,使用边缘细化
[BW,thresh]形式还会返回系统自动选择的阈值
%prewitt算子
BW = edge(I,'prewitt')
BW = edge(I,'prewitt',THRESH)
BW = edge(I,'prewitt',THRESH,DIRECTION)
BW = edge(I,'prewitt',THRESH,DIRECTION,OPTIONS)
[BW,thresh] = edge(I,'prewitt',...)
DIRECTION可取'horizontal'、'vertical'、'both'表示0°,90°,以及两者综合
%sobel算子
BW = edge(I,'sobel')
BW = edge(I,'sobel',THRESH)
BW = edge(I,'sobel',THRESH,DIRECTION)
BW = edge(I,'sobel',THRESH,DIRECTION,OPTIONS)
[BW,thresh] = edge(I,'sobel',...)
DIRECTION可取'horizontal'、'vertical'、'both'表示0°,90°,以及两者综合
%LoG算子
BW = edge(I,'log')
BW = edge(I,'log',THRESH)
BW = edge(I,'log',THRESH,SIGMA)
[BW,thresh] = edge(I,'log',...)
SIGMA表示高斯函数所取的标准差
%canny算子
BW = edge(I,'canny')
BW = edge(I,'canny',THRESH)
BW = edge(I,'canny',THRESH,SIGMA)
[BW,thresh] = edge(I,'canny',...)
SIGMA表示高斯函数所取的标准差
1、 一阶差分算子——三种一阶差分算子的检测差别
- 代码
% 1、图片读取与显示
lena=imread('lena.png');
subplot(2,2,1),imshow(lena),title('原图像');
% 2、roberts算子边缘检测
roberts=edge(lena,'roberts');
subplot(2,2,2),imshow(roberts),title('roberts边缘检测');
% 3、prewitt算子边缘检测
prewitt=edge(lena,'prewitt');
subplot(2,2,3),imshow(prewitt),title('prewitt边缘检测');
% 4、sobel算子边缘检测
sobel=edge(lena,'sobel');
subplot(2,2,4),imshow(sobel),title('Sobel边缘检测');
- 结果
- 结论
①roberts检测的是图像45°和135°的综合特征,就图像本身的45°和135°的边缘线会更加清晰,但水平和垂直边缘检测效果断断续续。
②prewitt检测的是图像0°和90°的综合特征,就图像本身更多的边缘是在水平和垂直方向的,所以得到的边缘检测结果会比roberts稍好一些。
③sobel检测的也是图像0°和90°的综合特征,但是相交prewitt加入了中心权重,我们可以看到眼睛的边缘会得到较好的边缘检测,即眼睛中心位置边缘更加突出,这是其他两个算子没有实现的。
2、LoG算子——不同SIGMA下的结果
- 代码
% 1、图片读取与显示
lena=imread('lena.png');
subplot(2,2,1),imshow(lena),title('原图像');
% 2、LoG算子边缘检测 方差为1——阈值统一取0.03
LoG_1=edge(lena,'log',0.03,1);
subplot(2,2,2),imshow(LoG_1),title('LoG边缘检测 方差为1');
% 3、LoG算子边缘检测 方差为0.5——阈值统一取0.03
LoG_05=edge(lena,'log',0.03,0.9);
subplot(2,2,3),imshow(LoG_05),title('LoG边缘检测 方差为0.9');
% 4、LoG算子边缘检测 方差为0.1——阈值统一取0.03
LoG_01=edge(lena,'log',0.03,0.8);
subplot(2,2,4),imshow(LoG_01),title('LoG边缘检测 方差为0.8');
- 结果
- 结论
随着高斯函数方差的越来越小,算子对图像的边缘提出的效果越来越差,提取到的边缘信息越来越模糊。
3、Canny算子——不同THRESH下的结果
- 代码
% 1、图片读取与显示
lena=imread('lena.png');
subplot(2,2,1),imshow(lena),title('原图像');
% 2、canny算子边缘检测 阈值为0.1
canny_01=edge(lena,'canny',0.1);
subplot(2,2,2),imshow(canny_01),title('canny边缘检测 阈值为0.1');
% 3、canny算子边缘检测 阈值为0.2
canny_02=edge(lena,'canny',0.2);
subplot(2,2,3),imshow(canny_02),title('canny边缘检测 阈值为0.2');
% 4、canny算子边缘检测 阈值为0.3
canny_03=edge(lena,'canny',0.3);
subplot(2,2,4),imshow(canny_03),title('canny边缘检测 阈值为0.3');
-
结果
-
结论
随着阈值的不断增大,边缘检测出来的点越来越少,边缘越来越细致。
五、综合实验——高斯抗噪能力
1、五种算子在原图像的检测能力
% 1、图片读取与显示
lena=imread('lena.png');
subplot(3,3,1),imshow(lena),title('原图像');
% 3、roberts算子边缘检测
roberts=edge(lena,'roberts');
subplot(3,3,4),imshow(roberts),title('roberts边缘检测');
% 4、prewitt算子边缘检测
prewitt=edge(lena,'prewitt');
subplot(3,3,5),imshow(prewitt),title('prewitt边缘检测');
% 5、sobel算子边缘检测
sobel=edge(lena,'sobel');
subplot(3,3,6),imshow(sobel),title('Sobel边缘检测');
% 6、LoG算子边缘检测——方差取1,阈值取0.03
LoG=edge(lena,'log',0.03,1);
subplot(3,3,7),imshow(LoG),title('LoG边缘检测');
% 7、canny算子边缘检测——阈值取0.3
canny=edge(lena,'canny',0.3);
subplot(3,3,8),imshow(canny),title('canny边缘检测');
2、五种算子在加噪声下的检测能力
% 1、图片读取与显示
lena=imread('lena.png');
subplot(3,3,1),imshow(lena),title('原图像');
% 2、对图像添加高斯噪声——方差默认0.2
lena=imnoise(lena,'gaussian',0.2);
subplot(3,3,1),imshow(lena),title('噪声图像');
% 3、roberts算子边缘检测
roberts=edge(lena,'roberts');
subplot(3,3,4),imshow(roberts),title('roberts边缘检测');
% 4、prewitt算子边缘检测
prewitt=edge(lena,'prewitt');
subplot(3,3,5),imshow(prewitt),title('prewitt边缘检测');
% 5、sobel算子边缘检测
sobel=edge(lena,'sobel');
subplot(3,3,6),imshow(sobel),title('Sobel边缘检测');
% 6、LoG算子边缘检测——方差取1,阈值取0.03
LoG=edge(lena,'log',0.03,1);
subplot(3,3,7),imshow(LoG),title('LoG边缘检测');
% 7、canny算子边缘检测——阈值取0.3
canny=edge(lena,'canny',0.3);
subplot(3,3,8),imshow(canny),title('canny边缘检测');
3、抗噪结论
算子 | 抗噪能力 |
---|---|
Roberts | 对噪声敏感 |
Prewitt | 具有一定的抗噪能力 |
Sobel | 具有一定的抗噪能力 |
LoG | 对噪声敏感 |
Canny | 具有很好的抗噪能力 |
六、实验收获
-
一阶差分与二阶差分相比的优势?
一阶差分计算成本更低,抗噪能力更强 -
那为什么提出二阶差分?
因为一阶差分检测出来的边缘点太多,可以通过第二次求导选择局部最大值为边缘点 -
为什么LoG梯度检测算子的处理结果不需要像Prewitt 等算子那样进行幅度组合?
因为LoG计算的模块元素没有冲突,可以直接整合为一个大的卷积模块 -
实验中所使用的五种算子所得到的边缘有什么异同?
算子 | 解释 |
---|---|
Roberts | 边缘定位准,但是对噪声敏感,适用于边缘明显且噪声较少的图像分割,其利用局部差分算子寻找边缘,处理得到的边缘不是很平滑,因为其在边缘处会有较宽的响应。因此,对其作边缘检测处理后,通常需要增加细化处理,进行更为准确的定位; |
Prewitt | 对噪声有抑制作用,抑制噪声的原理是通过像素平均,但是这样会导致边缘定位不够准确; |
Sobel | 对噪声有抑制作用,抑制噪声的原理是通过像素平均,但是这样会导致边缘定位不够准确;另外,该算子认为不同程度距离的像素对当前像素具有不同的影响,而Prewitt算子则未考虑; |
LoG | 使用二阶导数对图像作边缘处理,但因其对噪声敏感,所以通常需要对图像先作降噪处理,处理后得到的边缘平滑且可以降低计算二阶导数引起的噪声影响; |
Canny | 对噪声有抑制作用,抑制噪声的原理是通过对图像进行高斯平滑,并且考虑了多个方向上的梯度计算,通过双阈值进行边缘点的挑选,使边缘更加流畅; |