核心中最小距离的矢量化

时间:2014-03-12 14:33:43

标签: matlab multidimensional-array vectorization lookup bsxfun

我有一个Nx2数组K1,其中包含N个关键点的位置和一个3维WxHx3数组Kart1(width,height,coordinates),它将坐标映射到图像的每个像素。对于K1中的每个关键点,我想在Kart1中读取像素的位置,并在其周围的3x3内核中评估坐标(搜索最小值/最大值或计算平均值)并指定值到KPCoor1中的当前像素。

我目前的做法如下:

for ii=1:length(K1(:,1)) %for every keypoint in K1

    MinDist=sqrt(sum(Kart1(K1(ii,2)-1,K1(ii,1)-1,:).^2)); %Calculate distance
    xShift=0;
    yShift=0;
    for kk=-1:1 %for every pixel in a 3x3 kernel...
        for ll=-1:1

            Distance=sqrt(sum(Kart1(K1(ii,2)+kk,K1(ii,1)+ll,:).^2));

            if Distance<MinDist   %... if the current distance is smaller than MinDist
                MinDist=Distance; %... update MinDist...
                xShift=kk; %... and take the kernel coordinate of the pixel
                yShift=ll;
            end

        end
    end

    KP1Coor(ii,:)=Kart1(K1(ii,2)+xShift,K1(ii,1)+yShift,:); %assign the coordinates of the pixel with the minimal distance in kernel.

end

并且它运行,但是很难看,我怀疑它是在做我想做的事情。我对#多维度&#34;多维度感到困惑。对于这个问题,我不知道评估内核的许多函数,并且不能想出使用bsxfun()或逻辑运算等矢量化函数的方法(意味着我被卡住了,我的大脑干了:/)

有关如何消除这些循环/更正代码的任何建议?

1 个答案:

答案 0 :(得分:2)

矢量化方法在深入了解矢量化实现之后,它看起来像一个非常有趣的look-up problem,所以如果你仍然对矢量化技术感兴趣来完成工作,这里有一种方法与bsxfun -

%// Scalars to replace their repeated usages in the code
[W,H,NC]= size(Kart1);
d3a = 1:NC;

%// Indices for Kart1 at the first level of the nested loops
BI = bsxfun(@plus,K1(:,2)+(K1(:,1)-1)*W,(d3a-1)*W*H);

%// Indices for Kart1 in 3x3 kernel around the indices obtained at first level
BIW3 = bsxfun(@plus,[-1 0 1]',[-W 0 W]); %//'
%// Linear indices for the minimum value of Kart1 in the 3x3 neighborhood 
[~,MI3] = min(sqrt(sum(Kart1(bsxfun(@plus,...
    BI,permute(BIW3(:),[3 2 1]))).^2,2)),[],3);
%// X-Y indices
[xShift1,yShift1] = ind2sub([3 3],MI3);

%// Get Kart1 values corresponding to the indices for the minimum values
KP1Coor = Kart1(bsxfun(@plus,...
    K1(:,2)+xShift1-2 +(K1(:,1)+yShift1-2-1)*W,(d3a-1)*W*H));

<强>基准

我也可以使用并行计算工具箱中的gpuArray使用GPU测试它,然后使用W = 1000H = 1000运行一些基准并使用N作为数据大小用[1000 2000 5000 10000 20000]改变它。结果似乎很疯狂,尽管不是不可靠的,因为Measure and Improve GPU Performance使用了批准的基准测试方法。这是原始和CPU和GPU矢量化代码的基准图 -

enter image description here

然后看起来恰好仅对矢量化代码进行基准测试,对于更大的数据集,其绘图如下所示 -

enter image description here

结论:问题基本上看起来像查找问题,其中Kart1是数据,K1是要查找的索引数组。这里介绍的矢量化解决方案基本上是一种蛮力方法,基准测试结果显然有利于提高性能。但是,看看是否有任何非暴力方法可能是基于循环的,但是有效地利用这种方法可以表现得更好,这将会很有趣。

相关问题