优化代码 - 欧氏距离筛选的计算

Moh*_*med 4 matlab sift

首先,我很清楚Sift中的特征匹配背后的理论,我的问题是技术问题

所以我尝试计算第一个图像的矢量和第二个图像的所有矢量之间的欧几里德距离,然后如果最大的两个值之间的比率大于某个阈值而不是匹配

那是我的代码

distRatio = 0.5;   
for i = 1:size(des1,1)
    eucl = zeros(size(des2,1));
    for j=1:size(des2,1)
           eucl(j) = sqrt(sum((des1(i,:)-des2(j,:)).^2));
    end;

    [vals,indx] = sort(eucl);        
    if (vals(1) < distRatio * vals(2))
      match(i) = indx(1);
    else
      match(i) = 0;
    end
end;
Run Code Online (Sandbox Code Playgroud)

问题是它非常慢,而且我知道原因,因为嵌套循环它很慢,有没有办法优化它?对不起,我对Matlab语法的经验不佳.

Bri*_*n L 6

在计算欧氏距离时,您经常可以使用的一个巧妙技巧是修改算法以使用平方欧氏距离 - 这消除了不必要的昂贵的平方根函数,例如,如果您只是想找到最大的或者一组中的最小距离.

所以内部循环可能变成:

distSquared(j) = sum((des1(i, :) - des2(j, :)).^2);
Run Code Online (Sandbox Code Playgroud)

在你的情况下,改变的棘手的是线

if (vals(1) < distRatio * vals(2))
Run Code Online (Sandbox Code Playgroud)

这相当于

if (vals(1)^2 < (distRatio * vals(2))^2)
Run Code Online (Sandbox Code Playgroud)

要么

if (vals(1)^2 < (distRatio^2) * (vals(2)^2))
Run Code Online (Sandbox Code Playgroud)

如果您从而获得值distSquared而不是eucl,那么您可以使用

if (valSquared(1) < (distRatio^2) * valSquared(2))
Run Code Online (Sandbox Code Playgroud)

最后,你可以通过重写这样的减法来取出内循环:

countRowsDes2 = size(des2, 1); % this line outside the loop

%... now inside the loop
    des1expand = repmat(des1(i, :), countRowsDes2, 1); % copy this row

    distSquared = sum((des1expand - des2).^2, 2);      % sum horizontally
Run Code Online (Sandbox Code Playgroud)

我习惯于repmat复制行des1(i, :),并sum使用第二个维度参数在水平维度上工作.

把它们放在一起

distRatio = 0.5;
distRatioSq = distRatio^2; % distance ratio squared
countRowsDes1 = size(des1, 1); % number of rows in des1
countRowsDes2 = size(des2, 1); % number of rows in des2

match = zeros(countRowsDes1, 1); % pre-initialize with zeros

for i = i:size(des1, 1)
    des1expand = repmat(des1(i, :), countRowsDes2, 1); % copy row i of des1
    distSquared = sum((des1expand - des2).^2, 2);      % sum horizontally

    [valsSquared, index] = sort(distSquared);

    if (valsSquared(1) < distRatioSq * valsSquared(2))
        match(i) = index(1);
    % else zero by initialization
end
Run Code Online (Sandbox Code Playgroud)