一、Sobel算子理论解析
Sobel算子用来计算一阶、二阶、三阶或混合图像差分。
一阶图像差分根据一阶导数来近似,,
一阶计算过程:
1. 分别在x和y方向求导:
x方向:将I与一个奇数大小的内核Gx进行卷积,当内核为3时,Gx的计算结果为:
y方向:将I与一个奇数大小的Gy进行卷积,当内核为3时,Gy的计算结果为:
注:Sobel中间加入权重值2,可以有效抑制(平滑)噪声。
2. 在图像的每一点,结合以上两个结果求出近似梯度:
二阶图像差分根据二阶导数来近似,
二阶计算过程:
1. 分别在x和y方向求导:
x方向:将I与一个奇数大小的内核Gx进行卷积,当内核为3时,Gx的计算结果为:
y方向:将I与一个奇数大小的Gy进行卷积,当内核为3时,Gy的计算结果为:
注:Sobel中间加入权重值2,可以有效抑制(平滑)噪声。
2. 在图像的每一点,结合以上两个结果求出近似梯度:
注:为防止溢出,所有计算结果均需要在[0,255]中。
二、Sobel算子代码验证
#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat src = Mat(5,5,CV_8UC1);
randu(src, Scalar::all(0), Scalar::all(255));
Size size = src.size();
cout << "原图像" << endl;
cout << src << ";" << endl << endl;
Mat dst;
copyMakeBorder(src, dst, 1, 1, 1, 1, BORDER_DEFAULT);
cout << "BORDER_DEFAULT填充后的图像" << endl;
cout << dst << ";" << endl << endl;
Mat gradient_x;
Sobel(src, gradient_x, src.depth(), 1, 0);
cout << "SobelX方向的一阶差分" << endl;
cout << gradient_x << ";" << endl << endl;
Mat gradient_2;
Sobel(src, gradient_2, src.depth(), 2, 0);
cout << "SobelX方向的二阶差分" << endl;
cout << gradient_2 << ";" << endl << endl;
}
三、Scharr滤波器
在Sobel算法中,内核大小为3时,可能产生比较明显的误差。为了解决这一问题,opencv提供了scharr函数,仅作用于内核为3的特殊情况,内核为:
故下面两者是等价的
Scharr(src, dst,ddepth, dx, dy, scale, delta, bodertype)
Sobel( src, dst,ddepth, dx, dy, CV_SCHARR, scale, delta, bodertype)