sobel算子的基本概念
Sobel算子是一个主要用于边缘检测的离散微分算子,它结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。在图像的任何一点使用此算子,都会得倒对应的梯度矢量或其法向量。
sobel算子的计算过程
假设图像为I,分别在x和y方向上计算梯度,其实就是用卷积核在两个方向上与图像进行卷积,以大小为3的卷积核为例:
然后在图像上的每一点,结合以上两个结果求出近似梯度:
另外也可以用下面更简单的公式替代:
函数原型:
void Sobel(InputArray src, OutputArray dst, int ddpth, int dx, int dy, int ksize=3, double scale=1, double delta=0,int borderType=BORDER_DEFAULT);
参数详解:
- 第一个参数:输入图像,Mat类型即可;
- 第二个参数:输出,需要和源图像有一样的大小和类型;
- 第三个参数:int类型的ddepth,输入图像的深度,支持ruxiasrc.depth()和ddepth的组合。
- 若sec.depth()=CV_8U,取ddepth=-1/CV_16S/CV_32F/CV_64F;
- 若sec.depth()=CV_16U/CV_16S,取ddepth=-1/CV_16S/CV_32F/CV_64F;
- 若sec.depth()=CV_32F,取ddepth=-1/CV_16S/CV_32F/CV_64F;
- 若sec.depth()=CV_64F,取ddepth=-1/CV_16S/CV_64F;
- 第四个参数:int类型的dx,x方向上的差分阶数。
- 第五个参数:it类型dy,y方向上的差分阶数。
- 第六个参数:int类型的ksize,默认值是3,卷积核的大小,只能取1,3,5,7.
- 第七个参数:double类型的scale,计算导数时的可选尺度因子,默认值是1,表示默认情况下是没有应用缩放的。
- 第八个参数:double类型的delta,表示在结果存入目标图之前可选的delta值,默认值是0.
- 第九个参数:int类型的borderType,边界模式,默认值是BORDER_DEFALULT。
一般情况下都是用ksize*ksize的内核来计算导数的,但是一种特殊情况是,当ksize=1时,往往会使用3*1或1*3的内核,且这种情况下,并没有进行高斯平滑操作。
代码示例:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
int main()
{
// 初始化x和y方向的梯度
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
Mat srcImage;
srcImage = imread("/Users/dwz/Desktop/cpp/1.jpg");
cvtColor(srcImage, srcImage, COLOR_BGR2GRAY);
// 计算x方向的梯度
Sobel(srcImage, grad_x,CV_16S, 1, 0, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x);
// 计算y方向的梯度
Sobel(srcImage, grad_y, CV_16S, 0, 1, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(grad_y, abs_grad_y);
// 合并梯度
Mat dstImage;
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dstImage);
imwrite("sobel.jpg", dstImage);
}
输入:
输出: