版权声明:本文为博主原创文章,转载请标明出处 https://blog.csdn.net/C2681595858/article/details/85011951
一、实验内容
二、理论准备
-
什么是积分图?
- 图像I的积分图S是与其大小相同的图像,S的每一像素S(u,v)存储的是I(u,v)左上角所有像素的灰度值之和。如下图:
- 积分图可增量计算,只需对原图进行一边扫描。
- 图像I的积分图S是与其大小相同的图像,S的每一像素S(u,v)存储的是I(u,v)左上角所有像素的灰度值之和。如下图:
-
基于积分图的快速均值滤波具体执行方法
- 设滤波器模板大小为2w+1,滤波结果为图像O,则:
这里的 指的是滤波模板像素个数即 .
- 设滤波器模板大小为2w+1,滤波结果为图像O,则:
-
为什么这种滤波方式效率和窗口大小无关?这真的可以做到均值滤波吗?
- 首先我们用图示来看下它每一步都在做些什么:
- 参照上图来理解这个公式
。
首先S(u+w,v+w)是绿色框内所有灰度值之和,然后S(u-w-1,v-w-1)是黑色框内所有灰度值之和。他们两者相加就是绿色框所有灰度值之和其中黑色框被加了两次。然后S(u+w,v-w-1)是红色框内灰度之和,从之前的结果中减去红色框,由于黑色框被加了两次减去一次还剩一次,然后红色框内非黑色框部分被减掉了。然后S(u-w-1, v+w)黄色框部分,将剩余的一次黑色框减去,在减去黄色框非黑色框部分,左后就只剩下了背景为蓝色的部分刚好就是我们滤波模板所覆盖的部分像素值之和。然后再乘以1/z就是均值滤波。
- 首先我们用图示来看下它每一步都在做些什么:
-
什么时候进行边沿拓展?
- 在根据积分图计算最终图像时需要边缘拓展过的图像,那个什么时候进行边缘拓展比较合适呢?
- 有两个地方可以进行边缘拓展,第一个是计算积分图之前对原图像进行边缘拓展,第二个是对积分图进行边缘拓展。
- 这里为了加速滤波结果和不加速均值滤波结果相同,应该采取对原图像进行边缘拓展。
三、实验环境
- 操作系统及版本:windows10
- 编译软件及版本:vs2017+opencv
- 使用的计算机语言:c++
四、实验过程
- 就是把上面的理论转换成代码。
- 需要考虑下面一些问题:
1、 计算积分图的时候,下面公式中的v-1会导致数组越界访问,需要特殊处理。
2、进行滤波的时候,下面公式中有减号的项会导致数组越界访问,需要特殊处理。
实现代码:
基于积分图的快速均值滤波
五、实验结果
- 原图vs滤波后
六、实验总结
- 本来这次应该是最简单的实验,但我却把它做成了最复杂的实验,本来可以1小时完成的作业我却花了相当于一天时间,导致这个的原因是忽视数据类型,debug缺乏经验。
- 我写完代码,感觉非常良好,自信满满,觉得可以上交了,运行试下吧,结果如下:
直接不给我任何结果,很纳闷了,然后重新读代码,一遍又一遍,找不出什么问题啊。逻辑全正确,然后回想一下好像什么时候遇到过这种尴尬的场面。原因好像是float强制转int,导致0-1之间的数全0。好了完美,将车祸现场改成如下形式:
好了,这下总可以了吧。运行下:
- 我**不干了。。。。。。。。。。冷静冷静我们休息下再看。这一休息就是3天。
- 好吧,enjoy coding!终于再次发起冲锋,决心拿下敌方阵营。所以一开始直接用一张很小的图片,把每个中间结果输出来,然后手动验证。现场如下:分别输出边缘处理后图像灰度值,积分图,滤波后的图像灰度值。
经过计算验证,发现错误在滤波后的图像,所以着重看这部分代码。反复查看逻辑没问题,在输出每一个计算细节看哪里出问题了,最终发现还是上面那个式子出问题了。原因在于
红线地方少了一个左括号,导致计算出错,修改过来任务完成。 - 总结一下:细节很重要,特别是数据类型的转换导致精确度的变化,在这怎么细心都不为过。