个人博客地址:滤波器——BoxBlur均值滤波及其快速实现

动机:卷积核、滤波器、卷积、相关

在数字图像处理的语境里,图像一般是二维或三维的矩阵,卷积核(kernel)和滤波器(filter)通常指代同一事物,即对图像进行卷积或相关操作时使用的小矩阵,尺寸通常较小,常见的有3*3、5*5、7*7等。卷积操作相当于对滤波器旋转180度后的相关操作,如下图所示,但很多滤波器是中心对称的,而且两者运算上可以等价,所以很多时候不太区分。

设计不同的滤波器,可以达到去噪(denoising)、平滑(smoothing)、模糊(blurring)、锐化(sharpening)、浮雕(embossing)、边缘检测(edge detection)等目的。在空域中直接进行卷积操作(滑动窗口),需要4层循环嵌套,复杂度达到\(O(m^2*n^2)\),\(m\)为图像尺寸,\(n\)为滤波器尺寸,随着图像或卷积尺寸增大,复杂度以平方快速增长,因此需要一些快速实现方式,尤其是在计算资源并不充足的嵌入式等端上。

Box Blur

均值滤波器可能是最基本最常见的滤波器了,一个3*3的均值滤波器如1所示,使用该滤波器对图像进行滤波,相当于对图像中的每一个像素使用其周围的像素进行平均。均值滤波器用途广泛,除最直接的平滑操作外,还可近似实现其他滤波操作,比如带通滤波高斯平滑等。因为均值滤波器在频域近似为一个低通滤波器,因此两个不同半径的均值滤波器滤波结果的差值可近似带通滤波器;根据中心极限定理,多次Box Blur的结果可近似高斯平滑。应用得越广泛就越需要仔细优化,可以采用均值滤波器来近似实现其他滤波器的一个前提就是均值滤波可以更高效。
\[
\frac{1}{9}
\left[
\begin{matrix}
1 & 1 & 1 \\
1 & 1 & 1 \\
1 & 1 & 1
\end{matrix}
\right] \tag{1}
\]

直接实现四层循环的均值滤波复杂度为\(O(m^2*n^2)\),可以利用均值滤波器所有权重都相同等性质实现快速滤波。

行列分解实现

可将卷积核分解为列向量和行向量的相乘,如2所示,对图像进行2D的均值滤波,等价于先逐行进行平均然后逐列平均,复杂度可由\(O(m^2*n^2)\) 降至\(O(m^2*2n)\) 。这样实现的前提是卷积核可分解,换句话说,可分解的卷积核均可考虑这样优化,比如高斯滤波等。
\[
\frac{1}{9}
\left[
\begin{matrix}
1 & 1 & 1 \\
1 & 1 & 1 \\
1 & 1 & 1
\end{matrix}
\right] = \frac{1}{3}
\left[
\begin{matrix}
1 \\
1 \\
1
\end{matrix}
\right]
\cdot
\frac{1}{3}
\left[
\begin{matrix}
1 & 1 & 1 \\
\end{matrix}
\right] \tag{2}
\]

类“队列”实现

行列分解后,相当于在行上和列上进行1D滑动窗口均值滤波。在1D窗口滑动过程中,相邻窗口有大量元素是重叠的,比如下图中,8、5、10和5、10、7其中5和10就是重叠的。整个滑动过程可以看成是不断进出“队列”的过程,窗口每向右移动1个像素,相当于最左侧的像素出队列,最右侧的像素进队列,当前像素的滤波结果为当前队列内元素之和然后平均,而前后一直驻留在队列中的元素则不需要重复加和,通过避免重复计算来实现提速。

因此,计算第\(i+1\) 个窗口的和\(S[i+1]\)可以通过第\(i\) 个窗口的和\(S[i]\)与最左\(x[i-r]\)最右\(x[i+r+1\)的元素得到,\(r\) 为滤波器半径,如下:
\[S[i+1] = S[i] + x[i+r+1] - x[i-r]\]
这样,我们得到了与滤波器尺寸无关的算法,算法复杂度进一步降低至\(O(m^2)\) 。

此外,我们也可考虑2D的滑动窗口,如下图所示:

同样利用相邻滑动窗口内的重叠元素,计算以元素\((i, j)\) 为中心的窗口元素之和\(S[i, j]\) 如下,其中\(C[i, j]\)为窗口内以\((i, j)\)为中心的半径为\(r\)的列和,
\[S[i, j] = \sum_{k=-r}^{+r} C[i, j+k]\]

窗口向右移动时,
\[S[i, j+1] = S[i, j] + C[i, j+r+1] - C[i, j- r]\]

窗口向下移动时,
\[C[i+1, j] = C[i, j] + C[i+r+1, j] - C[i-r-1, j]\]

滤波结果为:
\[x'[i, j] = \frac{1}{(2r+1)^2} S[i, j]\]

积分图

如果需要得到多个不同半径的均值滤波结果时,使用积分图(Summed-area table)可能是个好办法。积分图中\((x, y)\) 位置\(I(x, y)\)的值等于原图中该位置左上角所有像素之和,累加和包不包含这个像素自身所在的行和列与具体实现有关,这里沿用Wiki上的表述方式包含(Opencv为不包含),计算方式如下:
\[I(x, y) = \sum_{x'\le x, \ y' \le y}i(x', y')\]

积分图可通过单趟遍历快速实现,有了积分图就可以计算任意尺寸box内元素之和,仅需2次减法和1次加法常数次运算,如下:

这样,当需要不同尺寸均的值滤波结果时,使用积分图的运算时间是一样的。

指令级优化

除了以上优化方法,还可采用指令级优化。对每一个像素位置求均值是在该像素的邻域范围内进行的,同一行上的像素位于连续的内存区域,对像素施加的都是近乎相同的操作——加法或减法,因此时宜采用SIMD指令,如MMX、SSE、AVX、NEON等,同时载入多个数据、同时对多个数据进行相同的操作,一些实现方式可参见 参考资料,这里不再详述。需要注意的是,指令级的优化意味着兼容性、可扩展性的损失,如果代码尚未稳定,则不建议采用

一些优缺点和总结

这里简单分析下各种方法的优缺点:

  • 类“队列”实现:不能实现in-place操作,如果内存空间不足,可缓存一个窗口高度图像宽度的内存块,在缓存块操作后再写回原图。
  • 积分图方法:需要较大的内存来存储积分图,好处是积分图仅需求取一次,后面所有尺寸的Box Blur均可使用,而且求各处的滤波结果互不依赖,方便并行化。

基本上所有的优化方式的出发点都是减少不必要的重复计算,本文所介绍的几种方法在其他滤波操作的优化中也常被采用。以上仅为算法思路介绍,具体实现时可能要进一步考虑内存访问的时间、边界处理等细节,不再赘述。

参考

滤波器——BoxBlur均值滤波及其快速实现的更多相关文章

  1. 学习 opencv---(7) 线性邻域滤波专场:方框滤波,均值滤波,高斯滤波

    本篇文章中,我们一起仔细探讨了OpenCV图像处理技术中比较热门的图像滤波操作.图像滤波系列文章浅墨准备花两次更新的时间来讲,此为上篇,为大家剖析了"方框滤波","均值滤 ...

  2. 基础图像处理之混合空间增强——(Java:拉普拉斯锐化、Sobel边缘检测、均值滤波、伽马变换)

    相信看过冈萨雷斯第三版数字图像处理的童鞋都知道,里面涉及到了很多的基础图像处理的算法,今天,就专门借用其中一个混合空间增强的案例,来将常见的几种图像处理算法集合起来,看能发生什么样的化学反应 首先,通 ...

  3. java实现中值滤波均值滤波拉普拉斯滤波

    目录 来对下面的图像滤波,其实就是对各个像素点进行数学运算的过程 均值滤波 中值滤波 拉普拉斯滤波 Sobel滤波 注意 来对下面的图像滤波,其实就是对各个像素点进行数学运算的过程 均值滤波 均值滤波 ...

  4. 图像处理之均值滤波介绍及C算法实现

    1 均值滤波介绍 滤波是滤波是将信号中特定波段频率滤除的操作,是从含有干扰的接收信号中提取有用信号的一种技术. 均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临 ...

  5. opencv —— boxFilter、blur、GaussianBlur、medianBlur、bilateralFilter 线性滤波(方框滤波、均值滤波、高斯滤波)与非线性滤波(中值滤波、双边滤波)

    图像滤波,指在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像与处理中不可缺少的操作. 邻域算子,指利用给定像素及其周围的像素值,决定此像素的最终输出值的一种算子.线性邻域滤波器就是一种常 ...

  6. opencv-10-图像滤波-噪声添加与均值滤波-含opencv C++ 代码实现

    开始之前 再说上一篇文章中, 我们想按照噪声产生, 然后将降噪的, 但是限于篇幅, 我就放在这一篇里面了, 说起图像的噪声问题就又回到了我们上一章的内容, 把噪声当作信号处理, 实际上数字图像处理实际 ...

  7. OpenCV计算机视觉学习(4)——图像平滑处理(均值滤波,高斯滤波,中值滤波,双边滤波)

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice &q ...

  8. opencv实现图像邻域均值滤波、中值滤波、高斯滤波

    void CCVMFCView::OnBlurSmooth()//邻域均值滤波 { IplImage* in; in = workImg; IplImage* out = cvCreateImage( ...

  9. 基于FPGA的均值滤波算法的实现

    前面实现了基于FPGA的彩色图像转灰度处理,减小了图像的体积,但是其中还是存在许多噪声,会影响图像的边缘检测,所以这一篇就要消除这些噪声,基于灰度图像进行图像的滤波处理,为图像的边缘检测做好夯实基础. ...

随机推荐

  1. Windows Ubuntu Bash申请免费通配符证书(Let's Encrypt)并绑定IIS

    什么是 Let’s Encrypt? 部署 HTTPS 网站的时候需要证书,证书由 CA 机构签发,大部分传统 CA 机构签发证书是需要收费的,这不利于推动 HTTPS 协议的使用. Let’s En ...

  2. 数字类型——python3

    今天我为各位小伙伴准备了python3中数字类型,希望能够帮助到你们! Python 数字数据类型用于存储数值. 数据类型是不允许改变的,这就意味着如果改变数字数据类型的值,将重新分配内存空间. 以下 ...

  3. eclipse中去掉py文件中烦人的黄色弹框

    eclipse中写py文件,当鼠标点击在参数上时总是出现黄线的弹框,影响人操作,感觉特别烦,如下: 解决方案: windows--preferences--hover--pydev--hover取消选 ...

  4. MYSQL—— 基础入门,增、删、改、查(基础篇)

    首先呢,先解释一下基本的概念,心里最起码知道就ok啦!其余更多的了解,得另查看喽! (1)什么是sql? sql:指结构化查询语言,有能力访问数据库,是一种ANSI(美国国家标准话组织)的标准计算机语 ...

  5. EffictiveC++笔记 第2章

    Chapter 2 构造 / 析构 / 赋值 条款 05:了解C++ 默默编写并调用哪些函数 如果你写下: class Empty{ }; 事实上编译器会帮你补全: class Empty{ publ ...

  6. volatile可见性的一些认识和论证

    一.前言 volatile的关键词的使用在JVM内存模型中已是老生常谈了,这篇文章主要结合自己对可见性的一些认识和一些直观的例子来谈谈volatile.文章正文大致分为三部分,首先会介绍一下happe ...

  7. 隐马尔可夫模型(HMM)总结

    摘要: 1.算法概述 2.算法推导 3.算法特性及优缺点 4.注意事项(算法过程,调参等注意事项) 5.实现和具体例子 6.适用场合 内容: 1.算法概述 隐马尔科夫模型(Hidden Markov ...

  8. 用keras实现人脸关键点检测(2)

    上一个代码只能实现小数据的读取与训练,在大数据训练的情况下.会造内存紧张,于是我根据keras的官方文档,对上一个代码进行了改进. 用keras实现人脸关键点检测 数据集:https://pan.ba ...

  9. Telerik控件集-2019.R1.SP1.All

    Telerik 专注于微软.Net平台的表示层与内容管理控件,提供高度稳定性和丰富性能的组件产品DevCraft,并可应用在非常严格的环境中.Telerik拥有 Microsoft, HP, Alco ...

  10. 描述性统计指标 - 众数 Mode

    定义- 数值型数据 - 出现频数最多的变量值- 品质型数据.单项式分组数据 - 频数最多的组为众数组,该组的变量值(类型)就是众数- 组距式分组数据 - 频数最多的组为众数组,通过公式求得众数 - 公 ...