Canny边缘检测原理及C#程序实现 您所在的位置:网站首页 边缘检测方法的原理 Canny边缘检测原理及C#程序实现

Canny边缘检测原理及C#程序实现

2024-06-26 15:18| 来源: 网络整理| 查看: 265

原文: Canny边缘检测原理及C#程序实现

    Canny边缘检测是被公认的检测效果最好的边缘检测方法,是由John F. Canny于1986年提出,算法目标是找出一个最优的边缘检测的方法,所谓最优即:1.好的检测:算法能够尽可能的标识出图像的边缘;2.好的定位:标识出的边缘要尽可能的与实际边缘相接近;3.最小响应:图像中的边缘只能标识一次,并且不能把噪声标识成边缘。同时我们也要满足3个准则:信噪比准则、定位精度准则、单边缘响应准则。

    Canny边缘检测算法可分为4步:

    高斯滤波器平滑、计算梯度、非极大值抑制、双阈值边缘检测和边缘连接。

    (经典不会随着时间褪色,算法也是一样)

    下面将逐步讲解并给出程序:

    第一步:高斯平滑

    为什么要对图像(灰度图像)进行高斯平滑预处理呢?高斯滤波器对去除服从正态分布的的噪声很有效,我做过实验,随着高斯模板的增大,被识别的边缘会逐渐减少,所以通过选着适合大小的高斯模板平滑,可以比较有效的去除一些伪边缘点。

    第二步:计算梯度

    首先,由一阶导数算子(一般用sobel模板)计算灰度图像每个像素点在水平和竖直方向上的导数Gx、Gy,得出梯度向量(Gx,Gy),计算梯度的值G和方向theta:

        G=sqrt(Gx*Gx+Gy*Gy)  theta=arctan(Gy/Gx)

然后,将每个像素点的梯度的值和方向分别放入两个数组中,程序如下:

byte[] orients = new byte[width * height];// 梯度方向数组 float[,] gradients = new float[width, height];// 梯度值数组 double gx, gy; for (int i = 1; i < (height - 1);i++ ) { for (int j = 1; j < (width - 1); j++) { //求水平和竖直导数 gx = bufdata[(i - 1) * width + j] + bufdata[(i + 1) * width + j] - bufdata[(i -1) * width + j - 1] - bufdata[(i + 1) * width + j - 1]+ 2*(bufdata[i * width + j + 1] - bufdata[i * width + j - 1]); gy = bufdata[(i - 1) * width + j - 1] + bufdata[(i + 1) * width + j + 1] - bufdata[(i + 1) * width + j - 1] - bufdata[(i + 1) * width + j + 1]+ 2*(bufdata[(i - 1) * width + j] - bufdata[(i + 1) * width + j - 1]); gradients[j, i] = (float)Math.Sqrt(gx * gx + gy * gy); if (gx == 0) { orientation = (gy == 0) ? 0 : 90; } else { double div = (double)gy / gx; if (div < 0) { orientation = 180 - Math.Atan(-div) * toAngle; } else { orientation = Math.Atan(div) * toAngle; } //只保留成4个方向 if (orientation < 22.5) orientation = 0; else if (orientation < 67.5) orientation = 45; else if (orientation < 112.5) orientation = 90; else if (orientation < 157.5) orientation = 135; else orientation = 0; } orients[i*width+j] = (byte)orientation; } }

 

     第三步:非极大值抑制

     如果直接把梯度作为边缘的话,将得到一个粗边缘的图像,这不满足上面提到的准则,我们希望得到定位准确的单像素的边缘,所以将每个像素点的梯度与其梯度方向上的相邻像素比较,如果不是极大值,将其置0,否则置为某一不大于255的数,程序如下:

float leftPixel = 0, rightPixel = 0; for (int y = 1; y


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有