卷积应用-图像边缘提取:
边缘是像素值发生跃迁的地方,是图像的显著特征之一,在图像特征提取、对象检测、模式识别等方面都有重要的作用。
对图像求它的一阶导数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方向梯度: 能够看出水平的边缘
合并梯度: