图像之间的欧几里德距离

nag*_*wal 5 algorithm matlab image

在此处输入图片说明我有两个图像,比如PS,大小为 8192×200,我想计算它们之间的自定义“欧几里德距离”。目前我使用以下步骤:

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

    Ip = Ip(:).';
    Is = Is(:);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 计算一个度量矩阵,G,其条目由公式给出

    G(i,j) = 1/(2*pi*r*r) * exp((-d*d)/(2*r*r));
    
    Run Code Online (Sandbox Code Playgroud)

    其中r是一个从 0 到 20 变化的全局参数,例如,d是 pixeli和 pixel之间的距离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).' );  
    
    Run Code Online (Sandbox Code Playgroud)

我已经使用 mex 函数编写了一些代码,但是在给出结果之前花费的时间太长(5-6 小时) - 请参阅此 SO 问题以获取代码以及对此的更多讨论。

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

dan*_*man 3

如果我理解正确,您应该能够执行以下操作,并让它在 2 秒内运行:

样本数据:

s1 = 8192; s2 = 200;
img_a = rand(s1, s2);
img_b = rand(s1, s2);
r = 2;
Run Code Online (Sandbox Code Playgroud)

以及计算本身:

s1 = 8192; s2 = 200;
img_a = rand(s1, s2);
img_b = rand(s1, s2);
r = 2;
Run Code Online (Sandbox Code Playgroud)

以上大约需要25s。为了降低到 2 秒,您需要用conv2更快的基于 fft 的卷积替换标准。看看这个这个

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);
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果您仍然希望它运行得更快,您可以利用相当小的 d非常接近于exp(-d^2/r^2)零的事实:因此您实际上可以将内核裁剪为一个很小的矩形,而不是上面建议的巨大的东西。较小的内核意味着(或者特别是)运行速度更快。conv2fftconv2