Side window filter

目录

    • box filter
    • side window filtering :
    • S-BOX

先介绍了box滤波器,然后介绍了Side window filter,之后介绍了S-BOX。写的很粗略,理解的不是很透彻,具体可以看我的参考内容。

box filter

参考: https://blog.csdn.net/lxy201700/article/details/25104887

(我瞎说的:不要管它的算法,本质上是均值滤波不用求和,通过一定技巧把O(M*N)的复杂度变成O(1))
Side window filter_第1张图片
1、给定一张图像,宽高为(M,N),确定待求矩形模板的宽高(m,n),如图紫色矩形。图中每个黑色方块代表一个像素,红色方块是假想像素。
2、开辟一段大小为M的数组,记为buff, 用来存储计算过程的中间变量,用红色方块表示
3、将矩形模板(紫色)从左上角(0,0)开始,逐像素向右滑动,到达行末时,矩形移动到下一行的开头(0,1),如此反复,每移动到一个新位置时,计算矩形内的像素和,保存在数组A中。以(0,0)位置为例进行说明:首先将绿色矩形内的每一列像素求和,结果放在buff内(红色方块),再对蓝色矩形内的像素求和,结果即为紫色特征矩形内的像素和,把它存放到数组A中,如此便完成了第一次求和运算。
4、每次紫色矩形向右移动时,实际上就是求对应的蓝色矩形的像素和,此时只要把上一次的求和结果减去蓝色矩形内的第一个红色块,再加上它右面的一个红色块,就是当前位置的和了,用公式表示 sum[i] = sum[i-1] - buff[x-1] + buff[x+m-1]
5、当紫色矩形移动到行末时,需要对buff进行更新。因为整个绿色矩形下移了一个像素,所以对于每个buff[i], 需要加上一个新进来的像素,再减去一个出去的像素,然后便开始新的一行的计算了。

side window filtering :

参考:https://zhuanlan.zhihu.com/p/79254846(论文解读和C++实现)
https://zhuanlan.zhihu.com/p/58326095 (论文原作者)

side window filter不管原来的滤波器保不保边,运用了side-window思想之后,都可以让它变成保边滤波! 经典滤波算法基本都是,以某个像素点为滤波窗口中心,最后会导致边缘部分模糊。
Side window filter_第2张图片

图上是三种经典的边缘情况,论文中对其导数进行分析。最后得出,a的左极限应该来自,a的左边区域,同理a的右极限应该来自右边区域,传统的滤波算法a的值不区分左边还是右边区域,就会导致阶梯减小,边缘愈发模糊。
然后,作者就提出滤波时直接把像素点与滤波器的边缘对齐,而不是与滤波器的中心对齐。至于边缘的方向,文章中提出了8个方向的滤波窗口,分别计算该点在各个方向上的值,取最佳结果作为滤波结果。下图是该思想的核心算法流程:
Side window filter_第3张图片

S-BOX

参考:https://zhuanlan.zhihu.com/p/64647829

S-BOX就是盒子滤波器和SWF相结合之后的滤波器,算法流程如下:
Side window filter_第4张图片
对应的matlab代码

function result=SideWindowBoxFilter(im, radius, iteration)
%  papers:   1) Sub-window Box Filter, Y.Gong, B.Liu, X.Hou, G.Qiu, VCIP2018, Dec.09, Taiwan
%        2) Side Window Filtering, H.Yin, Y.Gong, G.Qiu. CVPR2019
%implemented by Yuanhao Gong


r = radius; %the radius of the side window
k = ones(2*r+1,1)/(2*r+1); %separable kernel
k_L=k; k_L(r+2:end)=0; k_L = k_L/sum(k_L); %half kernel
k_R=flipud(k_L);
m = size(im,1)+2*r; n = size(im,2)+2*r; total = m*n;
[row, col]=ndgrid(1:m,1:n);
offset = row + m*(col-1) - total;   % 偏移
im = single(im);  %单精度
result = im;
d = zeros(m,n,8,'single');


for ch=1:size(im,3)
    U = padarray(im(:,:,ch),[r,r],'replicate'); %填充
    for i = 1:iteration
        %all projection distances
        d(:,:,1) = conv2(k_L, k_L, U,'same') - U;
        d(:,:,2) = conv2(k_L, k_R, U,'same') - U;
        d(:,:,3) = conv2(k_R, k_L, U,'same') - U;
        d(:,:,4) = conv2(k_R, k_R, U,'same') - U;
        d(:,:,5) = conv2(k_L, k, U,'same') - U;
        d(:,:,6) = conv2(k_R, k, U,'same') - U;
        d(:,:,7) = conv2(k, k_L, U,'same') - U;
        d(:,:,8) = conv2(k, k_R, U,'same') - U;   
        %find the minimal signed distance
        tmp = abs(d); % 求绝对值
        [~,ind] = min(tmp,[],3);  %~ 是最小值,ind是索引号
        index = offset+total*ind; % 填充之后,索引有偏差,需要恢复
        dm = d(index); %signed minimal distance
        %update
        U = U + dm;
    end
    result(:,:,ch) = U(r+1:end-r,r+1:end-r);
end

代码中使用的8个核
Side window filter_第5张图片

你可能感兴趣的:(论文,算法,计算机视觉)