Image 图像间欧氏距离

Image 图像间欧氏距离,image,algorithm,matlab,Image,Algorithm,Matlab,我有两个图像,比如说p和S,大小为8192×200,我想计算它们之间的自定义“欧几里德距离”。目前,我使用以下步骤: 将图像重塑为一对列向量和行向量: Ip=Ip(:); Is=Is(:); 计算一个度量矩阵,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

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

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

    Ip=Ip(:);
    Is=Is(:);
    
  • 计算一个度量矩阵,
    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

  • 使用以下公式计算两幅图像之间的最终(标量)欧氏距离:

    ImEuDist = sqrt( (Ip-Is) * G * (Ip-Is).' );  
    
  • 我已经使用mex函数编写了一些代码,但是在给出结果之前花费的时间太长(5-6个小时)-有关代码和更多讨论,请参阅


    请帮我优化这个;我希望它能在几秒钟内运行。请注意,我对涉及GPU的解决方案不感兴趣

    如果我理解正确,您应该能够执行以下操作,并在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);
    内核=1/(2/pi/r^2)*exp(-kernel/(2*r*2));
    g=conv2(img_diff,内核“相同”);
    res=g(:)'*img_diff(:);
    res=sqrt(res);
    
    以上过程大约需要25秒。要精确到2秒,您需要用更快的、基于fft的卷积代替标准的
    conv2
    。见和:

    函数c=conv2fft(X,Y) %忽略小的浮点差异,这是等效的 %到内置的Matlab conv2(X,Y,‘相同’) X1=[X个零(大小(X,1),大小(Y,2)-1); 零(大小(Y,1)-1,大小(X,2)+大小(Y,2)-1)]; Y1=零(尺寸(X1)); Y1(1:size(Y,1),1:size(Y,2))=Y; c=ifft2(fft2(X1)。*fft2(Y1)); c=c(尺寸(X,1)+1:尺寸(X,1)+尺寸(X,1),尺寸(X,2)+1:尺寸(X,2)+尺寸(X,2)); 结束

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

    我仍然认为您应该给出一个图表。只需在绘画中做一些简单的事情感谢编辑,但在第一步中,我同时将两个图像重塑为行向量或列向量,而不是一对行向量和列向量。我可以知道你的想法吗?如果你还需要图片,请告诉我。我可以放一个简单的。一个图像会很好,是的。我认为你的第一步不是正确的方法,考虑到你正在努力做的事情。“我的编辑”确实稍微改变了它(在转换为向量之前,您翻转了两幅图像),但这对解决整个问题并不特别有趣/相关。我不确定你在评论中所说的“同时”是什么意思。我所说的同时,是指
    Ip
    Is
    都是行向量或列向量。它排除了
    Ip
    是行向量和
    是列向量的情况,反之亦然。非常感谢您提供了如此出色的解决方案。如果有任何疑问,我会在这个帖子中再次回复你。再次感谢。如果您可以检查此解决方案是否有效(或者几乎有效),请将其标记为正确。另外,编辑上一个问题以链接到此问题可能会很好。请您解释一下步骤
    kernel=bsxfun(@plus,(-s1:s1)。^2.”,(-s2:s2)。^2)背后的想法好吗。此外,在这一步之后,数字非常大,以至于MATLAB为表达式
    exp(-kernel/(2*r*2))
    生成了0。因此,我认为这不符合我的目的。@nagarwal-第一行生成(正确地)一个大的2d数组,给出中心一点和每隔一点的一个点之间的平方距离。卷积将内核移动到每个可能的位置,并对该位置进行乘法和,这就是您所需要的。关于“Matlab正在生成[几乎]0”,我想你会发现这正是你想要的,我在答案的最后记下了这一点。我对你的代码进行了彻底的分析,意识到你的想法非常好。内核实际上是以多个8152x200数组的形式存储每个像素与所有其他像素的距离,然后卷积完成乘法和加法的其余工作。我只觉得在第一行,kernel应该定义为
    kernel=bsxfun(@plus,(-s1+1:s1-1)。^2',(-s2+1:s2-1)。^2)conv2
    期间使用了
    same
    标志,因此我们的结果不会受到影响。