如何提高matlab中径向对称积分的性能

时间:2016-01-19 14:18:43

标签: performance matlab image-processing

我为以下任务编写了代码:

  • 输入:大小的平方图像,例如2001x2001像素 - >重心位于1001/1001

从中心开始,增量为dr = 1pixel我想从我的图像中了解以下特征:

  • 半径范围内的点数(从r到r + dr)
  • 此范围内此像素的灰度值
  • ...

因此,我使用Matlab中的find函数搜索每个半径范围的矩阵索引。这是我的代码:

s = size(input image);

R = zeros(s(1),s(1));           %Initializing matrix R
x0 = ceil(s(1)/2); y0 = x0;

for i=1:s(1)                    %Calculation of matrix R
        for j=1:s(2)
            R(i,j) = sqrt((x0-j)^2 + (y0-i)^2);
        end       
end

r = 0;                                      %Start of radius at 0
maxr = ceil(max(max(R)));                   %Maximum radius

R2 = gpuArray(R);                           %Move matrix R to GPU

while (r <= (maxr-dr))       
    N = 1*((R2>=r) & (R2<(r+dr)));          %Logical matrix with 1 if r is in the radius range
    indnew = find(N);                       %Find the indices of non-zero elements
    indices = vertcat(indices,indnew);      %Create large vector with the founded indices
    indices = vertcat(indices,(-1));        %Append stop-sign -1
    r = r + dr;
end

ind2 = int32(gather(indices));              %Get indices from GPU to CPU

此代码的作用如下: 在这一行

  

N = 1 *((R2> = r)&amp;(R2&lt;(r + dr)));

我得到一个逻辑矩阵作为答案,将其乘以1.如果r在半径范围内,矩阵的值为1。然后我使用find函数搜索矩阵的索引。但是对于2000x2000像素的图像尺寸,我需要30秒(使用gpuArray(R))并且像一分钟没有将R移动到GPU。

所以似乎find函数非常慢,但我不知道一个和我编写的代码一样稳定的解决方案。

有没有人知道如何以更优雅和更快的方式找到所需的矩阵索引???

请记住,我现在在while循环中有1400次循环运行。甚至可以像使用find函数一样更快地获得索引吗?

提前谢谢!!

2 个答案:

答案 0 :(得分:0)

也许使用类似直方图的方法会有所帮助。 (histcounts) 将R2的元素从[0:dr:maxr]

中分成二进制位

答案 1 :(得分:0)

我最近完成了这个计算。关键是要避免发现。你不需要它,使用逻辑寻址......

my &double = * * 2; # WhateverCode
my &double = * × 2; # ditto

my &double = { $_ * 2 };       # bare block
my &double = { $^n * 2 };      # block with positional placeholder
my &double = -> $n { $n * 2 }; # pointy block

my &double = sub ( $n ) { $n * 2 } # anon sub
my &double = anon sub double ( $n ) { $n * 2 } # anon sub with name

my &double = &infix:<*>.assuming(*,2); # curried
my &double = &infix:<*>.assuming(2);

sub double ( $n ) { $n * 2 } # same as :( Any $n )

您还没有告诉我们您希望索引的内容,但可能您希望以某种方式累积它们。在这种情况下,accumarray的速度提高了几个数量级:

valsForRanger = inputImage((R>=r) & (R<(r+dr));
numValsForRanger = numel(valsForRanger);

PS。注意,GPU在这里是一个红鲱鱼。我不会用它。