如何在matlab中比较两个图像中的所有补丁?

时间:2014-03-25 06:52:52

标签: matlab optimization image-processing nearest-neighbor

我有两张图片,比方说AB,尺寸不必相同。 A的尺寸为255×255,B的尺寸为100×100。对于我的问题,补丁的尺寸是5×5。我需要做的是将A中的所有补丁与B中的所有补丁进行比较。

每个补丁都会与一些相邻补丁重叠。要明确这一点,A中的第一个补丁将是A(1:5,1:5)(MATLAB表示法)。第二个补丁A(2:6,1:5)等等,一直到第一行末尾的A(251:255,1:5),一直到A(251:255,251:255)的最后一个补丁A

我必须将这些补丁中的每一个与B中的所有补丁进行比较。如您所见,251*251中的A96*96补丁中有B个补丁。所以有很多比较要做。比较只是欧几里德距离,即我只需要取两个补丁的差值并对正方形求和。对于每个补丁比较,我将获得标量值作为结果。

我在MATLAB中实现了这个,但是需要几分钟才能执行。所以请建议我实现这个的最快方法。这部分是我整个项目的瓶颈。我写的代码如下。我不是一个明确的专家所以请原谅我的错误。

row = size(A,1);    
col = size(A,2);

row2 = size(B,1);    
col2 = size(B,2);

patch_long = zeros(5,5,(row2-4)*(col2-4));

idx = 1;

for i = 1:row2-4    
    for j = 1:col2-4

        patch_long(:,:,idx) = B(i:i+4,j:j+4);

        idx = idx+1;

    end

end

%// I rearranged 'B' matrix as 3d matrix with each patch arranged like 
%// slide behind one by one

parfor m = 1:row-4    
    for n = 1:col-4

        temp1 = bsxfun(@minus,(A(m:m+4,n:n+4)),patch_long);
        temp2 = sum(sum(temp1.^2));

        count = sum(temp2 <=threshold);

        if count > 1 
            % Do xyzend
        end

    end
end

%// count counts how many patches in 'B' are close to a particular patch in 'A'.

2 个答案:

答案 0 :(得分:4)

您可以使用im2col提取所有修补程序

pA = im2col( A, [5 5], 'sliding' );
pB = im2bol( B, [5 5], 'sliding' );
% compute squared difference
D = sum( bsxfun( @minus, permute( pA, [2 3 1] ), permute( pB, [3 2 1] ) ).^2, 3 );

顺便说一句,如果您不需要所有距离并且愿意为k最近邻居的近似值而妥协,您可能会发现PatchMatch非常有用:
这是为图像补丁量身定制的近似k - 最近邻居算法。它在内存(空间)使用方面非常高效且非常快。

答案 1 :(得分:3)

正如米哈伊尔所说,你实际上做得非常棒。实际上并没有那么多你可以改进的东西。

你只能做一些小事:

  1. 交换矩阵的处理顺序
  2. 交换循环顺序
  3. 由于A小于B,交换处理顺序将导致bsxfun执行更多繁重的工作。因为那是&#34;更接近硅&#34;比JIT的MATLAB循环,这将是有益的。

    使用tic...tocA = rand(255)进行一次简单的B = rand(10)测试(我没有一整天!:)给出了

    Elapsed time is 3.460361 seconds.  %// original processing order
    Elapsed time is 1.629848 seconds.  %// inverted processing order 
    

    对于您的情况,差异当然会减少,但这可能很重要。

    交换循环顺序(循环遍历内循环中的行,外循环上的列)是有效的,因为MATLAB以列主顺序存储数据。然后交换顺序意味着指针偏移计算可以在内循环中重复使用,因此需要较少的操作。通常情况下,这可以达到约30%的差异,但是,最近版本的MATLAB已经大大改进了(仍然不确定如何),并且你不使用1列,但是5 ......所以这可能是没有那么重要。

    使用不同的循环顺序进行相同的测试,得出:

    Elapsed time is 3.462599 seconds. %// original loop order
    Elapsed time is 3.272909 seconds. %// inverted loop order
    

    结合一切:

    Elapsed time is 1.571496 seconds. %// Both optimizations implemented
    

    我的代码:

    %// random data for testing
    A = rand(255);
    B = rand(10);
    threshold = rand;
    
    [rowA, colA] = size(A);
    [rowB, colB] = size(B);
    
    patch_long = zeros(5,5, (rowA-4)*(colA-4));
    
    tic
    
    %// re-arrange A into 3D array of 5×5 patches 
    idx = 1;
    for jj = 1:colA-4     
        c = jj:jj+4;      %// re-use column indices
        for ii = 1:rowA-4 %// inner loop is over the rows
    
            patch_long(:,:,idx) = A(ii:ii+4, c);        
            idx = idx+1;
    
        end
    
    end
    
    %// The heavy lifting
    for n = 1:colB-4     %// let bsxfun do more work; loop over smallest array here
        c = n:n+4;       %// re-use column indices
        for m = 1:rowB-4 %// inner loop is over the rows
    
            temp1 = bsxfun(@minus, B(m:m+4, c), patch_long);
            count = sum( sum(temp1.^2) <= threshold );
    
        end
    end
    
    toc
    

    请注意,我没有使用parfor,只是为了让每个人都可以复制一切。在真正的问题上使用parfor可以给我

    Elapsed time is 387.802798 seconds. %// original version, but without parfor
    Elapsed time is 362.991760 seconds. %// both optimizations, WITH parfor
    

    但我认为这主要是因为我的PC工作非常糟糕(AMD-A6 3650 APU)。