opencv笔记(4):边缘检测

来源:互联网 发布:淘宝上小提琴教学视频 编辑:程序博客网 时间:2024/06/12 00:28

五、边缘检测

边缘检测的一般步骤:滤波--->增强--->检测。
边缘检测的主要算子和滤波器有:Canny算子、Soble算子、Laplace算子和Scharr滤波器。

滤波:边缘检测的算法主要是基于图像强度的一阶和二阶导数,但是导数对噪声很敏感,所以需要采用滤波来改善和噪声有关的边缘检测器的性能。主要的滤波为高斯滤波。
增强:增强边缘的基础是确定图像各点领域强度的变化值。增强算法可以将图像领域强度值有明显变化的点突显出来。其可以通过计算梯度幅度值来确定。
检测:经过增强的图像,领域很多点的梯度值会比较大,而这些点又不是想要的点。常用的检测方法是用阈值来排除这些点。

1.Canny算子

Canny的目标是找到一个最优的边缘检测算法。其评价标准为:
1.低错误率:标识出尽可能多的实际边缘,同时尽可能的减少噪声产生的误报。
2.高定位性:标识出的边缘要与图像中实际边缘尽可能的接近。
3.最小响应:图像边缘只能标识一次,并且可能存在的图像噪声不应标识为边缘。

Canny边缘检测的步骤为:
1.消除噪声,主要是使用高斯滤波。下图为一个5*5的高斯核的示例。

2.计算梯度幅值和方向。
(1)先用一对卷积分别作用于x和y方向。


(2)然后计算梯度幅值和方向(近似到几个可能的角度,如0,45,90,135)。

3.非极大值抑制。排除非边缘像素,仅仅保留一些细线条。
4.滞后阈值。滞后阈值需要一个高阈值和低阈值,若高于高阈值,则保留为边缘像素;若低于低阈值,则排除;若在高低之间,则仅仅保留连接到高于高阈值像素的像素。一般高低阈值比在2:1到3:1之间。

void Canny(InputArray image,OutputArray edges, double threshold1, double threshold2, int apertureSize=3,bool L2gradient=false ) 
参数1:输入图像。
参数2:输出图像。
参数3:第一个滞后阈值。
参数4:第二个滞后阈值。
参数5:sobel算子的孔径大小,默认值为3.
参数6:计算图像梯度幅值的标识,默认值false。

//载入原始图Mat src = imread("1.jpg");Canny(src, src, 3, 9,3 );imshow("【效果图】Canny边缘检测", src); 

2.Sobel算子

Sobel算子是一个主要用作边缘检测的离散微分算子。结合了高斯平滑和微分求导,用来计算图像灰度的近似梯度。其计算过程类似Canny算子,只是没有求方向。

void Sobel (  InputArray src, OutputArray dst,int ddepth,int dx,  int dy,  int ksize=3,  double scale=1,  double delta=0,  int borderType=BORDER_DEFAULT );  
参数1:输入图像。
参数2:输出图像。
参数3:输出图像深度,支持如下组合:
  • 若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F
  • 若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F
  • 若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F
  • 若src.depth() = CV_64F, 取ddepth = -1/CV_64F
参数4:x方向上的差分阶数。
参数5:y方向上的差分阶数。
参数6:核大小,必须取1,3,5,7。
参数7:计算导数时可选的缩放因子,默认值为1。
参数8:表示存入目标图之前可选的值,默认为0。
参数9:边界类型。
当内核大小为3时,Sobel内核很可能产生比较明显的误差,这时需要使用Scharr函数,只能作用大小为3的内核,其内核如下:

int main( )  {      //【0】创建 grad_x 和 grad_y 矩阵      Mat grad_x, grad_y;      Mat abs_grad_x, abs_grad_y,dst;        //【1】载入原始图        Mat src = imread("1.jpg");       //【2】显示原始图       imshow("【原始图】sobel边缘检测", src);         //【3】求 X方向梯度      Sobel( src, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT );      convertScaleAbs( grad_x, abs_grad_x );      imshow("【效果图】 X方向Sobel", abs_grad_x);         //【4】求Y方向梯度      Sobel( src, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT );      convertScaleAbs( grad_y, abs_grad_y );      imshow("【效果图】Y方向Sobel", abs_grad_y);         //【5】合并梯度(近似)      addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst );      imshow("【效果图】整体方向Sobel", dst);         waitKey(0);       return 0;   }

3.Laplace算子

Laplace算子是n维欧几里德空间中的一个二阶微分算子,定义为梯度(grad)的散度(div)。由于使用了图像梯度,所以内部的代码调用了Sobel。若让原图减去Laplace可以增强对比度,其定义为:

void Laplacian(InputArray src,OutputArray dst,int ddepth, int ksize=1, double scale=1,double delta=0,intborderType=BORDER_DEFAULT );
参数1:输入图像。
参数2:输出图像。
参数3:图像深度。
参数4:核大小,大小为正奇数,默认值为1。
参数5:计算可选缩放因子,默认值为1。
参数6:delta,默认为0。
参数7:边界类型。

int main( )  {      //【0】变量的定义      Mat src,src_gray,dst, abs_dst;        //【1】载入原始图        src = imread("1.jpg");      //【2】显示原始图       imshow("【原始图】图像Laplace变换", src);         //【3】使用高斯滤波消除噪声      GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );        //【4】转换为灰度图      cvtColor( src, src_gray, CV_RGB2GRAY );        //【5】使用Laplace函数      Laplacian( src_gray, dst, CV_16S, 3, 1, 0, BORDER_DEFAULT );        //【6】计算绝对值,并将结果转换成8位      convertScaleAbs( dst, abs_dst );        //【7】显示效果图      imshow( "【效果图】图像Laplace变换", abs_dst );        waitKey(0);         return 0;   }  

4.Scharr滤波器

void Scharr(  InputArray src, OutputArray dst,int ddepth,int dx,  int dy,  double scale=1, double delta=0, intborderType=BORDER_DEFAULT )
参数1:输入图像。
参数2:输出图像。
参数3:图像深度。
参数4:x方向的差分阶数。
参数5:y方向的差分阶数。
参数6:缩放因子。
参数7:delta。
参数8:边界类型。

int main( )  {      //【0】创建 grad_x 和 grad_y 矩阵      Mat grad_x, grad_y;      Mat abs_grad_x, abs_grad_y,dst;        //【1】载入原始图        Mat src = imread("1.jpg");      //【2】显示原始图       imshow("【原始图】Scharr滤波器", src);         //【3】求 X方向梯度      Scharr( src, grad_x, CV_16S, 1, 0, 1, 0, BORDER_DEFAULT );      convertScaleAbs( grad_x, abs_grad_x );      imshow("【效果图】 X方向Scharr", abs_grad_x);         //【4】求Y方向梯度      Scharr( src, grad_y, CV_16S, 0, 1, 1, 0, BORDER_DEFAULT );      convertScaleAbs( grad_y, abs_grad_y );      imshow("【效果图】Y方向Scharr", abs_grad_y);         //【5】合并梯度(近似)      addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst );        //【6】显示效果图      imshow("【效果图】合并梯度后Scharr", dst);         waitKey(0);       return 0;   } 


特别说明:本文为本人学习opencv所做笔记。具体参照:http://blog.csdn.net/column/details/opencv-tutorial.html
0 0