标签:
最后来看看canny算子,这个是被成为最好的算子,因为过程多,有准测,后面会列出来,也是边缘检测的最后一个,所以这里作为结尾,来看看各个边缘检测的效果。
边缘检测结果比较
canny对边缘检测质量进行分析时,有3个原则:
canny边缘检测的基本思想是:首先对图像选择一定的Gauss滤波器进行平滑滤波,然后采用非极值抑制技术进行处理得到最后的边缘图像。
具体步骤:
1、用高斯滤波器平滑图像
对图像进行高斯滤波,听起来很玄乎,其实就是根据待滤波的像素点及其邻域点的灰度值按照一定的参数规则进行加权平均。这样可以有效滤去理想图像中叠加的高频噪声。
2、用一阶偏导的有限差分来计算梯度的幅值和方向
图像灰度值得梯度可使用一阶有限差分来进行近似,这样就可以得图像在x和y方向上偏导数的两个矩阵。常用的梯度算子就是Roberts.sobel,prewitt.,canny
3、对梯度幅值进行非极大值抑制
图像梯度幅值矩阵中的元素值越大,说明图像中该点的梯度值越大,但这不不能说明该点就是边缘(这仅仅是属于图像增强的过程)。在Canny算法中,非极大值抑制是进行边缘检测的重要步骤,通俗意义上是指寻找像素点局部最大值,将非极大值点所对应的灰度值置为0,这样可以剔除掉一大部分非边缘的点
4、用双阈值算法检测和连接边缘
Canny算法中减少假边缘数量的方法是采用双阈值法。选择两个阈值(关于阈值的选取方法在扩展中进行讨论),根据高阈值得到一个边缘图像,这样一个图像含有很少的假边缘,但是由于阈值较高,产生的图像边缘可能不闭合,未解决这样一个问题采用了另外一个低阈值。
通俗的来说:就是在进行边缘检测时,还是要用到滤波减小噪声,先通过在水平和垂直方向的一阶偏导,求得梯度的幅值和方向,这样每个点都可能有4中方向情况(0,45,90,135度),在局部范围内,保留在同一方向上,梯度最大的点,非最大就置零,最后使用2个阈值T1和T2(T1<T2),T2用来找到每条线段,T1用来在这些线段的两个方向上延伸寻找边缘的断裂处,并连接这些边缘。
<span style="font-size:18px;">C++: void Canny(InputArray image,OutputArray edges, double threshold1, double threshold2, int apertureSize=3,bool L2gradient=false ) </span>
<span style="font-size:18px;">#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <stdlib.h> #include <stdio.h> #include <iostream> using namespace cv; using namespace std; Mat src, src_gray; Mat dst, detected_edges; int edgeThresh = 1; int lowThreshold; int const max_lowThreshold = 100; int ratio = 3; int kernel_size = 3; const char* window_name = "Edge Map"; static void CannyThreshold(int, void*) { Canny( src_gray, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size ); dst = Scalar::all(0); src.copyTo( dst, detected_edges); imshow( window_name, dst ); } int main( int, char** argv ) { src = imread("D:\\lena.jpg",CV_LOAD_IMAGE_COLOR); if( !src.data ) { return -1; } dst.create( src.size(), src.type() ); cvtColor( src, src_gray, CV_BGR2GRAY ); namedWindow( window_name, CV_WINDOW_AUTOSIZE ); createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold ); CannyThreshold(0, 0); waitKey(0); return 0; } </span>
matlab
<span style="font-size:18px;">I=imread('d:\lena.jpg'); I1=rgb2gray(I); img1=edge(I1,'canny',[0.03,0.08],3); subplot(121),imshow(I); subplot(122),imshow(img1)</span>
Opencv图像识别从零到精通(21)-----canny算子边缘检测
标签:
原文地址:http://blog.csdn.net/qq_20823641/article/details/52102589