我正在尝试编写一些代码来轮换MATLAB中的图片,即相当于imrotate。我使用矩阵乘法来执行新图像到输入图像的逆映射。但是,它比明确写出等效方程需要更长的时间。有没有更好的方法来执行此乘法?
我更喜欢使用矩阵乘法,因为我可以通过替换变换矩阵RT
来使用相同的代码进行其他变换。
im1 = imread('file.jpg');
[h, w, p] = size(im1);
theta = -pi/6;
hh = round( h*cos(theta) + w*abs(sin(theta)));
ww = round( w*cos(theta) + h*abs(sin(theta)));
R = [cos(theta) -sin(theta); sin(theta) cos(theta)];
T = [w/2; h/2];
RT = [inv(R) T; 0 0 1];
for z = 1:p
for x = 1:ww
for y = 1:hh
% Using matrix multiplication
i = zeros(3,1);
i = RT*[x-ww/2; y-hh/2; 1];
%Using explicit equations
%i(1) = ( (x-ww/2)*cos(theta)+(y-hh/2)*sin(theta)+w/2);
%i(2) = (-(x-ww/2)*sin(theta)+(y-hh/2)*cos(theta)+h/2);
%% Nearest Neighbour
i = round(i);
if i(1)>0 && i(2)>0 && i(1)<=w && i(2)<=h
im2(y,x,z) = im1(i(2),i(1),z);
end
end
end
end
%Revised code
im1 = imread('file.jpg');
[h, w, p] = size(im1);
theta = (pi)/3;
hh = round(h*abs(cos(theta)) + w*abs(sin(theta)));
ww = round(w*abs(cos(theta)) + h*abs(sin(theta)));
im2 = zeros([hh,ww,p], class(im1));
R = [cos(theta) -sin(theta); sin(theta) cos(theta)];
T = [w/2; h/2];
RT = [inv(R) T; 0 0 1];
x=1:ww;
y=1:hh;
[X, Y] = meshgrid(x,y);
orig_pos = [X(:)' ; Y(:)' ; ones(1,numel(X))];
orig_pos_2 = [X(:)'-(ww/2) ; Y(:)'-(hh/2) ; ones(1,numel(X))];
new_pos = round(RT*orig_pos_2); % Round to nearest neighbour
% Check if new positions fall from map:
valid_pos = new_pos(1,:)>=1 & new_pos(1,:)<=w & new_pos(2,:)>=1 & new_pos(2,:)<=h;
orig_pos = orig_pos(:,valid_pos);
new_pos = new_pos(:,valid_pos);
siz = size(im1);
siz2 = size(im2);
% Expand the 2D indices to include the third dimension.
ind_orig_pos = sub2ind(siz2,orig_pos(2*ones(p,1),:),orig_pos(ones(p,1),:), (1:p)'*ones(1,length(orig_pos)));
ind_new_pos = sub2ind(siz, new_pos(2*ones(p,1),:), new_pos(ones(p,1),:), (1:p)'*ones(1,length(new_pos)));
im2(ind_orig_pos) = im1(ind_new_pos);
imshow(im2);
答案 0 :(得分:1)
你应该对for循环进行矢量化,看起来并不难。它会带给你很多。最棘手的是位置计算并忽略旋转后从图像上掉落的位置。
解决方案:
x=1:ww
y=1:hh
[X, Y] = meshgrid(x,y);
orig_pos = [X(:)' ; Y(:)' ; ones(1,numel(X))];
new_pos = round(RT*orig_pos); % round to nearest neighbour
% check if new positions fall from map:
valid_pos = new_pos(1,:)>=1 & new_pos(1,:)<=w & new_pos(2,:)>=1 & new_pos(2,:)<=h;
你可以在for循环中对结果矩阵进行赋值处理要忽略的位置,或者只是从源矩阵中删除它们并一次性完成赋值:
orig_pos = orig_pos(:,valid_pos);
new_pos = new_pos(:,valid_pos);
siz = size(im1);
im2 = zeros(siz,class(im1));
% expand the 2d indices to include the third dimension
ind_orig_pos = sub2ind(siz,orig_pos(2*ones(siz(3),1),:),orig_pos(ones(siz(3),1),:), (1:siz(3))'*ones(1,N));
ind_new_pos = sub2ind(siz, new_pos(2*ones(siz(3),1),:), new_pos(ones(siz(3),1),:), (1:siz(3))'*ones(1,N));
im2(ind_orig_pos) = im1(ind_new_pos);
您的代码可能也很慢,因为您没有初始化im2
所以它会在运行时根据需要进行扩展。
作为参考:使用'peppers.png'作为源图像,这整段代码在我的电脑上花了0.12秒,你的代码需要几分钟。最终结果是一样的。