1

我有一个 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

它运行,但很丑,我怀疑它正在做我想做的事。我对这件事的“多维性”有点困惑,不知道评估内核的许多函数,也想不出一种方法来使用矢量化函数bsxfun()或逻辑运算(意味着我被卡住了,我的大脑是干燥的 :/)

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

4

1 回答 1

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));

基准测试

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

在此处输入图像描述

然后仅对矢量化代码和更大的数据大小进行基准测试似乎是合适的,其图如下所示 -

在此处输入图像描述

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

于 2014-08-13T14:01:00.527 回答