花老湿学习OpenCV:基于Sobel算子的边缘检测

 

 

卷积应用-图像边缘提取:

边缘是像素值发生跃迁的地方,是图像的显著特征之一,在图像特征提取、对象检测、模式识别等方面都有重要的作用。

对图像求它的一阶导数delta =  f(x) – f(x-1), delta越大,说明像素在X方向变化越大,边缘信号越强,如图:

                   

Sobel 算子是一个主要用作边缘检测的离散微分算子 (discrete differentiation operator)。 它Sobel算子结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。l又被称为一阶微分算子,求导算子,在水平和垂直两个方向上求导,得到图像X方法与Y方向梯度图像。

根据soble算子的数学推导: 
当内核为3*3时,横向和纵向方向上的卷积因子分别为: 

   

由上述公式计算得到Gy和Gx后,可以计算得到G的值,一个点的G的代表该点的梯度,如果大于某一设定范围则认为该点是边缘点。 为了提高效率 使用不开平方的近似值:

 Gx及Gy分别代表经横向及纵向边缘检测的图像灰度值,如果为一幅图像有竖直边缘,该竖直边缘的水平两侧灰度将存在差异,同理如果存在水平边缘,该边缘的垂直两侧灰度将存在差异,soble算子利用这种差异实现竖直边缘和水平边缘的检测。

kernel=3时,Sobel滤波器不是很准确,OpenCV使用改进版本Scharr函数,算子如下:

调用cv::Sobel()时设置ksize为CV_SCHARR,即可消除3x3Sobel导数滤波器所带来的误差。 

 API:

代码示例:

#include "pch.h"
#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;


int main()
{
	Mat src = imread("F:\\visual studio\\Image\\building2.jpg");
	if (src.empty())
	{
		cout << "Can't load the image" << endl;
		return -1;
	}
	imshow("src", src);
	//边缘检测的算法主要是基于图像强度的一阶和二阶导数,但导数通常对噪声很敏感,
	//因此必须采用滤波器来改善与噪声有关的边缘检测器的性能
	Mat blursrc;
	GaussianBlur(src, blursrc, Size(3, 3), 0,0);

	//转化为灰度图
	Mat graysrc;
	cvtColor(blursrc, graysrc, cv::COLOR_BGR2GRAY);
	imshow("graysrc", graysrc);

	Mat xgrad, ygrad, xygrad;
	Mat xgrad_Scharr, ygrad_Scharr, xygrad_Scharr;
	
	//常规Sobel
	//x方向上求导  能够得到竖直边缘
	Sobel(graysrc, xgrad, CV_16S, 1, 0, 3);
        //convertScaleAbs缩放、计算绝对值并将结果转换为8位。
	convertScaleAbs(xgrad, xgrad);
	imshow("xgrad", xgrad);
	//y方向上求导  能够得到水平边缘
	Sobel(graysrc, ygrad, CV_16S, 0, 1, 3);
	//转化为绝对值
	convertScaleAbs(ygrad, ygrad);
	imshow("ygrad", ygrad);

	//Scharr滤波
	Sobel(graysrc, xgrad_Scharr, CV_16S, 1, 0, CV_SCHARR);
	convertScaleAbs(xgrad_Scharr, xgrad_Scharr);
	imshow("xgrad_Scharr", xgrad_Scharr);

	Sobel(graysrc, ygrad_Scharr, CV_16S, 0, 1, CV_SCHARR);
	convertScaleAbs(ygrad_Scharr, ygrad_Scharr);
	imshow("ygrad_Scharr", ygrad_Scharr);



	//合并梯度
	//不明白有些博主用addWeigthed的方式,希望有人可以解答。
	//addWeighted(xgrad, 0.5, ygrad, 0.5, 0, xygrad);
	add(xgrad, ygrad, xygrad);
	imshow("xygrad", xygrad);

	add(xgrad_Scharr, ygrad_Scharr, xygrad_Scharr);
	imshow("xygrad_Scharr", xygrad_Scharr);
	
	waitKey(0);
}

效果展示:

源图像与灰度图像如下:

Sobel与Scharr滤波下的x方向梯度: 能够看出竖直的边缘

Sobel与Scharr滤波下的x方向梯度: 能够看出水平的边缘

合并梯度:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值