MATLAB中的非局部均值滤波器优化

时间:2014-01-28 20:13:49

标签: matlab image-processing octave

我正在尝试为作业编写非局部均值过滤器。我用两种方式编写代码,但是我希望更快的方法比其他方法慢得多。

方法1 :(此方法较慢)

for i = 1:size(I,1)
    tic
    sprintf('%d/%d',i,size(I,1))
    for j = 1:size(I,2)
        w = exp((-abs(I-I(i,j))^2)/(h^2));

        Z = sum(sum(w));
        w = w/Z;

        sumV = w .* I;

        NL(i,j) = sum(sum(sumV));
    end
    toc
end

方法2 :(此方法更快)

for i = 1:size(I,1)
    tic
    sprintf('%d/%d',i,size(I,1))
    for j = 1:size(I,2)
        Z = 0;
        for k = 1:size(I,1)
            for l = 1:size(I,2)
                w = exp((-abs(I(i,j)-I(k,l))^2)/(h^2));

                Z = Z + w;
            end
        end

        sumV = 0;
        for k = 1:size(I,1)
            for l = 1:size(I,2)
                w = exp((-abs(I(i,j)-I(k,l))^2)/(h^2));
                w = w/Z;

                sumV = sumV + w * I(k,l);
            end
        end

        NL(i,j) = sumV;
    end
    toc
end

我真的认为MATLAB会针对Matrix操作进行优化。是否有理由不在此代码中?差异非常大。对于带有512x512的{​​{1}}图像,外部循环的一次迭代对于方法1需要h = 0.05秒,对于方法2则需要24-28秒。

3 个答案:

答案 0 :(得分:3)

这两种方法并没有做同样的事情。在方法2中,abs(I(i,j)-I(k,l))表达式中的w=项是平方的,这很好,因为该项只是一个数值。

但是,在方法1中,术语abs(I-I(i,j))实际上是一个矩阵(从矩阵I(i,j)中的每个元素中减去数值I,再次返回一个矩阵)。因此,当该术语与^运算符平方时,矩阵乘法正在发生。我的猜测,基于方法2,这不是你想要的。相反,如果要平方该矩阵中的每个元素,请使用.^运算符,如abs(I-I(i,j)).^2

矩阵乘法是一种计算量更大的操作,这可能是方法1需要更长时间的原因。

答案 1 :(得分:0)

我的猜测是你没有预先分配NL,两个方法都在同一个函数中(或者是脚本,你在函数运行之间没有清除NL)。这会使第一种方法减慢很多。

尝试以下操作:为两种方法创建一个函数。运行每个方法一次。然后使用profiler查看每个函数花费大部分时间的位置。

答案 2 :(得分:0)

使用im2col

可以实现更快的实现(Vectorized)
  1. 从每个社区创建一个Vector。
  2. 使用预定义索引计算每个补丁之间的距离。
  3. 使用sum函数对值和权重求和。
  4. 此方法完全没有循环。