
在: 中,我们主要讨论使用sobel算子和Laplace变换进行边缘检测. 其中,主要使用对梯度大小进行阈值化以获得二值边缘图像的方法. 在图像中,边缘通常包含重要的视觉信息,因为它们勾勒出图像元素的轮廓. 但是,仅使用简单的二进制边缘图像有两个主要缺点:
使用此方法检测到的边缘太厚,这意味着很难准确定位对象. 很难找到这样的阈值,该阈值可以检测所有足够低的重要边缘,并且同时不包含太多次的边缘.
这两个问题正是本节中使用的Canny算法试图解决的问题.

Canny运算符通常基于sobel运算符(尽管也可以使用其他梯度运算符),其核心思想是使用两个不同的阈值来确定哪些点属于轮廓,以便将两个阈值分别划分获得两个边缘贴图. 此后,Canny算法将两个边缘贴图组合在一起以生成“最佳”轮廓图. 如果存在连续的边缘点,则将低阈值图像中的边缘点与高阈值图像中的边缘相连,然后保留低阈值图像中的边缘点. 这种使用双阈值获取二进制图像的策略称为磁滞阈值.
Canny算法对选择两个阈值有一定要求. 对于较低的阈值,它应包括被认为属于明显图像轮廓的所有边缘像素. 较高阈值的作用应该是定义属于所有重要轮廓的边缘,并且应排除所有异常值.
在OpenCV中,实现Canny算法的函数是cv :: Canny. 该函数的调用方法如下:

cv::contours;
cv::Canny(image, // 输入的灰度图像
contours, // 输出轮廓
125, // 低阈值
200); // 高阈值
主要代码如下,直接将其添加到主要功能中
#include <QCoreApplication>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
cv::Mat image = cv::imread("c:/peng.jpg", 0);
if(!image.data)
{
qDebug() << "No input image";
}
cv::Mat result;
cv::Canny(image, result, 150, 220);
cv::namedWindow("Original Image");
cv::imshow("Original Image", image);
cv::namedWindow("Canny Result");
cv::imshow("Canny Result", result);
return a.exec();
}

效果:

以下是Sobel运算符的输出效果:


与Sobel运算符相比canny算子边缘检测原理,Canny运算符可以获得更细的边缘,因为Canny算法使用其他策略来提高图像质量. 在使用滞后阈值之前canny算子边缘检测原理,应去除梯度大小不是最大值的所有边缘点. 这样,渐变的方向始终垂直于边缘,因此该方向上的局部渐变最大值对应于轮廓强度最高的点. Canny算法适用于不同场合. 其参数允许根据不同实现的特定要求进行调整,以识别不同的边缘特征.
此外,Canny算法包含许多可调参数,这将影响算法的计算时间和有效性.
高斯滤波器的大小: 第一步中使用的平滑滤波器将直接影响Canny算法的结果. 较小的滤镜也会产生较少的模糊,因此可以检测到变化较小的细线. 较大的滤镜也会产生更多的模糊效果. 将图像的较大区域绘制为特定点的颜色值. 这样的结果对于检测较大的平滑边缘(例如彩虹边缘)更有用.
阈值: 使用两个阈值比使用一个阈值更灵活,但是阈值仍然存在一些常见问题. 如果阈值设置得太高,可能会丢失重要信息;如果阈值太低,则分支信息将被认为是重要的. 很难给出适用于所有图像的通用阈值. 当前没有经过验证的实现方法.
本文来自本站,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-250359-1.html
……