图像处理(七)——Canny边缘检测

版权声明: https://blog.csdn.net/Godsolve/article/details/83834508

Canny边缘检测算子是John F. Canny于 1986 年开发出来的一个多级边缘检测算法。更为重要的是 Canny 创立了边缘检测计算理论(Computational theory of edge detection)解释这项技术如何工作。
通常情况下边缘检测的目的是在保留原有图像属性的情况下,显著减少图像的数据规模。目前有多种算法可以进行边缘检测,虽然Canny算法年代久远,但可以说它是边缘检测的一种标准算法,而且仍在研究中广泛使用。

Canny算法是实现可以分为六步:

  1. 灰度化图像
    较为简单,不多说

  2. 高斯滤波
    高斯滤波是为了平滑图像,消除噪声。高斯滤波是实现之前的实验已经做过。

  3. 计算梯度之和方向
    图像灰度值的梯度一般使用一阶有限差分来进行近似,这样就可以得图像在x和y方向上偏导数的两个矩阵。
    在这里插入图片描述
    其中f为图像灰度值,P代表X方向梯度幅值,Q代表Y方向 梯度幅值,M是该点幅值,Θ是梯度方向,也就是角度。

  4. 非极大值抑制
    非极大值抑制是进行边缘检测的一个重要步骤,简单来说就是指寻找像素点局部最大值。
    在这里插入图片描述
    通过插值来计算dTemp1和dTemp2的像素值(亚像素 )。

  5. 双阈值的选取
    双阈值的选取是按照直方图来选择的,至于选取多少就要自己定义了,这里我测试了几种不同的取值,结果分别如下:
    (50,150)
    在这里插入图片描述
    (100,200)
    在这里插入图片描述
    (20,100)
    在这里插入图片描述
    如果边缘像素的梯度值高于高阈值,则将其标记为强边缘像素;如果边缘像素的梯度值小于高阈值并且大于低阈值,则将其标记为弱边缘像素;如果边缘像素的梯度值小于低阈值,则会被抑制。

  6. 边缘检测
    首先判断该点是否超过高阈值,然后判断该点的8邻域点中寻找满足超过低阈值的点,再根据此点收集新的边缘,直到整个图像边缘闭合。整个图像找完后,将非边缘点剔除,即灰度值置0.

完成了以上六步,Canny边缘检测算法就完成了,实测效果也挺不错的。


代码自取

// CVE7(2).cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "StdAfx.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
int main(int argc, char** argv)
{
	//声明IplImage指针
	IplImage* img = NULL;
	IplImage* cannyImg = NULL;
	//char *filename;
	//filename = "图片1.png";
	img = cvLoadImage("E:/C++/CVE7(2)/图片1.png", 1);
	//载入图像,强制转化为Gray
	if ((img = cvLoadImage("E:/C++/CVE7(2)/图片2.jpg", 0)) != 0)
	{
		//为canny边缘图像申请空间
		cannyImg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
		//canny边缘检测
		cvCanny(img, cannyImg, 20, 100, 3);
		//创建窗口
		cvNamedWindow("src", 1);
		cvNamedWindow("canny", 1);
		//显示图像
		cvShowImage("src", img);
		cvShowImage("canny", cannyImg);
		cvWaitKey(0); //等待按键
					  //销毁窗口
		cvDestroyWindow("src");
		cvDestroyWindow("canny");
		//释放图像
		cvReleaseImage(&img);
		cvReleaseImage(&cannyImg);
		return 0;
	}
	return -1;
}



猜你喜欢

转载自blog.csdn.net/Godsolve/article/details/83834508