一、什么是边缘检测?

边缘检测的基本思想是通过检测每个像素和其邻域的状态,以决定该像素是否位于一个物体的边界上。如果一个像素位于一个物体的边界上,则其邻域像素的灰度值的变化就比较大。假如可以应用某种算法检测出这种变化并进行量化表示,那么就可以确定物体的边界。

经典的边缘检测方法是对原始图像中像素的某小邻域来构造边缘检测算子。常用的边缘检测方法有Roberts算子、Sobe l算子、Prew itt算子、K irsch算子、Laplacian算子、LOG 算子、Canny算子等。其中canny算子最为常用,本文将重点介绍canny算子的运用。

二、边缘检测算法有如下四个步骤:


(1)滤波:边缘检测算法主要是基于图像强度的一阶和二阶导数,但导数的计算对噪声很敏感,因此必须使用滤波器来改善与噪声有关的边缘检测器的性能.需要指出,大多数滤波器在降低噪声的同时也导致了边缘强度的损失,因此,增强边缘和降低噪声之间需要折衷.

(2)增强:增强边缘的基础是确定图像各点邻域强度的变化值.增强算法可以将邻域(或局部)强度值有显著变化的点突显出来.边缘增强一般是通过计算梯度幅值来完成的.

(3)检测:在图像中有许多点的梯度幅值比较大,而这些点在特定的应用领域中并不都是边缘,所以应该用某种方法来确定哪些点是边缘点.最简单的边缘检测判据是梯度幅值阈值判据.

(4)定位:如果某一应用场合要求确定边缘位置,则边缘的位置可在子像素分辨率上来估计,边缘的方位也可以被估计出来.

在边缘检测算法中,前三个步骤用得十分普遍。这是因为大多数场合下,仅仅需要边缘检测器指出边缘出现在图像某一像素点的附近,而没有必要指出边缘的精确位置或方向.边缘检测误差通常是指边缘误分类误差,即把假边缘判别成边缘而保留,而把真边缘判别成假边缘而去掉.边缘估计误差是用概率统计模型来描述边缘的位置和方向误差的.我们将边缘检测误差和边缘估计误差区分开,是因为它们的计算方法完全不同,其误差模型也完全不同.


三、canny算子的数学算法原理

可参见:canny算子canny算子相关文献


四、Canny()原型

canny算子在OpenCV中已经被编写为函数Canny(),可直接调用,其原型如下:


void cv::Canny

(

InputArray 

 

 

OutputArray 

//canny检测后的输出图像

 

 

double 

//阈值1,低阈值

 

 

double 

//阈值2,高阈值,低/高=比值1:2~1:3尤佳

 

 

int 

3,  //Sobel算子的孔径大小

 

 

bool 

false  //计算梯度幅度值的标识,默认为false

 

)

 


五、代码示例

//Canny边缘检测练习
//2016.07.21

//头文件和命名空间
#include<opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace cv;

int main()
{
	Mat srcImage = imread("grape.jpg");
	Mat img = srcImage.clone();//原图备份至img,用于后续的处理
	imshow("【1】原图", img);

	Mat  grayImage, addingImage, blurImage,canny_detection;

	addingImage.create(img.size(), img.type());//创建于原图大小和类型相同的矩阵
	cvtColor(img, grayImage, COLOR_BGR2GRAY);//将待处理图像转换为灰度图
	imshow("【2】灰度图", grayImage);

	blur(grayImage, blurImage, Size(7, 7));//均值滤波,降噪处理
	imshow("【3】灰度图+均值滤波", blurImage);

	Canny(blurImage, canny_detection, 3, 9, 3);//边缘检测
	imshow("【4】灰度图+均值滤波+边缘检测", canny_detection);

	addingImage = Scalar::all(0);//创建黑色画布
	img.copyTo(addingImage, canny_detection);//将备份图和canny输出的边缘检测图叠加
	imshow("【5】原图和边缘检测叠加", addingImage);

	waitKey(0);//按ESC可退出
	return 0;
}



六、运行结果

java opencv dnn 边缘检测 opencv canny边缘检测算法_OpenCV

java opencv dnn 边缘检测 opencv canny边缘检测算法_canny_02

java opencv dnn 边缘检测 opencv canny边缘检测算法_算法_03


============不同的参数取值,如滤波采用的内核,及canny的阈值对最终检测效果影响较大============


***均值模糊采用3x3的内核,高低阈值分别为3,9,其边缘检测效果:

java opencv dnn 边缘检测 opencv canny边缘检测算法_边缘检测_04

***均值模糊采用7X7的内核,高低阈值分别为3、9,其边缘检测效果:

java opencv dnn 边缘检测 opencv canny边缘检测算法_边缘检测_05

***均值模糊采用7X7的内核,高低阈值分别为40、90,其边缘检测效果:

java opencv dnn 边缘检测 opencv canny边缘检测算法_边缘检测_06


边缘检测图与原图叠加后的效果图:

java opencv dnn 边缘检测 opencv canny边缘检测算法_canny_07

java opencv dnn 边缘检测 opencv canny边缘检测算法_算法_08