计算机视觉作业二
代码文件
用CImg重写Code0文件夹中的canny.c和canny.h为canny.cpp和canny.h,并增加一个main.cpp文件作为图像数据输入并测试。
重写过程:首先替换原来的图像输入为CImg图像输入,以及对像素点的for循环更改为CImg版本cimg_forXY(),最后把原来的C语言struct结构体改成C++类。
canny.h文件
1 |
|
canny.cpp文件
1 |
|
main.cpp文件
1 |
|
测试数据
作业中有四张bmp图像,但这里限于篇幅,我以女神lena为例:
测试结果
修改算法参数后的测试结果
注意到程序中这个函数接收Canny边缘检测算法的相关参数,也就是调参主要是针对这几个参数:其中width和height为输入图像的宽度和高度,无需调整,所以一共有五个参数需要调整,分别为lowthreshold低阈值(默认2.5)、highthreshold高阈值(默认7.5)、gaussiankernelradius标准差(默认2.0)、gaussiankernelwidth高斯卷积核大小(默认16)、contrastnormalised图像是否需要归一化(默认0值表示不需要)。
lowthreshold低阈值
保持其他参数不变,修改低阈值后的测试结果如下:默认2.5。
分析:
可以看出,我们修改原程序中的lowthreshold低阈值后,比如改成0.1,低阈值减小,将会增加很多噪声;而改成6.0,低阈值增大,又会丢失很多强边缘像素。这与已知结论吻合:对于弱边缘像素(在低阈值和高阈值之间),这些像素可以从真实边缘提取也可以是因噪声或颜色变化引起的。为了获得准确的结果,应该抑制由后者引起的弱边缘像素。因此需要调整低阈值参数。
highthreshold高阈值
保持其他参数不变,修改高阈值后的测试结果如下:默认7.5。
分析:
可以看出,我们修改原程序中的highthreshold高阈值后,比如改成3.0,高阈值减小,此时将会增加很多强边缘像素,因为大于3的像素点将被确定为边缘;而改成10.0,高阈值增大,原来的强边缘像素大部分会转化为弱边缘像素,丢失一部分边缘像素点。这与已知结论吻合:被划分为强边缘的像素点已经被确定为边缘,因为它们是从图像中的真实边缘中提取出来的。
gaussiankernelradius标准差
保持其他参数不变,修改标准差后的测试结果如下:默认2.0。
分析:
可以看出,我们修改原程序中的gaussiankernelradius标准差后,比如改成1.0,标准差减小,为标准正态分布,此时将会增加很多噪声,高斯滤波平滑效果不好,表现为噪声过多;而改成4.0,标准差增大,原来的强边缘像素大部分被误认为噪声,因此将会被丢弃,造成边缘缺失,高斯滤波平滑效果也不好。这与已知结论吻合:为了平滑图像,使用高斯滤波器与图像进行卷积,该步骤将平滑图像,以减少边缘检测器上明显的噪声影响。
gaussiankernelwidth高斯卷积核大小
保持其他参数不变,修改高斯卷积核大小后的测试结果如下:默认16。
分析:
可以看出,我们修改原程序中的gaussiankernelwidth高斯卷积核大小后,比如改成7,发现两张边缘检测图其实没变化,说明原程序中高斯卷积核大小16已经过大,将会浪费内存空间,其实为7就有同样的效果了;而改成5,高斯卷积核大小为5也是比较推荐的折中,再看改成3,此时丢失了很多边缘像素,即误认为噪声,对噪声的敏感度较大。这与已知结论吻合:高斯卷积核大小越大,检测器对噪声的敏感度越低,但是边缘检测的定位误差也将略有增加。
contrastnormalised图像是否需要归一化
保持其他参数不变,修改该参数后的测试结果如下:默认0。
分析:
可以看出,我们修改原程序中的contrastnormalised为1后,此时程序将会先对图像矩阵进行归一化处理,对照原图,我发现归一化会丢失一些比较暗、比较模糊的像素,在这种情况下做边缘检测时这些像素点都会被忽略,不会被认为是边缘。
Canny边缘检测算法总结
Canny边缘检测算法可以分为以下5个步骤:
- 使用高斯滤波器,以平滑图像,滤除噪声。
- 计算图像中每个像素点的梯度强度和方向。
- 应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应
- 应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
- 通过抑制孤立的弱边缘最终完成边缘检测。