个人博客地址:滤波器——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. BZOJ_1029_ [JSOI2007]建筑抢修_贪心+堆

    BZOJ_1029_ [JSOI2007]建筑抢修_贪心+堆 Description 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是 ...

  2. 用Fundebug插件记录网络请求异常

    在服务端,不管我们使用Node.js.Java.PHP还是Python等等,都会用日志以文本的形式记录请求以及报错信息.这个对于后端做事后分析是很有用的. 另一方面,前端有时候出问题其实是因为后端接口 ...

  3. Spring Boot之WebSocket

    一.项目说明 1.项目地址:https://github.com/hqzmss/test01-springboot-websocket.git 2.IDE:IntelliJ IDEA 2018.1.1 ...

  4. 开源方案搭建可离线的精美矢量切片地图服务-3.Mapbox个性化地图定制入门

    1.简介 mapbox是一家非常牛的公司,比如像特斯拉.DJI大疆创新.孤独星球.Airbnb.GitHub.Cisco.Snap.飞猪.Keep.Bosch这些在国内外各自领域中响当当的企业都是它的 ...

  5. ConcurrentDictionary并发字典知多少?

    背景 在上一篇文章你真的了解字典吗?一文中我介绍了Hash Function和字典的工作的基本原理. 有网友在文章底部评论,说我的Remove和Add方法没有考虑线程安全问题. https://doc ...

  6. Flutter 实现原理及在马蜂窝的跨平台开发实践

    一直以来,跨平台开发都是困扰移动客户端开发的难题. 在马蜂窝旅游 App 很多业务场景里,我们尝试过一些主流的跨平台开发解决方案, 比如 WebView 和 React Native,来提升开发效率和 ...

  7. SpringCloud-分布式链路跟踪配置详解

    SpringCloud-分布式链路跟踪 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 注:作者使用IDEA + Gradle 注:需要有一定的java SpringBoot and ...

  8. Asp.Net Core 轻松学-经常使用异步的你,可能需要看看这个文章

    前言 事情的起因是由于一段简单的数据库连接代码引起,这段代码从语法上看,是没有任何问题:但是就是莫名其妙的报错了,这段代码极其简单,就是打开数据库连接,读取一条记录,然后立即更新到数据库中.但是,惨痛 ...

  9. 程序员如何让自己 Be Cloud Native - 配置篇

    前言 这是<程序员如何让自己 Be Cloud Native>系列文章的第二篇,从第一篇的反馈来看,有些同学反馈十二要素太形式主义,不建议盲目跟从.作者认为任何理论和技术都需要有自己的观点 ...

  10. Java之mybatis详解

    文章大纲 一.mybatis介绍二.mybatis代码实战三.项目源码下载四.参考文章   一.mybatis介绍 1. mybatis是什么?   mybatis是一个持久层的框架,是apache下 ...