(2)寻找图像中的亮度梯度
图像中的边缘可能会指向不同的方向,所以 Canny 算法使用 4 个 mask 检测水平、垂直以及对角线方向的边缘。原始图像与每个 mask 所作的卷积都存储起来。对于每个点我们都标识在这个点上的最大值以及生成的边缘的方向。这样我们就从原始图像生成了图像中每个点亮度梯度图以及亮度梯度的方向。
(3)在图像中跟踪边缘
较高的亮度梯度比较有可能是边缘,但是没有一个确切的值来限定多大的亮度梯度是边缘多大又不是,所以 Canny 使用了滞后阈值。
滞后阈值需要两个阈值——高阈值与低阈值。假设图像中的重要边缘都是连续的曲线,这样我们就可以跟踪给定曲线中模糊的部分,并且避免将没有组成曲线的噪声像素当成边缘。所以我们从一个较大的阈值开始,这将标识出我们比较确信的真实边缘,使用前面导出的方向信息,我们从这些真正的边缘开始在图像中跟踪整个的边缘。在跟踪的时候,我们使用一个较小的阈值,这样就可以跟踪曲线的模糊部分直到我们回到起点。
一旦这个过程完成,我们就得到了一个二值图像,每点表示是否是一个边缘点。一个获得亚像素精度边缘的改进实现是在梯度方向检测二阶方向导数的过零点 它在梯度方向的三阶方向导数满足符号条件。
其中 Lx, Ly ... Lyyy 表示用高斯核平滑原始图像得到的尺度空间表示 L计算得到的偏导数。用这种方法得到的边缘片断是连续曲线,这样就不需要另外的边缘跟踪改进。滞后阈值也可以用于亚像素边缘检测。
3.2.2 Canny算法在OpenCV中的应用
Canny算法在实际中处理效果十分理想,因而应用相当广泛。但Canny算法的实现和理论推导却相当复杂,因此前面也仅仅是介绍了算法的流程和设计思想。OpenCV中提供了实现Canny边缘检测算法的函数,应用这个函数可以快速高效地开发出具有实用价值的图像边缘检测程序。在OpenCV中实现Canny边缘检测算法的函数是cvCanny(),cvCanny()函数采用Canny算法发现输入图像的边缘,而且在输出图像中标识这些边缘。Threshold1和threshold2当中的小阈值用来控制边缘连接,大的阈值用来控制边缘的初始分割。其函数的完整声明如下:
void cvCanny( const CvArr* image, CvArr* edges, double threshold1,double threshold2, int aperture_size=3 );
--image 输入图像
--edges 输出的边缘图像
--threshold1 第一个阈值
--threshold2 第二个阈值
--aperture_size Sobel 算子内核大小
Canny算法通常处理的图像为灰度图,因此如果摄像机获取的是彩色图像,那首先就得进行灰度化。对一幅彩色图进行灰度化,就是根据图像各个通道的采样值进行加权平均。以RGB格式的彩图为例,通常灰度化采用的方法为:
Gray=0.299R+0.587G+0.114B;
其代码实现为:
for(i=0;i<cimg->height;i++)
for(j=0;j<cimg->width;j++)
gimgA[i][j]= (uchar)(cimgA[i][j].b*0.114 +
cimgA[i][j].g*0.587 + cimgA[i][j].r*0.299);
实验用图经红色标志提取、灰度变换和canny边缘检测效果如图5至图7所示:
图5 原始图像
图6 基于颜色的标志提取(红色标志)
图7 Canny边缘检测结果 基于Hough变换的静态交通标志检测方法研究(7):http://www.751com.cn/jisuanji/lunwen_7819.html