1、边缘提取
边缘提取,是对于图片轮廓的一个处理。对于边界处,灰度值变化比较剧烈的地方,就定义为边缘。也就是拐点,拐点是指函数发生凹凸性变化的点。二阶导数为零的地方。并不是一阶导数,因为一阶导数为零,表示是极值点。
关于导数总结如下:
(1)一阶导数是图像中产生较粗的边缘
(2)二阶导数对精细细节,如细线、孤立点和噪声有较强的响应
(3)二阶导数在灰度斜坡和灰度台阶过度处会产生双边沿响应
(4)二阶导数的符号可以确定边缘的过渡是从亮到暗还是从暗到亮
(5)选导数提取边沿之前最好是做下图像的平滑,导数对噪声比较敏感。
边缘提取:首先是利用边缘增强算子,突出图像中的局部边缘,然后定义象素的“边缘强度”,通过设置阈值的方法提取边缘点集。由于噪声和模糊的存在,监测到的边界可能会变宽或在某点处发生间断。因此,边界检测包括两个基本内容: (1)用边缘算子提取出反映灰度变化的边缘点集。
(2)在边缘点集合中剔除某些边界点或填补边界间断点,并将这些边缘连接成完整的线。
边缘定义:图像灰度变化率最大的地方(图像灰度值变化最剧烈的地方)。图像灰度在表面法向变化的不连续造成的边缘。一般认为边缘提取是要保留图像的灰度变化剧烈的区域,这从数学上看,最直观的方法就是微分(对于数字图像来说就是差分),在信号处理的角度来看,也可以说是用高通滤波器,即保留高频信号。
边缘信息包含两个方面:
(1).像素的坐标
(2).边缘的方向
2、边缘提取的算子
(1)Sobel算子
横向的卷积算子
纵向的卷积算子
Sobel算子的函数
void Sobel(
InputArray src,
OutputArray dst,
int ddepth, // 输出图像深度
int dx, // x方向的梯度
int dy, // y方向的梯度
int ksize = 3,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT );
(2) laplance算子
在二阶导数的时候,最大变化处的值为零即边缘是零值。通过二阶导数计算,依据此理论我们可以计算图像二阶导数,提取边缘。
laplance算子函数:
void Laplacian(
InputArray src,
OutputArray dst,
int ddepth,// 输出图像深度
int ksize = 1,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT
);
(3) Canny算子
Canny算子是由几个算子的组合:
a.高斯模糊。
b.灰度变化
c.用Sobel计算梯度
d.用threshold输出二值图。
void Canny(
InputArray image,
OutputArray edges,
double threshold1, // 低阈值
double threshold2,// 高阈值
int apertureSize = 3, // sobel算子的Kernel size
bool L2gradient = false // 是否规一化
);
3、代码与效果图
cvtColor(srcImg1, grayImg, CV_BGR2GRAY);
Mat sobelImgx;
Mat sobelImgy;
Sobel(grayImg, sobelImgx, -1, 1, 0);
Sobel(grayImg, sobelImgy, -1, 0, 1);
imshow("sobelImgx", sobelImgx);// 显示
imshow("sobelImgy", sobelImgy);// 显示
Mat LaplacianImg;
Laplacian(grayImg, LaplacianImg, -1, 3);
imshow("LaplacianImg", LaplacianImg);// 显示
Mat CannyImg;
Canny(grayImg, CannyImg, 50,150);
imshow("CannyImg", CannyImg);// 显示
原图:
Sobel(横向):
Sobel(纵向):
拉普拉斯
Canny算子
4、工程源码下载
本文源代码在Debug–x64下编译运行。
ZIP包中包含开发环境,下载解压后可直接编译运行。