导数与边缘特征
看到画红圈的地方了吗,是头发(黑色)和脸部(白色)交界处,也就是图像像素值变化最大处,怎么找出变化最大处呢?如,一条曲线,怎么找变化最大处呢?求一阶导数,当一阶导数最大时,此处就是变化最大处,也就是极值点,最右边的图是中间的一阶导数图。很明显我们图像也可以看着一个函数,对函数求导即可。
边缘是什么?是像素值发生跃迁的地方,使图像的显著特征之一。在图像特征提取、对象检查、模式识别等方面有着重要作用。
如何扑捉提取边缘呢? 对图像求一阶导数。delet = f(x) - f(x-1)/x-(x-1),当delet越大时,说明x方向变化越大,边缘信息越强。
看到这里是不是有点慌,要求导耶,不用担心,因为前人已经经过无数次实验,找出了一个算子,可以代替求导,直接用这个算子对图像做卷积运算即可。这个算子也就是 Soble 算子。
一、Soble算子讲解
(1)是离散微分算子,是计算图像灰度的近似梯度。(2)soble算子功能集合了高斯平滑和微分求导。(3)又被称为一阶微分算子,求导算子,在水平和垂直两个方向上求导,得到x方向和y方向梯度图像。
如下图,Gx为水平方向的梯度图像,Gy为垂直方向的梯度图像。 可以观察 算子的特征 结合 求导公式,可以看出为什么称它为水平算子(或者垂直算子)和为什么可以代替求导。
水平算子 垂直算子
图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:
通常,为了提高效率使用不开平方的近似值:
然后可用以下公式计算梯度方向:
二、sobel算子的构建过程
Sobel算子是在一个坐标轴的方向上进行非归一化的高斯平滑,在另外一个坐标轴方向上进行差分处理,
的Sobel算子是由平滑算子和差分算子full卷积而得到的,其中为奇数。对于窗口大小为的非归一化的
Sobel平滑算子等于阶的二项式展开式的系数,那么问题只剩下怎么构建窗口大小为的Sobel差分算子?其
实,窗口大小为的Sobel差分算子是在阶的二项式展开式的系数两侧补零,然后向后差分得到的。
接下来我们来构建一个4阶的非均一化的Sobel平滑算子(其实就是高斯平滑算子)和Sobel差分算子,来理解整个构建过程。
第一步:取二项式的指数n=3,然后计算展开式的系数,如下所示:
也就是:
这就是4阶的非均一化的Sobel平滑算子(其实就是高斯平滑算子)。
第二步: 取二项式的指数,然后计算展开式的系数,即:
然后在两侧补零,得到:
接着后向差分(后面的数值减去前面相邻的数值),即得到差分后的结果为:
这就是4阶的Sobel差分算子。
第三步:将4阶的Sobel平滑算子(其实就是高斯平滑算子)和Sobel差分算子进行full卷积,即可得到的Sobel算子,即:
Sobel平滑算子和差分算子总结如下:
其实构造Sobel算子的理论基础是帕斯卡三角形(Pascal's triangle),帕斯卡三角形可以计算出平滑算子的一组系数,在极限情况下这组系数与高斯平滑算子的系数大致相同。帕斯卡三角形如下:
三、卷积核也可以旋转,用与查找不与x,y轴平行或垂直的方向上的边缘。
四、检测实例
opencv c++ 中 Soble 算子的API
Soble(
src, //输入图像
dst, //输出图像
int depth,// 图像深度
int dx, // x方向 几阶导数
int dy, // y方向 几阶导数
int Size, // Soble核算子大小,1,3,5,7...
double scale = 1, // 像素值扩大的倍数
double delta = 0, // 最终的像素值加上的数。
int borderType = BORDER_DEFAULT
)
和Soble一样,具有边缘检测的功能的 Scharr。API和Soble参数一样。
Soble 边缘检测的步骤
(1)模糊
(2)转灰度
(3)求X和Y方向的梯度
(4)振幅图像。
#include "stdafx.h"
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<algorithm>
#include<math.h>
#include<iostream>
using namespace cv;
using namespace std;
int main()
{
Mat src = imread("C:\\Users\\Geek\\Desktop\\1281425_2019-07-18_10_0\\youbantu.jpg");
Mat dst,gray;
GaussianBlur(src, dst, Size(5, 5), 0, 0);
cvtColor(src, gray, CV_RGB2GRAY);
//Soble()
//imshow("src", src);
imshow("gray", gray);
Mat xgray, ygray;
Sobel(gray, xgray, -1, 1, 0, 3);
Sobel(gray, ygray, -1, 0, 1, 3);
convertScaleAbs(xgray, xgray); // 把负的像素值变为正的。 不想不确定有没有这个必要。
convertScaleAbs(ygray, ygray);
imshow("xgray", xgray);
imshow("ygray", ygray);
Mat fgray;
addWeighted(xgray, 1, ygray, 1, 0, fgray);
imshow("fgray", fgray);
waitKey(0);
return 0;
}
结果:
五、Soble算子的优缺点
优点:计算简单,速度很快;
缺点:计算方向单一,对复杂纹理的情况显得乏力;
直接用阈值来判断边缘点欠合理解释,会造成较多的噪声点误判。