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



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

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

a='C:UserssepidehDesktopIP_abadpourS45C-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 语句。

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

这里有几个建议:

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

    b = b + 50;
    
  2. 为什么要在将b传递给bsxfun之前对其进行重塑?bsxfun输出的大小与您的图像相同,这里真的没有必要重塑任何东西。

  3. 关于您的test功能,请注意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)));
    

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

  4. 对于空间分析,请按照 Dan 的建议查看conv2(或者为了练习而实现您自己的 2-D 卷积(。对于傅里叶分析,请考虑在频域中使用fft2ifft2函数。

希望这有帮助!

因此,对于您发布的示例,您可以利用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);

相关内容

  • 没有找到相关文章

最新更新