Canny检测
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验二 opencv实现canny边缘检测
一、实验目的
1、了解如何在VC++6.0上安装与配置opencv
2、了解canny边缘检测的原理与opencv的实现
二、实验引言
边缘是一幅图像最重要的特征之一,图像边缘部分集中了图像的大部分信息。因此,边缘的确定对于图像场景的识别与理解非常重要;同时在图像分割中也有重要应用。可以利用边缘对图像进行区域分析。边缘在图像体现为局部区域亮度的显著变化,可见这种变化是为灰度面的阶跃。有很多种方法可以用来对图像边缘进行检测。本实验中采用Canny边缘检测。
三、实验原理
检测阶跃边缘的基本思想是在图像中找出具有局部最大梯度值的像素点,其大部分的工作集中在寻找能够用于实际图像的梯度数字逼近。
图像梯度逼近必须满足要求:
1、逼近必须能够抑制噪声效应
2、必须尽量精确的确定边缘的位置
Canny检测的基本过程
平滑与计算
Canny边缘检测器就是高斯函数的一阶导数,是对信噪比与定位之间最优化的逼近算子。高斯平滑和梯度逼近结合的算子不是旋转对称的。高斯平滑和梯度逼近结合的算子不是旋转对称的。
在边缘方向是对称的,在垂直边缘方向是反对称的(梯度方向)。该算子在对最急剧变化方向上的边缘很敏感,沿边缘方向不敏感。
非极大值抑制
前面的计算得到梯度的幅度图像阵列为M[i,j],此值的值越大,其对应的图像梯度值也越大。但还不能精确的确定边缘。为了确定边缘,必须细化幅度值图像中的屋脊带(ridge ),即只保留幅度值局部变化最大的点。此过程称为非极大值抑制(non-maxima suppression,NMS ),其结果会产生细化的边缘。非极大值抑制通过抑制梯度线上所有的非屋脊峰值的幅度值来细化[,]M i j 中的梯度幅值屋脊。算法使用一个3×3邻域作用在幅值阵列[,]M i j 的所有点上;每一个点上,邻域的中心像素[,]M i j 与沿着梯度线的两个元素进行比较,其中梯度线是由邻域的中心点处的扇区值ζ[i,j ]给出。如果在邻域中心点处的幅值[,]M i j 不比梯度线方向上的两个相邻点幅值大,则[,]M i j 赋值为零,否则维持原值;此过程可以把M[i,j]宽屋脊带细化成只有一个像素点宽,即保留屋脊的高度值。
非极大值抑制公式为:
[,]([,],[,])N i j N M S M i j i j z =
[,]N i j 中的非零值对应着图像强度阶跃变化处对比度,其坐标对应着图像梯度值经过非极大值抑制后细化得到的边缘。
虽然在边缘检测前经过了图像的高斯平滑,但是经过NMS 后仍然会包含许多噪声和细纹理引起的假边缘段。所以要经过阈值化处理。
阈值化
去除假边缘的方法是对[,]N i j 使用阈值处理,将低于某一阈值的所有值赋值零,得到图像边缘阵列[,]I i j 。
单阈值τ太低造成的假阳性以及阴影会使边缘对比度减弱; 单阈值t 太高造成的假阴性会使部分轮廓丢失; 常用双阈值1t 和212t t =对非极大值抑制图像[,]N i j 处理得到两个边
缘图像1[,]T i j 和2[,]T i j 。2[,]T i j 用高阈值得到,所以含有较少的假边缘,但其中有轮廓
的间断。双阈值要在2[,]T i j 中把边缘连接成轮廓,当到达轮廓端点时,就在1[,]T i j 的8邻
点位置寻找可以连接到轮廓上的边缘。综述整个算法的主要步骤是:不断的在1[,]T i j 中收
集边缘,直到2[,]T i j 中的所有间隙连接起来位置。
从而得出Canny 算法的具体实现步骤:
Step1:用高斯滤波器平滑图像,去除图像噪声。一般选择方差为1.4的高斯函数模板和图像进行卷积运算。
Step2:用一阶偏导的有限差分来计算梯度的幅值和方向。使用 的梯度算子计算x 和y 方向的偏导数 和 ,方向角 ,梯度幅值 。
Step3:对梯度幅值应用非极大值抑制。幅值M 越大,其对应的图像梯度值也越大,但这
还不足以确定边缘,因为这里仅把图像快速变化的问题转化成求幅值局部最大值问题,为确定边缘,必须细化幅值图像中的屋脊带,只保留幅值局部变化最大的点,生成细化的边缘。
Step4:用双阈值算法检测并且连接边缘。双阈值法使Canny算子提取的边缘点更具有鲁棒性,高低阈值分别表示为Hth和Lth,对于高阈值Hth的选折,基于计算出的图像梯度值对应的直方图进行选取。
三.实验过程
1、按手册正确安装VC++6.0和opencv1.0并对VC++6.0添加一系列库文件完成配置
2、在VC++6.0上添加工程,根据算法编写程序并执行。
3、运行并观察结果
四.程序流程图
五、实验结果
下面是第一个阈值始终为1,第二个阈值依次增大下检测出来的图像。可见阈值越大原图像中变化越不太显的部分渐渐消失,当阈值最大时剩下的就是图像中亮暗变化最明显的部分。
六、参考文献与资料
贾云得,机器视觉,科学出版社,2000
中国Opencv官网:/浏览时间:2011年5月29日
七、附录
代码:
#pragma package
#include "cv.h"
#include "highgui.h"
char wndname[] = "Canny边缘检测后图像";
char tbarname[] = "阀值";
int edge_thresh = 1;
IplImage *image, *cedge, *gray, *edge;
//编写函数实现Canny检测和图片的转存等一系列操作
void on_trackbar(int i)
{
cvSmooth(gray,edge,CV_BLUR,3,3,0,0); //CV_BLUR:对每个象素3×3邻域求和并做尺度变换1/(3.3).
cvCanny(gray,edge,(float)edge_thresh,(float)edge_thresh*3,3); // 做canny检测
cvZero( cedge ); //图像清零
cvCopy( image, cedge, edge ); //从image中复制edge部分到cedge
cvShowImage(wndname, cedge); //显示图片
}
int main()
{ //读图并判断
image = cvLoadImage("G:\\sex.BMP");
if (!image)
{
return -1;
}
cedge = cvCreateImage(cvSize(image->width,image->height), IPL_DEPTH_8U, 3); // 建立检测图像
gray = cvCreateImage(cvSize(image->width,image->height), IPL_DEPTH_8U, 1);
edge = cvCreateImage(cvSize(image->width,image->height), IPL_DEPTH_8U, 1);