图像变换 - Canny算子边缘检测(cvCanny)
来源:互联网 发布:网络出版许可证查询 编辑:程序博客网 时间:2024/06/10 12:38
John Canny于1986年提出Canny边缘检测算法。
John Canny研究了最优边缘检测方法所需的特性,给出了评价边缘检测性能优劣的三个指标:
1.好的信噪比,即将非边缘点判定为边缘点的概率要低,将边缘点判为非边缘点的概率要低;
2.高的定位性能,即检测出的边缘点要尽可能在实际边缘的中心;
3. 对单一边缘仅有唯一响应,即单个边缘产生多个响应的概率要低,并且虚假响应边缘应该得到最大抑制。
Canny算子求边缘点具体算法步骤如下:
1. 用高斯滤波器平滑图像;
2. 用一阶偏导有限差分计算梯度幅值和方向;
3. 对梯度幅值进行非极大值抑制;
4. 用双阈值算法检测和连接边缘。
在opencv里面提供了cvCanny函数来求canny算子,该算法没有进行高斯平滑图像。首先在x和y方向求一阶导数,使用sobel算子,核的大小由用户输入(可以是3、5、7),然后组合成为4个方向的导数,分别判断相应方向上是否为极大值。这些方向导数达到局部最大值的点就是边缘的候选点。Canny算法最重要的一个新特点是试图将独立边的候选像素拼装成轮廓。轮廓的形成是对这些像素运用滞后性阈值。这意味着有两个阈值,上限和下限。如果一个像素的梯度大于上限阈值,则被认为是边缘像素,如果低于下限阈值,则被抛弃,如果介于二者之间,只有当其与高于上限阈值的像素连接时才会被接受。Canny推荐的上下限阈值比为2:1到3:1之间。具体算法如下:
1、使用sobel算子求每个像素x和y方向的梯度;
2、求每个像素的方向。若|dy|< |dx|*tan22.5,则认为是x方向;若|dy|>|dx|*tan67.5,则认为是y方向;若|dx|*tan67.5>|dy|> |dx|*tan22.5,且dx和dy同方向,则认为是45°方向;若|dx|*tan67.5>|dy|> |dx|*tan22.5,且dx和dy反方向,则认为是135°方向。
3、求幅值,有两种算法,一种是|dx|+|dy|,另一种是squr(|dx|^2+|dy|^2);
4、非极大值抑制。以x方向为例,对a进行非极大值抑制,若a的幅值同时大于a-1点和a+1点的幅值,则认为a点为极大值点,可能是边缘,因此保留;否则认为a点不是极大值点,不是边缘,因此该点的幅值重新赋值0;
5、双阈值算法检测。输入高阈值和低阈值,对整幅图像进行阈值检测,若该点的幅值大于高阈值,则该点为边缘点,该点的像素幅值255(以8位为例);若该点的幅值小于低阈值,则该点为非边缘点,该点的像素幅值0;小于高阈值而大于低阈值的点保留,该点有可能是边缘点,也有可能不是;
6、连接边缘。寻找每个大于高阈值的像素点,并判断周围8个像素点是否存在小于高阈值而大于低阈值的点,若是,则认为是边缘点,赋值255。如此循环,直到每一个高阈值点周围不存在小于高阈值而大于低阈值的点,则认为连接完成,最后对整幅图像进行扫描,除边缘部分为255外,其余赋值0。
Canny
void cvCanny( const CvArr* image,
CvArr* edges,
double threshold1,
double threshold2,
int aperture_size=3 );
单通道输入图像。
edges
单通道存储边缘的输出图像。
threshold1
第一个阈值。
threshold2
第二个阈值。
aperture_size
Sobel 算子内核大小 (见 cvSobel)。
函数 cvCanny 采用 CANNY 算法发现输入图像的边缘而且在输出图像中标识这些边缘。threshold1和threshold2 当中的小阈值用来控制边缘连接,大的阈值用来控制强边缘的初始分割。
注意事项:cvCanny只接受单通道图像作为输入。
/*code*/
#include <highgui.h>#include <cv.h>#include <cxcore.h> //人脸识别的一个库文件//Canny:Implements Canny algorithm for edge detection.int main( int argc, char** argv ){IplImage* src = NULL;IplImage* dst = NULL;//载入图像,转换为灰度图src = cvLoadImage( argv[1], 0 ); //为canny边缘图像申请空间,1表示单通道灰度图dst = cvCreateImage( cvGetSize( src ), IPL_DEPTH_8U, 1 ); cvCanny( src, dst, 50, 150, 3 );//边缘检测cvNamedWindow( "src", 1 );cvNamedWindow( "canny", 1 );cvShowImage( "src", src );cvShowImage( "canny", dst );cvWaitKey(0);cvReleaseImage( &src );cvReleaseImage( &dst );cvDestroyAllWindows();return 0;}
/*result*/
参考:http://blog.csdn.net/hitwengqi/article/details/6877864
参考:学习《OpenCV中文版》于仕琪 刘瑞祯 译
- 图像变换 - Canny算子边缘检测(cvCanny)
- 第六章 - 图像变换 - Canny算子边缘检测(cvCanny)
- 第六章 - 图像变换 - Canny算子边缘检测(cvCanny)
- 图像变换-用canny算子实现边缘检测
- cvCanny:Canny边缘检测
- canny边缘检测算子
- Canny边缘检测算子
- canny算子边缘检测
- Canny算子边缘检测
- Canny边缘检测算子
- 边缘检测:Canny算子
- 图像基本变换---Canny边缘检测算法
- 图像处理-Canny算子、Sobel算子边缘检测
- 边缘检测——cvCanny算子
- canny 算子检测图像边缘 C++程序问题探究
- Opencv对图像做边缘检测——canny算子
- opencv图像边缘检测Canny算子的总结分析
- Matlab图像边缘检测Roberts\Sobel\Prewitt\Canny算子
- C#泛型<T>说明
- 图像特征(转)
- 叶树:任总喊你回家吃饭 (zz)
- English job interview Q&A
- JDBC获得生成主键的方法
- 图像变换 - Canny算子边缘检测(cvCanny)
- 数据库表连接方式分析及常见用法
- XML
- C#餐厅管理系统6--呼叫管理员!
- ZOJ 1216 Deck
- linux下request_mem_region的粗略理解
- 开源爬虫Labin,Nutch,Neritrix介绍和对比
- 浅谈Java中的几种随机数
- SQL的join使用图解