我有一个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()
或逻辑运算等矢量化函数的方法(意味着我被卡住了,我的大脑干了:/)
有关如何消除这些循环/更正代码的任何建议?
答案 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 = 1000
,H = 1000
运行一些基准并使用N
作为数据大小用[1000 2000 5000 10000 20000]
改变它。结果似乎很疯狂,尽管不是不可靠的,因为Measure and Improve GPU Performance
使用了批准的基准测试方法。这是原始和CPU和GPU矢量化代码的基准图 -
然后看起来恰好仅对矢量化代码进行基准测试,对于更大的数据集,其绘图如下所示 -
结论:问题基本上看起来像查找问题,其中Kart1
是数据,K1
是要查找的索引数组。这里介绍的矢量化解决方案基本上是一种蛮力方法,基准测试结果显然有利于提高性能。但是,看看是否有任何非暴力方法可能是基于循环的,但是有效地利用这种方法可以表现得更好,这将会很有趣。