边缘检测 - Sobel算子
程序员文章站
2024-01-28 09:05:04
...
一. Sobel算子简介
Sobel算子是一个主要用于边缘检测的离散微分算子(discrete differentiation operator)。它结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。
二. Sobel算子的计算过程
- 分别在 x 和 y 两个方向求导。
① 水平变化:将图像与一个奇数大小的内核Gx进行卷积。
② 垂直变化:将图像与一个奇数大小的内核Gy进行卷积。
- 在图像的每一点,结合以上两个结果求出近似梯度:
另外,也可用下面更简单的公式代替:
三. Sobel() 函数介绍
void Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, intborderType=BORDER_DEFAULT )
- 第一个参数,InputArray 类型的src,为输入图像,填Mat类型即可。
- 第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
- 第三个参数,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,x 方向上的差分阶数。
- 第五个参数,int类型dy,y方向上的差分阶数。
- 第六个参数,int类型ksize,有默认值3,表示Sobel核的大小;必须取1,3,5或7。
- 第七个参数,double类型的scale,计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。
- 第八个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
- 第九个参数, int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。
四. 代码演示
int main(int argc, char** argv)
{
Mat src = imread("E:/Image/hf.png");
if (src.empty())
{
cout << "load image error..." << endl;
return -1;
}
imshow("src img", src);
GaussianBlur(src, src, Size(3, 3), 0, 0);
cvtColor(src, src, CV_BGR2GRAY);
Mat sobel_x, sobel_y;
// 求X方向梯度
Sobel(src, sobel_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT);
//convertScaleAbs(sobel_x, sobel_x);
imshow("sobel_x", sobel_x);
// 求Y方向梯度
Sobel(src, sobel_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT);
//convertScaleAbs(sobel_y, sobel_y);
imshow("sobel_y", sobel_y);
// 合并梯度
Mat dst;
addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0, dst);
imshow("result", dst);
waitKey(0);
return 0;
}
结果示例:
注:
-
convertScaleAbs() 函数可以实现图像增强,是一个位深转化函数,可将任意类型的数据转化为CV_8UC1。具体数据处理方式如下:
(1). 对于srcalpha+beta的结果如果是负值且大于-255,则直接取绝对值;
(2). 对于srcalpha+beta的结果如果大于255,则取255;
(3). 对于srcalpha+beta的结果是负值,且小于-255,则取255;
(4). 对于srcalpha+beta的结果如果在0-255之间,则保持不变; -
addWeighted() 函数是将两张相同大小,相同类型的图片融合的函数。