canny边缘检测算子是一个多级边缘检测算法。
最优边缘检测的评价标准:低错误率、高定位性、最小响应。为了满足这些要求,Canny使用了变分法,这是一种寻找满足特定功能的函数的方法。最优检测用4个指数函数项的和表示,但是它非常近似于高斯函数的一阶导数。
Canny函数利用Canny算子来进行图像的边缘检测操作。
void Canny(
InputArray image,
OutputArray edges,
double threshold1,
double threshold2,
int apertureSize=3,
bool L2gradient=false) ;
#include
#include
using namespace cv;
int main()
{
Mat srcImage = imread("fg.jpg");
imshow("[原图]Canny边缘检测", srcImage);
Mat dstImage, edge, grayImage;
dstImage.create(srcImage.size(), srcImage.type());
cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
blur(grayImage, edge, Size(3, 3));
Canny(edge, edge, 3, 9, 3);
imshow("[效果图]Canny边缘检测", edge);
waitKey(0);
return 0;
}
运行效果如下:
Sobel算子是一个主要用于边缘检测的离散微分算子。它结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。在图像的任何一点使用此算子,都将会产生对应的梯度矢量或是其法矢量。
Sobel函数使用扩展的Sobel算子,来计算一阶、二阶、三阶或混合图像差分。
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) ;
#include
#include
#include
using namespace cv;
int main()
{
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y, dst;
Mat src = imread("fg.jpg");
imshow("【原始图】sobel边缘检测", src);
Sobel(src, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x);
imshow("【效果图】 X方向Sobel", abs_grad_x);
Sobel(src, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT);
convertScaleAbs(grad_y, abs_grad_y);
imshow("【效果图】Y方向Sobel", abs_grad_y);
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst);
imshow("【效果图】整体方向Sobel", dst);
waitKey(0);
return 0;
}
运行效果如下:
Laplacian算子是n维欧几里得空间中的一个二阶微分算子,定义为梯度grad的散度div。根据图像处理的原理可知,二阶导数可以用来进行边缘检测,因为图像是二维的,需要在两个方向进行求导。使用Laplacian算子将会使求导过程变得简单。
Laplacian算子的定义:
Laplacian函数可以计算出图像经过拉普拉斯变换后的结果。
void Laplacian(
InputArray src,
OutputArray dst ,
int ddepth,
int ksize=1,
double scale=1,
double delta=0 ,
intborderType=BORDER_DEFAULT) ;
#include
#include
#include
using namespace cv;
int main()
{
Mat src, src_gray, dst, abs_dst;
src = imread("fg.jpg");
imshow("【原始图】图像Laplace变换", src);
GaussianBlur(src, src, Size(3, 3), 0, 0, BORDER_DEFAULT);
cvtColor(src, src_gray, CV_RGB2GRAY);
Laplacian(src_gray, dst, CV_16S, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(dst, abs_dst);
imshow("【效果图】图像Laplace变换", abs_dst);
waitKey(0);
return 0;
}
运行效果如下:
我们一般直接称scharr为滤波器,而不是算子。它在OpenCV中主要是配合Sobel算子的运算而存在的。
使用Scharr滤波器运算符计算x或y方向的图像差分,其参数变量和Sobel基本上是一样的,除了没有ksize核的大小。
void Scharr(
InputArray src,
OutputArray dst,
int ddepth,
int dx,
int dy,
double scale=1 ,
double delta=0 ,
intborderType=BORDER_DEFAULT) ;
#include
#include
#include
using namespace cv;
int main()
{
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y, dst;
Mat src = imread("fg.jpg");
imshow("【原始图】Scharr滤波器", src);
Scharr(src, grad_x, CV_16S, 1, 0, 1, 0, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x);
imshow("【效果图】 X方向Scharr", abs_grad_x);
Scharr(src, grad_y, CV_16S, 0, 1, 1, 0, BORDER_DEFAULT);
convertScaleAbs(grad_y, abs_grad_y);
imshow("【效果图】Y方向Scharr", abs_grad_y);
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst);
imshow("【效果图】合并梯度后Scharr", dst);
waitKey(0);
return 0;
}
运行效果如下: