18.Sobel算子

1.主要内容

(1)卷积应用-图像边缘提取

(2)sobel经典算法与opencv提供的sobel算法

(3)当一些API不能满足自己的需求时,如何去自己完成一些计算

2.卷积应用——图像边缘提取

(1) 边缘是什么-是像素值发生跃迁的地方,是图像的显著特征之一,在图像特征提取、对象检测、模式识别等方面都有重要的作用
(2)如何捕捉/提取边缘-对图像求它的一阶导数
delta = f(x)- f(x - 1),delta越大,说明像素在X 方向变换越大,边缘信号越强
那么怎么去求导数呢?使用sobel算子就好,卷积操作
在这里插入图片描述
图像该区域像素值的变化
在这里插入图片描述
此时,在中点的变换率最大
在这里插入图片描述

3.sobel算子

(1)第一部分

  • 是离散微分算子(discrete differentiation operator)用来计算图像灰度的近似梯度。

  • sobel算子功能集合高斯平滑和微分求导。

  • 又称为一阶微分算子,求导算子,在水平和垂直两个方向上求导,得到图像X方向和Y方向梯度图像。

  • 对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高。当对精度要求不是很高时,是一种较为常用的边缘检测方法。

(2)第二部分(GX,GY代表利用模板对原图像卷积的结果)

  • 通过赋予个像素不同的权重来扩大个像素之间的差异,从而得到图像。
  • 水平梯度(横向的算子)
    在这里插入图片描述
  • 垂直梯度(纵向的算子)
    在这里插入图片描述
    如果G大于某一个阈值,则认定该点为一个边缘点。
    上述的处理可以同时进行两个方向的处理,当需要突出图像某一个方向的边缘信息时,也可以只进行其中一个方向的处理。
  • 最终图像梯度计算
    在这里插入图片描述

(3)第三部分

  • 求取倒数的近似值,sobel算子kernel=3时不是很准确,opencv3使用改进版本Scharr函数,算子如下:
    在这里插入图片描述

4.相关API

(1)API说明cv::sobel

Sobel(
InputArray Src,//输入图像
OutputArray dst,//输出图像,大小与输入图像一致
int depth,//输出图像深度,针对不同的输入图像,输出目标图像有不同的深度,具体组合如下: 
//ddepth =-1时,代表输出图像与输入图像相同的深度。 
int dx,//X方向,x 方向上的差分阶数,1或0 
int dy,//Y方向,y 方向上的差分阶数,1或0 
 int ksize,//SOBEL算子kernel大小,必须是1,3,5,7
 double scale = 1//将得出的值放大几倍或者缩小几倍
 double delta = 0//加上一个常量值
 int borderType = BORDER_DEFAULT
 );
 //dx=1,dy=0,表示计算X方向的导数,检测出的是垂直方向上的边缘;
 //dx=0,dy=1,表示计算Y方向的导数,检测出的是水平方向上的边缘。 

在这里插入图片描述
int ksize:为进行边缘检测时的模板大小为ksizeksize,取值为1、3、5和7,其中默认值为3。特殊情况:ksize=1时,采用的模板为31或1*3。
当ksize=3时,Sobel内核可能产生比较明显的误差,此时,可以使用 Scharr 函数,该函数仅作用于大小为3的内核。具有跟sobel一样的速度,但结果更精确。
由于sobel算子求出来的值有可能出现负值,所以当图像为8U是,dst必须为16S,而不能为16U。
使用filter2D函数来进行sobel算子的计算,图像与直接使用sobel()函数计算得到的不相同,主要原因在于没有考虑数据的溢出以及一些数据的正负性。
有时发现最后的图像上出现一些不应该亮或者暗的地方,这应该是数据的截断问题,原因一般是图像的类型不一致。

(2)API说明cv::Scharr

Scharr(
InputArray Src,
OutputArray dst,
int depth,
int dx,
int dy,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT
)

(3)其他API

GaussianBlur(src,dst,Size(3,3),0,0,BORDER_DEFAULT);
cvtColor(src,gray,COLOR_RGB2GRAY);
addWeighted(A,0.5,B,0.5,0,AB);
convertScaleAbs(A,B)//计算图像A的像素绝对值,输出到图像B

5.本节演示程序步骤

(1)先做高斯模糊。

原因:sobel算子对噪声比较敏感,容易受到噪声的影响,此时用高斯模糊来降噪。

(2)转换为灰度图像。

(3)通过sobel算子求X、Y梯度,再使用convertScaleAbs()函数将图像中的一些负数变为正数。

(4)通过addWeighted函数混合X、Y梯度的图像,得到最终的振幅图像。

//为了获得更好的效果可以自己尝试写代码,不使用addWeighted函数,
Mat xygrad=Mat (xgrad.size(),xgrad.type());
printf("type:%d\n",xgrad.type());  //查看原图像的数据类型,防止稍后数据溢出
int width = xgrad.cols;
int height = ygrad.rows;
fort(int row = 0;row < height;row++){
    for(int col = 0;col < width;col++){
        int xg = xgrad.at<uchar>(row,col);
        int yg = ygrad.at<uchar>(row,col);
        int xy = xg + yg;//如同上诉公式
        //将最终的像素值进行赋值,并且使用saturate_cast <uchar> ()函数来控制数据的大小
        xygrad.at<uchar>(row,col) = saturate_cast <uchar> (xy);
    }
}
/*相同功能但是功能稍弱的操作
*addWeighted(xgrad,0.5,ygrad,0.5,0,xygrad);
*/
imshow("Fina_image",xygrad);

6.Scharr和sobel相同图像的对比

原图像
在这里插入图片描述
sobel
在这里插入图片描述
Scharr
在这里插入图片描述

7.对于个图像深度的总结

CV_8U - 8-bit unsigned integers ( 0..255 )
CV_8S - 8-bit signed integers ( -128..127 )
CV_16U - 16-bit unsigned integers ( 0..65535 )
CV_16S - 16-bit signed integers ( -32768..32767 )
CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )

8.课外扩展

sobel函数
Opencv中cvSobel函数使用
Scharr函数
opencv中addWeighted()函数用法总结(05)
GaussianBlur函数
OpenCV学习笔记-Sobel()函数与Scharr()函数怎么用
opencv函数之saturate_cast(防止溢出)
opencv之saturate_cast模板函数
saturate_cast(X)作用:确保X中RGB值得范围在0~255之间
Opencv convertScaleAbs函数 和灰度图上进行透明彩色绘制

发布了41 篇原创文章 · 获赞 14 · 访问量 2001

猜你喜欢

转载自blog.csdn.net/qq_43367829/article/details/104323671
今日推荐