用Canny算子检测图像轮廓 - sumpig/OpenCV GitHub Wiki
Canny 算法可通过 OpenCV 的 cv::Canny 函数实现。
// 应用Canny 算法
cv::Mat contours;
cv::Canny(image, // 灰度图像
contours, // 输出轮廓
125, // 低阈值
350); // 高阈值
Canny 算子通常基于 Sobel 算子,虽然也可使用其他的梯度算子。它的核心理念是用两个不同的阈值来判断哪个点属于轮廓,一个是低阈值,一个是高阈值。
具体做法是在低阈值边缘分布图上只保留具有连续路径的边缘点,同时把那些边缘点连接到属于高阈值边缘分布图的边缘上。这样一来,高阈值分布图上的所有边缘点都被保留下来,而低阈值分布图上边缘点的孤立链全部被移除。这是一种很好的折中方案,只要指定适当的阈值,就能获得高质量的轮廓。这种基于两个阈值获得二值分布图的策略被称为 滞后阈值化,可用于任何需要用阈值化获得二值分布图的场景。但是它的计算复杂度比较高。
另外,Canny 算法在进行滞后阈值化之前,如果梯度幅值不是梯度方向上的最大值,那么对应的边缘点都会被移除。因此,这个方向上梯度的局部最大值对应着轮廓最大强度的位置。这是一个细化轮廓的运算,它创建的轮廓宽度只有一个像素。这也解释了为什么Canny 轮廓分布图的边缘比较薄。