图像之间的欧几里德距离

时间:2016-05-02 15:08:40

标签: image algorithm matlab

enter image description here我有两张图片,比如PS,大小为8192×200,我想计算它们之间的自定义“欧几里德距离”。目前我使用以下步骤:

  1. 将图像重塑为一对列和行向量:

    Ip = Ip(:).';
    Is = Is(:);
    
  2. 计算度量矩阵G,其条目由公式

    给出
    G(i,j) = 1/(2*pi*r*r) * exp((-d*d)/(2*r*r));
    

    其中r是一个全局参数,从0到20不等,而d是像素i和像素j之间的距离。例如,如果像素i(k,l)而像素j(k1,l1),则d = sqrt((k-k1)^2 + (l-l1)^2);。像素1将为(1,1),像素2将为(1,2),依此类推。因此,矩阵G的大小将为1638400×1638400

  3. 使用以下方法计算两幅图像之间的最终(标量)欧几里德距离:

    ImEuDist = sqrt( (Ip-Is) * G * (Ip-Is).' );  
    
  4. 我已经使用mex函数编写了一些代码,但是在给出结果(5-6小时)之前花了太长时间 - 请参阅this SO question以获取代码并对此进行更多讨论。

    请帮我优化一下;理想情况下,我希望它能在几秒钟内完成。请注意,我对涉及GPU的解决方案不感兴趣。

1 个答案:

答案 0 :(得分:2)

如果我理解正确,你应该能够做到以下几点,让它在2s以下运行:

示例数据:

s1 = 8192; s2 = 200;
img_a = rand(s1, s2);
img_b = rand(s1, s2);
r = 2;

和计算本身:

img_diff = img_a - img_b;
kernel = bsxfun(@plus, (-s1:s1).^2.', (-s2:s2).^2);
kernel = 1/(2/pi/r^2) * exp(-kernel/ (2*r*2));
g = conv2(img_diff, kernel, 'same');
res = g(:)' * img_diff(:); 
res = sqrt(res);

以上需要大约25秒。要降低到2秒,您需要使用更快,基于fft的卷积替换标准conv2。请参阅thisthis

function c = conv2fft(X, Y)
    % ignoring small floating-point differences, this is equivalent
    % to the inbuilt Matlab conv2(X, Y, 'same')
    X1 = [X zeros(size(X,1), size(Y,2)-1);
          zeros(size(Y,1)-1, size(X,2)+size(Y,2)-1)];
    Y1 = zeros(size(X1)); 
    Y1(1:size(Y,1), 1:size(Y,2)) = Y;
    c = ifft2(fft2(X1).*fft2(Y1));
    c = c(size(X,1)+1:size(X,1)+size(X,1), size(X,2)+1:size(X,2)+size(X,2));
end

顺便提一下,如果你仍然希望它变得更快,你可以利用exp(-d^2/r^2) 非常接近的事实为零,相当小的d:所以你可以实际裁剪你的内核只是一个小矩形,而不是上面提到的巨大的东西。较小的内核意味着conv2fft(或特别是conv2)运行得更快。