OpenCV教程 之 边缘检测函数:Canny、Sobel、Scharr(C++)

边缘检测是数字图像处理领域非常重要与基础的操作,这里简单介绍OpenCV里的Canny检测算子、sobel检测算子、scharr滤波器的基本应用

一、Canny算子

Canny边缘检测算子是John F.Canny于1986年开发出来的一个多级边缘检测算法。更为重要的是,Canny创立了边缘检测计算理论,解释了这项技术是如何工作的。Canny边缘检测算法以Canny的名字命名,被很多人推崇为当今最优的边缘检测算法

在OpenCV中,Canny函数利用Canny算子来进行图像的边缘检测操作,我们先来看看它的函数原型

void Canny(InputArray image,Output edges,double threshold1,double threshold2,int apertureSize= 3,bool L2gradient = false)

@第一个参数,InputArray类型的image,输入图像,即原图像,填Mat类型的对象即可,且需为单通道8位图像
@第二个参数,OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和类型
@第三个参数,double类型的threshold1,第一个滞后性阈值
@第四个参数,double类型的threshold2,第二个滞后性阈值
@第五个参数,int类型的apertureSize,表示应用Sobel算子的孔径大小,其有默认值3
@第六个参数,bool类型的L2gradient,一个计算图像梯度幅值的标识,有默认值false

举个栗子:
"1.jpg"如下,是一匹小马,我们接下来的程序都以这个为源图片
OpenCV教程 之 边缘检测函数:Canny、Sobel、Scharr(C++)_第1张图片

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

效果图如下:
OpenCV教程 之 边缘检测函数:Canny、Sobel、Scharr(C++)_第2张图片

二、Sobel算子

Sobel算子是一个主要用于边缘检测的离散微分算子。它结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度
在OpenCV中,Sobel函数使用扩展的Sobel算子来计算一阶、二阶、三阶或者混合图像的差分,我们来看一下它的函数原型

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);

@第一个参数,InputArray类型的src,为输入图像,填Mat类型即可
@第二个参数,OutputArray类型的dst,基本目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型
@第三个参数,int类型的ddepth,输出图像的深度
@第四个参数,int类型的dx,x方向上的差分阶数
@第五个参数,int类型的dy,y方向上的差分阶数
@第六个参数,int类型的ksize,有默认值3,表示Sobel核的大小,可以在1、3、5、7中选取一个
@第七个参数,double类型的scale,计算导数值时可以选择的缩放因子,默认值是1,表示默认情况下是没有缩放应用的
@第八个参数,double类型的delta,表示在结果存入目标图之前可选的delta值,默认为0
@第九个参数,int类型的borderType,边界模式,有默认值BORDER_DEFAULT

举个栗子

int main()
{
    //创建grad_x和grad_y矩阵
    Mat grad_x,grad_y;
    Mat abs_grad_x,abs_grad_y,dst;

    //载入原始图
    Mat src = imread("1.jpg")

    //求x方向梯度
    Sobel(src,grad_x,CV_16S,1,0,3,1,1,BORDER_DEFAULT);
    convertScaleAbs(grad_x,abs_grad_x);
    
    //求y方向梯度
    Sobel(src,grad_y,CV_16S,0,1,3,1,1,BORDER_DEFAULT);
    convertScaleAbs(grad_y,abs_grad_y);

    //合并梯度
    addweighted(abs_grad_x,0.5,abs_grad_y,0.5,0,dst);
    inshow("【效果图】Sobel边缘检测",dst);

    waitKey(0);
    return(0);
}

效果图如下:
OpenCV教程 之 边缘检测函数:Canny、Sobel、Scharr(C++)_第3张图片

三、Scharr滤波器

我们一般直接称Scharr为滤波器,而不是算子。使用Scharr滤波器计算x或y方向的图像差分,其实它的参数变量和Sobel基本上是一样的,除了没有Ksize核的大小

void Schurr(InputArray src,outputArray dst,int ddepth,int dx,int dy,double scale = 1,double delta = 0,intborderType = BORDER_DEFAULT)
@第一个参数,InputArray类型的src,为输入图像,填Mat类型即可
@第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图像有一样的尺寸和类型
@第三个参数,int类型的ddpeth,输出图像的深度
@第四个参数,int类型的dx,x方向上的差分阶数
@第五个参数,int类型的dy,y方向上的差分阶数
@第六个参数,double类型的scale,计算导数值时可选的缩放因子,默认为1
@第七个参数,double类型的delta,表示在结果存入目标图之前可选的delta值,有默认值0
@第八个参数,int类型的borderType,边界模式,有默认值BORDER_DEFAULT

举个栗子

int main()
{
    //创建grad_x和grad_y矩阵
    Mat grad_x,grad_y;
    Mat abs_grad_x,abs_grad_y,dst;

    //载入原始图
    Mat src = imread("1.jpg")

    //求x方向梯度
    Scharr(src,grad_x,CV_16S,1,0,1,0,BORDER_DEFAULT);
    convertScaleAbs(grad_x,abs_grad_x);
    
    //求y方向梯度
    Scharr(src,grad_y,CV_16S,0,1,1,0,BORDER_DEFAULT);
    convertScaleAbs(grad_y,abs_grad_y);

    //合并梯度
    addweighted(abs_grad_x,0.5,abs_grad_y,0.5,0,dst);
    inshow("【效果图】Scharr边缘检测",dst);

    waitKey(0);
    return(0);
}

综合实例

此处为上文中所讲述的OpenCV中的三种边缘检测算法应用实例:
https://github.com/LiangjunFeng/Implement-OpenCV/blob/master/4.EdgeDetected.cpp

更多资源下载

微信搜索“老和山算法指南”获取更多下载链接与技术交流群
在这里插入图片描述
有问题可以私信博主,点赞关注的一般都会回复,一起努力,谢谢支持。

你可能感兴趣的:(OpenCV教程 之 边缘检测函数:Canny、Sobel、Scharr(C++))