C/C++ OpenCV实现 Canny 边缘检测
图像的边缘检测的原理是检测出图像中所有灰度值变化较大的点,而且这些点连接起来就构成了若干线条,这些线条就可以称为图像的边缘。
而本文提到的Canny边缘检测算子是John F. Canny于 1986 年开发出来的一个多级边缘检测算法。
一、边缘检测的一般步骤
1、滤波
边缘检测的算法主要是基于图像强度的一阶和二阶导数,但是导数通常对噪声很敏感,因此必须采用滤波器来改善与噪声有关的边缘检测器的性能。
2、增强
增强边缘检测的基础是确定图像各点的领域强度的变化值。增强算法可以将图像灰度点领域强度值 有显著变化的点凸显出来。
3、检测
常用的方法是通过阈值化方法来检测
二、Canny函数介绍
1、Canny函数原型
Canny( InputArray image,
OutputArray edges,
double threshold1, double threshold2,
int apertureSize = 3, bool L2gradient = false );
2、参数介绍
第一个参数表示输入图像,必须为单通道灰度图。
第二个参数表示输出的边缘图像,为单通道黑白图。
第三个参数和第四个参数表示阈值,这二个阈值中当中的小阈值用来控制边缘连接,大的阈值用来控制强边缘的初始分割即如果一个像素的梯度大与上限值,则被认为是边缘像素,如果小于下限阈值,则被抛弃。如果该点的梯度在两者之间则当这个点与高于上限值的像素点连接时我们才保留,否则删除。
第五个参数表示Sobel 算子大小,默认为3即表示一个3*3的矩阵。Sobel 算子与高斯拉普拉斯算子都是常用的边缘算子,详细的数学原理可以查阅专业书籍。
三、C++程序实现
1、Code
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat src = imread("C:\\Users\\zcc\\Desktop\\Axian.jpg");
if (!src.data)
{
cout << "Can not load the image!" << endl;
return -1;
}
Mat src1 = src;
Mat out;
namedWindow("原图");
imshow("原图", src);
//方法一3以下的版本
Canny(src, out, 150, 100);
namedWindow("方法一的效果图");
imshow("方法一的效果图", out);
//方法二3以上的版
Mat dst, edge, gray;
//创建一个与src1一样的矩阵
dst.create(src1.size(), src1.type());
//将原图像转为灰度
cvtColor(src1, gray, COLOR_RGB2GRAY);
//滤波(降噪)
blur(gray, edge, Size(3, 3));
namedWindow("模糊图像");
imshow("模糊图像", edge);
//canny
Mat out2;
Canny(edge, out2, 15, 10);
dst = Scalar::all(0);
src1.copyTo(dst, out2);
namedWindow("方法二的效果图");
imshow("方法二的效果图", out2);
waitKey();
return 0;
}