OpenCV Sobel函数

OpenCV Sobel函数作用Sobel函数使用扩展的Sobel算子,来计算一阶、二阶、三阶或混合图像差分。原理首先,我们来开一下计算机是如何检测边缘的。以灰度图像为例,它的理论基础是这样的,如果出现一个边缘,那么图像的灰度就会有一定的变化,为了方便假设由黑渐变为白代表一个边界,那么对其灰度分析,在边缘的灰度函数就是一个一次函数y=kx,对其求一阶导数就是其斜率k,就是说边缘的一阶导数是一个常数,而由于非边缘的一…

大家好,欢迎来到IT知识分享网。

作用

Sobel函数使用扩展的 Sobel 算子,来计算一阶、二阶、三阶或混合图像差分。

原理

首先,我们来开一下计算机是如何检测边缘的。以灰度图像为例,它的理论基础是这样的,如果出现一个边缘,那么图像的灰度就会有一定的变化,为了方便假设由黑渐变为白代表一个边界,那么对其灰度分析,在边缘的灰度函数就是一个一次函数y=kx,对其求一阶导数就是其斜率k,就是说边缘的一阶导数是一个常数,而由于非边缘的一阶导数为零,这样通过求一阶导数就能初步判断图像的边缘了。通常是X方向和Y方向的导数,也就是梯度。理论上计算机就是通过这种方式来获得图像的边缘。

但是,具体应用到图像中你会发现这个导数是求不了的,因为没一个准确的函数让你去求导,而且计算机在求解析解要比求数值解麻烦得多,所以就想到了一种替代的方式来求导数。就是用一个3×3的窗口来对图像进行近似求导。拿对X方向求导为例,某一点的导数为第三列的元素之和减去第一列元素之和,这样就求得了某一点的近似导数。其实也很好理解为什么它就近似代表导数,导数就代表一个变化率,从第一列变为第三列,灰度值相减,当然就是一个变化率了。这就是所谓的Prewitt算子。这样近似X方向导数就求出来了。Y方向导数与X方向导数求法相似,只不过是用第三行元素之和减去第一行元素之和。X方向和Y方向导数有了,那么梯度也就出来了。这样就可以找出一幅图中的边缘了。

还有一个问题,由于求的是3×3中心点的导数,所以给第二列加了一个权重,它的权重为2,第一列和第三列的权重为1,好了,这就是Sobel算子了。相比Prewitt算子,Sobel的抗噪能力更强。如图所示:
在这里插入图片描述

这样,中心点的Y方向导数就求出来了。

举个例子吧。X点以Sobel方式求导数ΔX=1×50+2×30+1×50-(1×50+2×30+1×50)=0。这样可以看出这个点不是边界。
在这里插入图片描述

好了,了解了基本理论之后,我们看看OpenCv下的Sobel函数吧

函数原型

CV_EXPORTS_W 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 InputArray 类型的src,为输入图像,填Mat类型即可
OutputArray dst OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
int ddepth int类型的ddepth,输出图像的深度,支持如下src.depth()和ddepth的组合:
若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F
若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F
若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F
若src.depth() = CV_64F, 取ddepth = -1/CV_64F
int dx int类型dx,x 方向上的差分阶数
int dy int类型dy,y方向上的差分阶数。
int ksize = 3 int类型ksize,有默认值3,表示Sobel核的大小;必须取1,3,5或7。
double scale = 1 double类型的scale,计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。
double delta = 0 double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
int borderType = BORDER_DEFAULT int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate处得到更详细的信息

调用Sobel函数

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;


const char* load_win = "load image";
const char* gray_win = "gray imgae";

int main(int argc, char** argv)
{
	Mat src, dst;
	src = imread("2.jpg");
	if (src.empty())
	{
		cout << "could not load..." << endl;
		return -1;
	}
	namedWindow(load_win, 0);
	imshow(load_win, src);

	GaussianBlur(src, dst, Size(3, 3), 0, 0);
	Mat src_gray;
	cvtColor(dst, src_gray, COLOR_BGR2GRAY);
	namedWindow(gray_win, 0);
	imshow(gray_win, src_gray);

	Mat x_grad, y_grad;
	Sobel(src_gray, x_grad, CV_16S, 1, 0, 3);
	Sobel(src_gray, y_grad, CV_16S, 0, 1, 3);
	convertScaleAbs(x_grad, x_grad);
	convertScaleAbs(y_grad, y_grad);

	namedWindow("x_grad", 0);
	imshow("x_grad", x_grad);
	namedWindow("y_grad", 0);
	imshow("y_grad", y_grad);

	waitKey(0);
	return 0;
}

效果图

在这里插入图片描述

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/14645.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信