Вы можете использовать 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
можно найти здесь .
* Весь расчет занимает менее минуты.