赞
踩
离散值的导数使用差分代替:
所以:
以(x, y)为中心点,在水平和垂直方向上应用拉普拉斯算子,滤波器(对应a=1的情况)为:
这个滤波器在90°方向上是各向同性的,但在45°方向上不是。而拉普拉斯算子具有旋转不变性,所以在
°方向上也应该具有各向同性,所以再在45°方向上应用拉普拉斯算子(对应a=0.5的情况):
同理:
常用的5*5滤波器模板为
使用公式13,带入并归一化后可以算出:
使用Prewitt,Sobel,Canny,FDoG算子处理三张以上图片,分析并比较结果。
图1
图2
图3
图4
图5
prewitt算子和sobel算子都是一阶导数算子,只对图像求一阶导数,返回梯度值,而非0-1边界,所以图像较为平滑,并且有明暗灰度的变化,越明显的边界,在图中越亮,也就是梯度值越大。相比较的话, sobel算子的表现力更好一些,因为考虑了局部性原则,对像素点附近的像素附加了更大的权重,所以能更好的还原图像局部细节,如图3的左眼,图1图2的鼻梁;而prewitt算子是平均滤波,所以图像的灰度更加平均,二者在速度上没有什么差异。
Canny算子和FDoG算子都是返回的0-1边界,但是不同之处在于Canny算子进行了非极大值抑制,边界是一个像素宽的,FDoG的边界是多像素。FDoG处理过程中会将不明确的边界方向按邻居的方向来补全,所以边界具有更好的连续性,如图4中脸的左下边界。并且FDoG对于文字的边界能够几乎完整的识别出来,但是Canny的文字边界则是模糊不可辨认的,可能是由于FDoG识别图像的切线而文字较为连续。但是图4中FDoG对于山的边缘识别效果 差,山顶、边缘的山脉边界和雪线都没有识别出来,Sobel识别效果 好,山顶梯度值很高,雪线的边界明显。FDoG还倾向于把边缘连接成线,如图4右下角的草丛。图5中FDoG效果 差,将岩石的纹理全都识别为了边界,并且导致左下角草丛和山的边界不可辨认,而Canny算子效果稍好一些,Prewitt和Sobel算子效果 好。
两者也都具有一些问题,如把纹理识别为边界,如图3卫衣的帽子,这部分在Prewitt和Sobel中也具有较高的梯度值,应该是由于前面较暗,后面较亮,所以对比强烈被误认为了边界。有的边界也没有被识别出来,如图2的衣服图5后面的山脉,同样在Prewitt和Sobel算子中这个边界也并不明显,因为皮肤和白衣服的颜色、雪山和天空的颜色非常相近,所以这个边界的梯度值较小。在处理过程中,Canny的速度要慢得多,因为步骤繁琐,并且是对每个像素逐点计算的。
对FDoG的参数进行修改:
修改循环次数和有无高斯滤波
直观来看,循环次数对结果的影响并不大。仔细观察的话,可以发现随着循环次数的增多,图像识别出了更多细微的边缘。
个高斯值的差也会随之变化
也就是上式中的f(t)变化,由于没有进行非极大值抑制,边界像素点的数目就会增多,所以导致结果的线条粗细发生变化。
修改的值,论文中默认为3.0
的变化对结果的影响也不明显,主要是边界线条会有更多的延伸, 出现在最后一次积分中:
论文中也解释到控制"flow kernel"的拉长程度,所以 增大时,G会减小,然后在 后的阈值判断中,小于阈值的像素点被认为是边界,这导致了会有更多的像素点成为边界,也就表现为线条的拉伸。
使用论文中的两个测试用例如下,效果并不好,并且通过修改给定的那几个参数并没有显著提升。应该是在构建ETF时就没有构建好圆形的切线方向,后续的调参都是在ETF的基础上进行的,所以并没有改善结果。
为了测试这几种算子的分类效果,使用了伯克利大学提供的这个数据集可以用来进行图像分割和图像边缘检测,数据集中的ground truth是人工标记的。这里将数据集中给定的ground truth标注信息绘制成为黑白边界图像,如下所示。
然后对数据集中的图片应用四种边缘检测算子,与ground truth的结果进行对比,计算准确率、精准率、召回率和F-score。
准确率 | 精准率 | 召回率 | F-score | |
Prewitt | 0.883 | 0.914 | 0.967 | 0.940 |
Sobel | 0.909 | 0.913 | 0.995 | 0.953 |
Canny | 0.769 | 0.916 | 0.840 | 0.877 |
FDoG | 0.754 | 0.926 | 0.822 | 0.871 |
FDoG+NMS | 0.894 | 0.914 | 0.979 | 0.945 |
加入非极大值抑制之后,FDoG的F1-score和准确率都有了较大提升,这是因为ground truth中的边界是单像素宽的,如果不加非极大值抑制FDoG的结果会过宽,影响正确率。准确率不够高的另一个原因是 ground truth中只有真正的物体边界曲线而且有一些边界并没有标注(如上图上侧的横向边界),而不论是什么算子都会有一些纹理被识别成边界,造成误差。
结果如下:
为了将结果边界线条变为1像素宽,需要在上面(16)(17)式之间进行非极大值抑制(NMS),也就是对图(d) 中-T~T方向上积分的结果进行非极大值抑制,使得原本作为边界的多个像素点中只保留一个作为边界,然后正常的进行-S~S方向上的积分得到结果。
在fdog.cpp中的GetFDoG()函数里添加NMS()函数:
NMS()实现的主要代码如下所示:
- max = dog[i][j]; //记录当前点的DoG值
- for (s = -half;s <= half;s++) { //对[-s, s]的点进
- 行比较
- x = d_x + vn[0] * s;
- y = d_y + vn[1] * s;
-
- if (x > (double)image_x - 1 || x<0.0 || y>(double)image_y - 1 ||
- y < 0.0)
- continue;
- x1 = round(x);
- if (x1 < 0) x1 = 0; if (x1 > image_x - 1) x1 = image_x - 1;
- y1 = round(y);
- if (y1 < 0) y1 = 0; if (y1 > image_y - 1) y1 = image_y - 1;
- val = dog[x1][y1];
-
- if (val < max) {
- sign = 0;
- break;
- }
- }
- if (sign == 0) { //作为局部极小值时才会被保留,否则
- 255(白色)
- dog[i][j] = 255;
- }
虽然叫作非极大值抑制,但是从原本的实现中可以知道, 终结果小于阈值时才会保留为边界,否则赋值为白色(非边界)。所以实际上是需要判断当前值是否为局部 小值,如果是的话保留,否则赋一个比较大的值,让这个像素点作为白色的背景。
在实现完非极大值抑制功能后,为了得到上面比较好的结果,需要进行调参。在给定的几个参数中sm3 的效果较为明显,当把sm3调小时结果会变好,否则边界曲线会断断续续,如下所示:
CS专业的学生相对于其他专业来说,对于底层知识掌握的更多、更扎实。所谓的“底层”也就是操作系统、汇编、编译原理、体系结构等知识,因为相对来说,其他专业的学生不会主动去学习这些知识。并且这部分知识比较“硬核”,在专业课里也算是比较难的部分。通常其他专业转CS会从见效快的部分学习,如Python,java,web开发等等。计算机科班出身的学生可能也会更有编程的思想,也就是会考虑如何通过写代码来实现某项计算,比如求三角函数就可以用级数展开来模拟。
CS专业对于其他专业的劣势在于他们具有自己的领域背景知识,如生物信息学需要生物知识、许多加密算法需要数学知识、银行金融类的开发也需要相应领域知识。使用编程语言本身其他专业的未必会比计科专业的差,所以在指定领域的开发中其他专业学生甚至有可能更有竞争力。尤其是一些培训班出来的学生,对某种语言的掌握程度可能会比很多计科本科生要好。这当然也是他们的劣势,因为他们大部分也是“追热点”学习, 近就有各行业的人学习人工智能,当这个热点过去后,他们可能掌握的知识就不足以应对新的要求,但是计科的学生对计算机方向的知识有比较好的学习能力,可以学习新的热点方向。
完整的代码:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。