常用的高斯滤波或者均值滤波相对都比较简单,即每个窗口的滤波核都是一样的。稍微复杂一些保边滤波如,双边滤波和导向图滤波等。这里介绍几种ffmpeg里面包含的相对比较复杂的滤波算法。计算量不可谓不小。可以通过ffmpeg查看源码实现过程,这里部分使用MATLAB,主要是为了代码的易读性和简易。
NL-meals(非局部均值滤波算法)
该算法主要用于去除高斯白噪声之类的噪点噪声
非局部均值滤波的基本原理与均值滤波类似,都是要取平均值,但是非局部均值滤波在计算中加入了每一个点的权重值,所以能够保证在相邻且相差很大的点在方框中求平均值时相互之间的影响减小,也就对图像边缘细节部分保留很多,这样图像看起来会更清晰。非局部均值滤波的算法我认为可以大致分为以下几个步骤:
- 首先在一个点A周围取一个大的框(搜索框),设边长为s,A在方框的中心,然后再在方框中取小的方框,即相似框,设边长为d
- 那么在A周围也有一个边长为d的方框,然后在大方框中找到所有边长为d的小方框的组合(就是一个小正方形在一个大正方形中到处移动,记录小正方形中心点的坐标就行了),设小方框的中心点为B,分别于A周围的相似框求减法,并且加入高斯核计算得到的加权值,这样可以计算出一个二维数组,里面存放着各个点的差值乘以权重后的值,加入高斯核主要是因为距离中心点距离不同对中心点的影响大小也不同,而且高斯核的权重和是1,所以就不用再归一化了。
- 然后将这个二维数组求和并平均,得到的值就是这个相似框的中心点B对于A的权重值。计算出A周围所有点的权重值,其实这个时候这个值和权重是成反比的,以A本身为例(以A为中心点的相似框),计算出来A对于A的所谓权重值是零。然后根据计算出来的值用一个指数减函数就得到了成正比的权重关系,具体的函数见下面的代码,w=exp(-d/h),就是这个,其中d就是计算出来的值啦,代入后w就是成正比的权重关系啦,h是一个滤波百分比值。可以先固定为一个常数。 而且这个计算出来w就是一个(0,1)的值哦,自动归一化啦
- 然后就是根据得到的权重值以及各个点本身的灰度值计算出非局部均值滤波后A点的灰度值。
- 以此类推,可以计算出图中所有点经过非局部均值滤波后的值
function [output]=NLmeansfilter(input,t,f,h)
[m n]=size(input);
%t:搜索框半径;f:相似框半径;h:滤波频率百分比
Output=zeros(m,n);
input2 = padarray(input,[f f],'symmetric');
%将边缘对称折叠上去
% f :加宽的宽度值
kernel = make_kernel(f); %计算得到一个高斯核,用于后续的计算
kernel = kernel / sum(sum(kernel)); %sum:对矩阵k的每一列求和,k表示矩阵k的总和
h=h*h;
for i=1:m
for j=1:n
i1 = i+ f;
j1 = j+ f;
W1= input2(i1-f:i1+f , j1-f:j1+f);
wmax=0;
average=0;
sweight=0;
rmin = max(i1-t,f+1); %确定相似框的边长,其实可以在代入数据的时候就设置搜索框和边界框边长的大小关系,就不用求最大最小值了
rmax = min(i1+t,m+f); %这段主要是控制不超出索引值
smin = max(j1-t,f+1);
smax = min(j1+t,n+f);
for r=rmin:1:rmax
for s=smin:1:smax
if(r==i1 && s==j1) continue; end;
W2= input2(r-f:r+f , s-f:s+f); % 取出正方块的所有像素值
d = sum(sum(kernel.*(W1-W2).*(W1-W2)));
w=exp(-d/h);
if w>wmax
wmax=w;
end
sweight = sweight + w; % w为(r,s)点的权重值,进行权重求和,为了归一化
average = average + w*input2(r,s); % 将权重和该点的像素值求的加权值。
end
end
average = average + wmax*input2(i1,j1);
sweight = sweight + wmax;
if sweight > 0
output(i,j) = average / sweight; %归一化
else
output(i,j) = input(i,j);
end
end
end
MATLAB代码比较清晰易读,但这篇介绍的更加详细一些,包括了一些加速的策略。
BM3D
BM3D号称是传统方法中效果最好的去噪算法,这里的噪声类型是指高斯类型的白噪声。
主要流程如下图:
高深的理论推理可以参考这里,专业术语表述太多,可以匆匆过一遍,不太建议深入了解。
从上图上看,该过程可以分为两步,而且两步的流程几乎一致。我们从不一样的地方看主要是如下两个地方:
hard thresholding:硬阈值滤波
wiener filtering:维纳滤波
第二阶段的输入是基于第一阶段的结果。主要是维纳滤波需要。
这里的块匹配以及权重比的理解,可以参考上一节的非局部均值滤波方法。
硬阈值滤波原理
硬阈值滤波是小波域对白噪声进行去噪的方法,它的基本假设是白噪声在小波的各个尺度中均匀分布,但是相对于主要信号的系数来说很小,于是可以通过一个硬阈值来将其区分开来,小于阈值的系数,将其置零,大于阈值的系数保持不变,通过这样的方法可以达到对信号进行去噪的目的
其具体过程描述如下:
(1)将信号从时间域或者空间域通过正交变换变换到变换域
(2)对变换域系数进行硬阈值滤波
(3)将硬阈值滤波后的变换域系数通过正交反变换还原到原来的时间域或者空间域得到去噪后的信号
这里的硬阈值滤波就是对变换域系数做一个简单的判断,如果其系数绝对值大于给定的阈值,那么保持系数不变,如果系数绝对值小于给点阈值,那么将系数置零。
正交变换可以是任意针对信号处理设计的正交变换,常用的傅立叶变换,离散余弦变换,小波变换,多尺度几何分析(超小波)等均在正交变换的范围内。
总体上可以理解在使用频域的一些方法进行去噪。因此,一些高频细节会随着噪声的去除而被抹去。因此引入了维纳滤波。
维纳滤波
维纳滤波器是采用统计的方法对平稳信号进行滤波的一种方法,其基本思想是设计一个滤波器使得信号经过滤波器后的输出信号和原始信号误差在统计意义上最小,其流程如下图所示
在信号的采集或者传输的过程中,信道里存在噪声,比如拍照过程,传感器中本身存在热噪声,同时在光子计数过程中也存在着泊松噪声,这样我们的ISP处理器得到的信号就是一个含噪信号,ISP去噪的过程就是为了从含有噪声的CMOS RAW数据中恢复出原始不好早的照片。维纳滤波器想要达到的目的是经过滤波其得到的信号y和原始信号在统计意义上误差最小,即均方误差最小
在工程中想要找到区分信号和噪声的合适阈值很困难,很容易“误伤”小系数的真实信号。从而导致细节的损失。
首先对含噪信号进行硬阈值滤波,得到的信号当作原始信号带入到维纳滤波系统函数中,然后对未经过任何操作的含噪信号进行维纳滤波,这样得到的结果更好。
这是因为,维纳滤波里通过系统函数H可以分成以下三种情况:(1)在信号功率很小的时候噪声为主,那么H几乎等于零,H与含噪信号系数相乘,含噪信号的系数几乎等于零,很好抑制噪声信号;(2)在信号功率很大的时候信号为主,那么H几乎等于一,H与含噪信号系数相乘,信号几乎不变,信号得到了很好的保留;(3)在噪声功率和信号功率差不多的时候,这时候信号与噪声各占一半,H的数值约等于二分之一,H与含噪信号系数相乘,含噪系数近似恢复到原始信号系数;基于上面三种情况的分析,维纳滤波器可以减少信号的“误伤”,比直接进行硬阈值滤波会有更好的结果,另外维纳滤波是一种统计意义上误差最小的滤波方式。
BM3D滤波流程
第一阶段:
- 块匹配估计:i)块匹配分组 ii)3D协同硬阈值滤波
- 聚合加权滤波
1. 这里的块匹配按照划窗的方式在图像中搜索与给定图像块的相似图像块,如果和图像的相似度高,那么将其加入到该分组中,如果相似度不高,舍弃,继续寻找下一个相似的图像块,需要特殊说明的是,图像的相似度与图像的差异成反相关关系,在相似度比较之前先对图像块做一个硬阈值收缩,去掉因为高频噪声带来的影响;一个块经过匹配后形成块组,2D变3D
这里的3D正交变换充分利用了图像块内部的相关性和图像块之间的相关性,在上图中第一二维空间组成的图像块内部,一个2D的正交变换揭示了图像内部的相关性,所有图像块经过第一个2D正交变换后,对应位置的像素点沿着第三维串起来,在第三维方向进行1D的正交变换,这个正交变换揭示了图像块之间的相关性,充分利用了同一组图像块相似来进行系数表示,通过这样的先2D正交变换再1D正交变换构成的3D正交变换硬阈值滤波,可以很好的抑制图像的噪声,同时保留了该组图像块中各个图像块自身的独特的细节。
2. 通过3D协同滤波后,将图像块放回到其原始的位置,但是由于搜索相似图像块的时候,存在图像块重叠的情况,如上图中红色区域中的几个图像块,彼此之间有重叠区域,那么重叠区域里像素点会有不止一个去噪后的结果,到底取哪一个呢,处理这个问题的方法就叫做聚合加权滤波,即对于同一个像素点的不同估计值赋予它们一个权值,取加权平均结果作为最终的结果
第二阶段:
- 块匹配估计:i)块匹配分组 ii)3D协同维纳滤波
- 聚合加权滤波
1. 经过第一阶段的基本估计滤波后得到一幅基本估计滤波后的图像,再对其进行块匹配估计,得到新的分组,然后在未经去噪的原始含噪图像的相同位置按照基本滤波后的分组,将原始含噪图像也进行相同的分组,具体的块匹配过程与第一阶段块匹配过程相似,这里便不再赘述,需要说明的是,这里得到两个块匹配分组,一个分组的图像块来自第一阶段基本估计滤波后的图像,我们称之为a组,另一个分组来自没有经过任何处理的含噪图像,我们称之为b组。在得到第二阶段块匹配的两个分组后,我们将a组作为指导图像块,当作为经过噪声污染的原始图像,b组图像当作要去噪的图像,对两组分别进行3D正交变换,然后按照文本第三部分介绍的那样,进行维纳滤波,维纳滤波后,对b组进行3D反正交变换到空间域图像块,并将图像块的图像块放回其原始位置。
2. 同第一阶段聚合加权滤波一样,这里对b组的图像数据进行聚合加权滤波,得到BM3D的最终结果。
代码
python代码、matlab等
ffmpeg滤镜介绍:nlmeans、BM3D