opencv笔记(4):边缘检测

五、边缘检测

边缘检测的一般步骤:滤波--->增强--->检测。
边缘检测的主要算子和滤波器有: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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值