一、图像边缘检测原理
图像边的缘由图像中两个相邻的区域之间的像素集合组成,是指图像中一个区域的结束和另外一个区域的开始。也可以这么理解,图像边缘就是图像中灰度值发生空间突变的像素的集合。梯度方向和幅度是图像边缘的两个性质,沿着跟边缘垂直的的方向,像素值的变化幅度比较平缓;而沿着与边缘平行的方向,则像素值变化幅度变化比较大。于是,根据该变化特性,通常会采用计算一阶或者二阶导数的方法来描述和检测图像边缘。
基于边缘检测的图像分割方法的基本思路是首先检测出图像中的边缘像素,然后再把这些边缘像素集合连结在一起便组成所要的目标区域边界。
由上可知,图像中的边缘可以通过对灰度值求导来检测确定,然而求导数可以通过计算微分算子来实现。在数字图像处理领域,微分运算通常被差分计算来近似代替。
二、Sobel算子
Sobel算子是Irwin Sobel于1968年在一次博士生课题研讨会他提出的一个 3x3的各向同性梯度算子(Isotropic Gradient Operator)。
X方向:
Y方向:
对应的水平和垂直其梯度公式为:
另外一点要指出的是,Sobel算子存在一种变种为各向同性Sobel算子,其模板为
X方向:
Y方向:
与普通Sobel算子相比, Sobel各向同性算子的权值准确性更高。因为其模板的权值规律是离中心越远的位置,权值(绝对值)的比重越小,如下图,可以将模板看做是9个边长为1的小正方形组成,图中虚线三角形的下直角边长为1,斜边长为。如果(0,0)位置权值绝对值大小为1,则按照距离关系,位置(1,0)处的权值绝对值大小应该为才是准确的。sobel算子具有比较准确的边缘定位,对噪声较多和灰度渐变的图像处理效果较好。
三、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 );
参数说明:
src :输入图像;
dst : 输出与src大小、通道数相同的图像;、
ddepth :输出图像的深度,必须大于输入的图像数据类型,参见@ref filter_depth " combined ";在输入图像为8位的情况下会导致导数被截断。
dx : x的导数的阶次;
dy : y的导数的阶次;
ksize : 扩展Sobel内核的大小;它一定是1 3 5或7。
scale : 计算出的导数值选择尺度因子;默认情况下是1,不缩放;
delta : 表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
borderType : 边界的处理模式,默认值:BORDER_DEFAULT。
cv::Mat src;
src = cv::imread("D:\\QtProject\\Opencv_Example\\Sobel\\sobel.png", cv::IMREAD_GRAYSCALE);
if (src.empty()) {
cout << "Cannot load image" << endl;
return;
}
cv::imshow("src", src);
cv::Mat sobelX, sobelY;
cv::Sobel(src, sobelX, CV_16S, 1, 0);
cv::Sobel(src, sobelY, CV_16S, 0, 1);
cv::Mat convertX, convertY;
cv::convertScaleAbs(sobelX, convertX); //将结果转换为8位。
cv::convertScaleAbs(sobelY, convertY);
cv::Mat addDst;
cv::addWeighted(convertX, 1, convertY, 1, 0, addDst);
cv::imshow("dst", addDst);