我正在MATLAB中处理两个512x512图像,即域图像和范围图像。我想要完成的是以下内容:
为实现这一目标,我编写了以下代码:
RangeImagecolor = imread('input.png'); %input is 512x512
DomainImagecolor = imread('input.png'); %Range and Domain images are identical
RangeImagetemp = rgb2gray(RangeImagecolor);
DomainImagetemp = rgb2gray(DomainImagecolor);
RangeImage = im2double(RangeImagetemp);
DomainImage = im2double(DomainImagetemp);
%For the (k,l)th 8x8 range image block
for k = 1:64
for l = 1:64
minerror = 9999;
min_i = 0;
min_j = 0;
for i = 1:64
for j = 1:64
%here I compute for the (i,j)th domain block, the transformed domain block stored in D_trans
error = 0;
D_trans = zeros(8,8);
R = zeros(8,8); %Contains the pixel values of the (k,l)th range block
for m = 1:8
for n = 1:8
R(m,n) = RangeImage(8*k-8+m,8*l-8+n);
%ApplyTransformation can depend on (k,l) so I can't compute the transformation outside the k,l loop.
[m_dash,n_dash] = ApplyTransformation(8*i-8+m,8*j-8+n);
D_trans(m,n) = DomainImage(m_dash,n_dash);
error = error + (R(m,n)-D_trans(m,n))^2;
end
end
if(error < minerror)
minerror = error;
min_i = i;
min_j = j;
end
end
end
end
end
作为ApplyTransformation的一个例子,可以使用身份转换:
function [x_dash,y_dash] = Iden(x,y)
x_dash = x;
y_dash = y;
end
现在我遇到的问题是计算时间很长。上述代码中的计算顺序为64 ^ 5,其顺序为10 ^ 9。这种计算应该在最坏的几分钟或一小时内进行。计算仅50次迭代大约需要40分钟。我不知道为什么代码运行得这么慢。
感谢您阅读我的问题。
答案 0 :(得分:5)
您可以使用im2col
*将图片转换为列格式,以便每个块形成[64 * 4096]
矩阵的列。然后对每列应用转换,并使用bsxfun
来向量化错误计算。
DomainImage=rand(512);
RangeImage=rand(512);
DomainImage_col = im2col(DomainImage,[8 8],'distinct');
R = im2col(RangeImage,[8 8],'distinct');
[x y]=ndgrid(1:8);
function [x_dash, y_dash] = ApplyTransformation(x,y)
x_dash = x;
y_dash = y;
end
[x_dash, y_dash] = ApplyTransformation(x,y);
idx = sub2ind([8 8],x_dash, y_dash);
D_trans = DomainImage_col(idx,:); %transformation is reduced to matrix indexing
Error = 0;
for mn = 1:64
Error = Error + bsxfun(@minus,R(mn,:),D_trans(mn,:).').^2;
end
[minerror ,min_ij]= min(Error,[],2); % linear index of minimum of each block;
[min_i min_j]=ind2sub([64 64],min_ij); % convert linear index to subscript
解释:
我们的目标是尽可能减少循环次数。为此,我们应该避免矩阵索引,而应该使用矢量化。嵌套循环应转换为一个循环。作为第一步,我们可以创建一个更优化的循环:
min_ij = zeros(4096,1);
for kl = 1:4096 %%% => 1:size(D_trans,2)
minerror = 9999;
min_ij(kl) = 0;
for ij = 1:4096 %%% => 1:size(R,2)
Error = 0;
for mn = 1:64
Error = Error + (R(mn,kl) - D_trans(mn,ij)).^2;
end
if(Error < minerror)
minerror = Error;
min_ij(kl) = ij;
end
end
end
我们可以重新安排循环,我们可以将最内部的循环作为外部循环,并将最小值的计算与错误的计算分开。
% Computation of the error
Error = zeros(4096,4096);
for mn = 1:64
for kl = 1:4096
for ij = 1:4096
Error(kl,ij) = Error(kl,ij) + (R(mn,kl) - D_trans(mn,ij)).^2;
end
end
end
% Computation of the min
min_ij = zeros(4096,1);
for kl = 1:4096
minerror = 9999;
min_ij(kl) = 0;
for ij = 1:4096
if(Error(kl,ij) < minerror)
minerror = Error(kl,ij);
min_ij(kl) = ij;
end
end
end
现在代码的排列方式可以最好地进行矢量化:
Error = 0;
for mn = 1:64
Error = Error + bsxfun(@minus,R(mn,:),D_trans(mn,:).').^2;
end
[minerror ,min_ij] = min(Error, [], 2);
[min_i ,min_j] = ind2sub([64 64], min_ij);
*如果您没有图像处理工具箱,可以找到更有效的im2col
实施{。{3}}。
*整个计算只需不到一分钟。
答案 1 :(得分:2)
首先要做的事 - 你的代码什么都不做。但是你可能会对这个最小错误的东西做些什么,只是忘了在这里粘贴它,或者仍然需要编写那个位。没关系。
您的代码的一个大问题是您计算了64x64生成的图像和源图像块的转换。复杂操作的64 ^ 5次迭代必然很慢。相反,您应该立即计算所有转换并保存它们。
allTransMats = cell(64);
for i = 1 : 64
for j = 1 : 64
allTransMats{i,j} = getTransformation(DomainImage, i, j)
end
end
function D_trans = getTransformation(DomainImage, i,j)
D_trans = zeros(8);
for m = 1 : 8
for n = 1 : 8
[m_dash,n_dash] = ApplyTransformation(8*i-8+m,8*j-8+n);
D_trans(m,n) = DomainImage(m_dash,n_dash);
end
end
end
这用于获取allTransMat
并且在k,l循环外部。最好是一个简单的功能。
现在,你可以制作你的大k,l,i,j循环,根据需要比较所有元素。比较也可以按块进行,而不是填充一个小的8x8矩阵,但由于某种原因,每个元素都要进行比较。
m = 1 : 8;
n = m;
for ...
R = RangeImage(...); % This will give 8x8 output as n and m are vectors.
D = allTransMats{i,j};
difference = sum(sum((R-D).^2));
if (difference < minDifference) ...
end
即使这是一个简单的无变换案例,但这会加速代码。
最后,您确定需要将每个转换输出块与源中的每个块进行比较吗?通常,您将block1(a,b)
与block2(a,b)
- 同一位置的块(或像素)进行比较。
编辑:allTransMats也需要k和l。哎哟。没有办法让这个快速进行一次迭代,因为你需要64 ^ 5次调用ApplyTransformation(或者该函数的矢量化,但即便如此,它可能也不会很快 - 我们必须看到这里有帮助的功能) 。
因此,我将重新迭代我的建议以生成所有转换,然后执行查找:应将allTransMats
生成的答案的上半部分更改为包含所有4个循环并生成allTransMats{i,j,k,l};
。它会很慢,没有办法像我在编辑的上半部分所提到的那样。但是,这是一次支付的费用,因为在保存allTransMats
之后,所有进一步的图像分析都可以简单地加载它而不是再次生成它。
但是......你甚至做什么?依赖于源和目标块索引以及像素索引(总共= 6个值)的转换听起来像某个地方的错误,或者是优化的主要候选者,而不是所有其他的。