原理:通过图像信号函数的极大值来判定图像的边缘像素点。
最优边缘检测主要以下面三个参数为评判标准:
低错误率:标识出尽可能多的实际边缘以及减少噪声产生。
高定位性:表示出边缘要与图像中的实际边缘尽可能接近。
最小响应:图像的边缘标记具有唯一性,虚假响应边缘应该得到最大抑制。
目录
(一)Canny的原理
检测步骤:
-
消除噪声
边缘检测的算法主要是基于图像强度的一阶和二阶微分操作,但导数通常对噪声很敏感,边缘检测算法常常需要根据图像源的数据进行预处理操作,因此必须采用滤波器来改善与噪声有关的边缘检测的性能。
这个预处理就是操作,就是在进行Canny算子边缘检测前,应当先对原始数据进行高斯模板进行卷积操作,可得到的图像与原始图像相比有些轻微的模糊。
通常使用高斯平滑滤波器卷积降噪:

消除噪声的代码如下:
CV::GausssianBlur(src,image,Size(3,3),1.5);
-
计算幅度与方向
梯度可以使用一阶有限差分,也就是上一篇文章讲述过的图像在x和y方向上偏导数的两个矩阵,用一对卷积阵列分布作用于对应的水平与垂直方向。Canny算子中使用的sobel模板如下:

Gx为水平x方向掩码模板,Gy为垂直y方向掩码模板,K为邻域标记矩阵。
那么可以根据上面三个矩阵,可计算出图像梯度幅值以及相应的方向:

那么梯度的方向近似到四个可能的角度之一,一般取值为0,45,90,135。分别取其atan系数,就可以遍历图像了。
那么计算梯度幅值与方向如代码如下所示:
//使用Sobel计算相应的梯度幅值及方向
cv::Mat magX = cv::Mat(src.rows,src.cols,CV_32F);
cv::Mat magY = cv::Mat(src.rows,src.cols,CV_32F);
cv::Sobel(image,magX,CV_32F,1,0,3);
cv::Sobel(image,magY,CV_32F,0,1,3);
//计算斜率
cv::Mat slopes = cv::Mat(image.rows,image.cols,CV_32F);
divide(magY,magX,slopes);
//计算每个点的梯度
cv::Mat sum = cv::Mat(image.rows,image.cols,CV_64F);
cv::Mat prodX = cv::Mat(image.rows,image.cols,CV_64F);
cv::Mat prodY = cv::Mat(image.rows,image.cols,CV_64F);
//平方
multiply(magX,magY,prodX);
multiply(magY,magY,prodY);
sum = prodX + prodY;
//开平方,求出G
sqrt(sum,sum);
cv::Mat magnitude = sum.clone();
-
非极大值抑制
在上一篇边缘检测的文章中是有做介绍的,在Canny算法中,非极大值抑制是进行边缘检测的重要步骤。
非极大值抑制通俗的讲是这样的:
寻找像素点局部的最大值,将非极大值点所对应的灰度值设置为背景像素点,像素领域区域满足梯度值的局部最优值判断为该像素的边缘,对其余非极大值的相关信息进行抑制,利用该准则可以剔除大部分非边缘点。
那么利用程序可以这么写:
//非极大值抑制
void nonMaximumSuppression(Mat &magnitudeImage,
Mat &directionImage)

Canny边缘检测算法是一种经典的图像处理技术,通过高斯滤波消除噪声、计算梯度幅度与方向、非极大值抑制及滞后阈值处理来找到图像边缘。该算法旨在降低错误率、提高定位性和最小化响应,确保边缘检测的准确性。本文详细介绍了Canny算子的步骤,包括预处理、梯度计算、非极大值抑制和阈值处理,以及在实际应用中的实现和效果。
最低0.47元/天 解锁文章
1万+

被折叠的 条评论
为什么被折叠?



