如何在不使用for循环且不影响速度的情况下应用逐元素操作

时间:2013-06-24 09:40:00

标签: performance matlab image-processing filter bsxfun

假设我有一个RGB图像矩阵,我想对它应用一些空间滤镜。 一般来说,我想应用逐元素操作(请注意,这是一项大学任务,我不允许使用图像处理工具箱中提供的任何内置函数)。我决定将过滤器编写为函数,然后将bsxfun应用于图像上的这些函数。

一个简单的例子就是:
我想将50添加到图像的所有灰度级,然后用200以上的200替换所有灰度级。这是我的代码:

a='C:\Users\sepideh\Desktop\IP_abadpour\S45C-113050518040.jpg';  
b=imread(a);  
b(:,:,1)=b(:,:,1)+50;  
b(:,:,2)=b(:,:,2)+50;  
b(:,:,3)=b(:,:,3)+50;  
c=reshape(b,[],1);  
d=bsxfun(@test,c,200);

test是这种形式的函数:

function Out = test(in,a)  
   if in>a
      in=200;
   end
   Out = in;
end  

这段代码不起作用,因为在第二行“in> a”是一个有0和1的矩阵(我的意思是所有的元素都不是1而不应该是)所以调试器不会分支到if声明。

您能否指导我如何编写此函数以及如何在不影响性能和运行时速度的情况下对图像应用空间和傅里叶分析?

2 个答案:

答案 0 :(得分:1)

因此,对于您发布的示例,您可以利用matlab中的大多数运算符本地处理矩阵的事实:

b=imread(a);
c = a + 50;
c(c > 200) = 200;

就这么简单。

对于过滤,如果您被允许,我会查看conv2函数。您可以通过这种方式进行空间滤波,而无需转换到频域(记住,频域中滤波器的乘法与空间域中的卷积相同)。例如,基本的低通滤波器:

lpf = ones(5)./25;
c(:,:,1) = conv2(b(:,:,1), lpf);
c(:,:,2) = conv2(b(:,:,2), lpf);
c(:,:,3) = conv2(b(:,:,3), lpf);

答案 1 :(得分:1)

以下是一些建议:

  1. 首先,您不需要单独为RGB矩阵的每一层添加50。你可以这样做:

    b = b + 50;
    
  2. 为什么在将b传递给bsxfun之前对其进行重新整形? bsxfun输出的大小与您的图像相同,实际上没有必要在此重塑任何内容。

  3. 关于test功能,请注意official documentation of bsxfun状态:

      

    C = fun(A,B)形式的二进制元素函数接受任意但相等大小的数组AB,并返回相同大小的输出。输出数组C中的每个元素都是仅对AB的相应元素进行操作的结果。 fun还必须支持标量扩展,例如,如果AB是标量,则C是将标量应用于其他输入数组中的每个元素的结果。

    因此bsxfun执行单例扩展并将其两个输入数组“膨胀”到相同的大小,然后将指定的函数应用于膨胀的数组。事实上,元素方式函数fun在数组上运行,而不是在标量上运行。我在这里使用bsxfun并没有看到任何实际的好处。

    也就是说,您可以按照Dan的建议简化代码,或将其作为函数实现:

    function out = test(in, a);
        out = in;
        out(in > a) = a;
    

    我假设如果您使用值210而不是200,那么您也希望将所有灰度级别限制为210,因此您应该使用a而不是硬编码值200你也可以像这样编写你的函数:

    function out = test(in, a)
        out = min(in, a);
    

    然后用:

    调用它
    d = test(b, 200);
    

    而不是更复杂的d = bsxfun(@test, b, 200)

    另一种方法是使用arrayfun

    d = arrayfun(@(x)test(x, 200), a);
    

    d = arrayfun(@test, a, 200 * ones(size(a)));
    

    其中arrayfun将以元素方式应用test,而test函数只需要在标量上运行。但是,arrayfun通常比循环运行得慢,更不用说矢量化操作了。

  4. 对于空间分析,请查看conv2,就像建议的Dan一样(或为了练习,实施自己的二维卷积)。对于傅里叶分析,请考虑在频域中使用fft2ifft2函数。

  5. 希望这有帮助!