我有两张图片,比方说A
和B
,尺寸不必相同。 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
中的A
和96*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'.
答案 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)
正如米哈伊尔所说,你实际上做得非常棒。实际上并没有那么多你可以改进的东西。
你只能做一些小事:
由于A
小于B
,交换处理顺序将导致bsxfun
执行更多繁重的工作。因为那是&#34;更接近硅&#34;比JIT的MATLAB循环,这将是有益的。
使用tic...toc
和A = 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)。