【问题标题】:Matlab: How to vectorize a nested loop over a 2D set of vectorsMatlab:如何在一组 2D 向量上向量化嵌套循环
【发布时间】:2013-06-13 22:19:01
【问题描述】:

我有一个如下形式的函数:

function Out = DecideIfAPixelIsWithinAnEllipsoidalClass(pixel,means,VarianceCovarianceMatrix)  
   ellipsoid = (pixel-means)'*(VarianceCovarianceMatrix^(-1))*(pixel-means);  
   if ellipsoid <= 1
      Out = 1;
   else
      Out = 0;
   end
end  

我正在使用matlab进行遥感处理,我想对LandSatTM图像进行分类。这张图片有7个波段,大小为2048*2048。所以我将它们存储在3维2048*2048*7矩阵中。在这个函数中意味着是一个 7*1 矩阵,使用名为 ExtractStatisticalParameters 的函数中的类样本计算得出,而 VarianceCovarianceMatrix 实际上是一个 7*7 矩阵,您会看到:

ellipsoid = (pixel-means)'*(VarianceCovarianceMatrix^(-1))*(pixel-means);  

是椭圆体的方程。我的问题是每次你可以将一个像素(它是一个 7*1 向量,其中每一行是分隔带中像素的值)传递给这个函数,所以我需要像这样写一个循环:

for k1=1:2048  
   for k2=1:2048  
      pixel(:,1)=image(k1,k2,:); 
      Out = DecideIfAPixelIsWithinAnEllipsoidalClass(pixel,means,VarianceCovarianceMatrix);  
   end  
end  

您知道这将花费系统的大量时间和精力。您能建议我一种减少施加在系统上的压力的方法吗?

【问题讨论】:

    标签: performance matlab image-processing vectorization


    【解决方案1】:

    不需要循环!

    pMinusMean = bsxfun( @minus, reshape( image, [], 7 ), means' ); %//' subtract means from all pixes
    iCv = inv( arianceCovarianceMatrix );
    ell = sum( (pMinusMean * iCv ) .* pminusMean, 2 ); % note the .* the second time!
    Out = reshape( ell <= 1, size(image(:,:,1)) ); % out is 2048-by-2048 logical image
    

    更新:

    在下面的 cmets 中进行了(有些激烈的)辩论之后,我添加了 Rody Oldenhuis 所做的更正:

    pMinusMean = bsxfun( @minus, reshape( image, [], 7 ), means' ); %//' subtract means from all pixes
    ell = sum( (pMinusMean / varianceCovarianceMatrix ) .* pminusMean, 2 ); % note the .* the second time!
    Out = reshape( ell <= 1, size(image(:,:,1)) );
    

    此更改的关键问题是Matlab 的inv() 实现不佳,最好使用mldividemrdivide(运算符/\)代替。

    【讨论】:

    • ...你刚才是不是用inv() 解决了一个线性系统? doc inv 的顶部附近:“实际上,很少需要形成矩阵的显式逆矩阵。在求解线性方程组 Ax = b 时,经常会出现 inv 的误用。解决此问题的一种方法是与x = inv(A)*b。从执行时间和数值精度的角度来看,更好的方法是使用矩阵除法运算符x = A\b。这使用高斯消元法产生解决方案,而不形成逆。参见mldivide (`` ) 了解更多信息。”
    • @RodyOldenhuis inv 不用于求解此问题中的方程组,它用作高斯(椭球)的协方差矩阵。
    • euhmmm...所以?是什么阻止你写sum( pMinusMean/varianceCovarianceMatrix .* pminusMean, 2)
    • @Shai:这不是我的真正意图,但谢谢 :) 并不是说​​它“实施不善”,只是没有算法可以像你能做到的那样快速和准确用于计算乘积 inv(A)*xx*inv(A)。对不起,如果我对这个问题有点强硬,但是当你看到人们使用 ij 作为变量名时,你会怎么做? :) 我是说出于教育原因实施一次或两次冒泡排序或 bogosort 很好,但实际上,最后你应该使用是快速排序(和类似的)——与inv()相同。
    • 你的评论不是关于A*X = B,而是说一个人永远不应该使用inv。我不喜欢笼统的陈述。正如您所说,教新用户为什么事情会以这种或另一种方式工作以及权衡取舍比仅仅说“从不”要好。如前所述,inv 是一个简单的函数,在某些情况下具有速度优势。只要了解特定问题的数字,并不总是需要精确到eps。 “最佳”并不总是意味着最准确。对于我机器上的大型随机矩阵,trace(A\eye(size(A)))trace(inv(A)) 花费的时间长 50%。
    猜你喜欢
    • 1970-01-01
    • 2013-12-06
    • 2012-11-04
    • 2016-12-09
    • 1970-01-01
    • 2020-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多