如何在matlab中比较两幅图像中的所有面片?
我有两个图像,比如说如何在matlab中比较两幅图像中的所有面片?,matlab,optimization,image-processing,nearest-neighbor,Matlab,Optimization,Image Processing,Nearest Neighbor,我有两个图像,比如说A和B,它们的大小不需要相同Abe的尺寸为255×255,而Bbe的尺寸为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:255251:255)中的最后一个补丁 我必须将这些补丁与B中的所有补丁进行比较。如您所
A
和B
,它们的大小不需要相同<代码>Abe的尺寸为255×255,而B
be的尺寸为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:255251:255)
中的最后一个补丁
我必须将这些补丁与B
中的所有补丁进行比较。如您所见,在A
中有251*251
补丁,在B
中有96*96
补丁。因此,有很多比较需要进行。比较就是欧几里得距离,也就是说,我只取两个面片的差,然后求平方和。对于每个补丁比较,我将得到一个标量值作为结果
我在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'.
row=大小(A,1);
col=尺寸(A,2);
第2行=尺寸(B,1);
col2=大小(B,2);
patch_long=零(5,5,(第2-4行)*(第2-4行));
idx=1;
对于i=1:第2-4行
对于j=1:col2-4
斑块长(:,:,idx)=B(i:i+4,j:j+4);
idx=idx+1;
结束
结束
%//我将“B”矩阵重新排列为3d矩阵,每个面片的排列方式如下
%//一个接一个地滑到后面
m=1的参数:第4行
对于n=1:col-4
temp1=bsxfun(@负,(A(m:m+4,n:n+4)),面片长;
temp2=sum(sum(temp1.^2));
计数=总和(temp2 1
%多西泽德
结束
结束
结束
%//计数计算“B”中与“a”中特定修补程序接近的修补程序的数量。
您可以使用来提取所有修补程序
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
近邻的近似值妥协,您可能会发现非常有用:这是一个近似的
k
-最近邻算法,专门为图像修补程序量身定制。它在内存(空间)使用方面非常有效,速度也非常快。正如Mikhail提到的那样,你的工作做得非常出色。你真的没有什么可以改进的
您只能做几件小事:
A
小于B
,交换处理顺序将导致bsxfun
承担更多的繁重工作。因为这比JIT'ed MATLAB循环“更接近硅”,这将是有益的
用a=rand(255)
和B=rand(10)
做一个简单的tic…toc
测试(我没有一整天的时间!)
对于您的情况,差异当然会小一些,但这可能是非常重要的
交换循环顺序(在内部循环的行上循环,在外部循环的列上循环)这是因为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
但我认为这主要是因为我的工作电脑很差(AMD-A63650APU)你实际上做了一个很好的矢量化。看起来这不能明显改善。考虑算法的改进。比如,你真的需要比较所有的补丁吗?你碰巧有双精度的GPU吗?你有什么版本的Matlab?我不知道GPU。我的MATLAB版本是2012B.@你的意思是我应该在循环时先写“for cols”,然后写“for rows”?如果在命令提示符中键入
gpuDevice
,你会看到什么?查看我的im2col
实现(我现在在R2010b上),它没有做任何与OP已经做的不同的事情,除了使用更多的内存…除了缩短代码,我不能产生任何明显的速度差异。也许在以后的版本中实现发生了更改;你能用你的(较新)版本验证加速吗?@RodyOldenhuis我没有访问较新版本的权限。抱歉。@akhilc,在这种情况下,您只需要每个补丁的10个最近邻(NN):如果它们比阈值更接近,则使用所有,如果不是,则仅使用其中的一部分。要精确获得10个NN,您确实需要与所有其他补丁进行广泛比较。但是,如果您愿意进行一些近似,您可以获得(近似值)10 NN快得多。看看PatchMatch!如果我理解正确,PatchMatch是蛮力方法的早期版本。这意味着,它仍然是O(N²)最坏情况(只有最后一个补丁低于阈值)。这是否正确?@akhilc我在下载的版本中看到了一个readme.txt
文件。非常感谢。让我试试这个,稍后再给你回复。我为a(255255)和B(50,50)运行了你的优化代码“行先列法”耗时30秒,建议的循环法耗时29.5秒。我认为,对于更大的图像,这可以节省我大量的时间。虽然你的第二个建议对我来说有点难以采纳。我的意思是使用“B”上的循环。因为“阈值”实际上是一个矩阵。对于
%// 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
Elapsed time is 387.802798 seconds. %// original version, but without parfor
Elapsed time is 362.991760 seconds. %// both optimizations, WITH parfor