我想寫我自己的圖像旋轉功能,使用線性插值(見下面的代碼)。在示例256x256圖像上運行我的代碼需要大約8秒,或每像素大約0.12ms。在相同的圖像上使用雙線性插值運行Matlab的旋轉函數需要大約0.2秒,或每像素約0.003毫秒 - 大約提高一百倍。Matlab的速度如此之快?
我猜想有一些vectorisation優化,我失蹤,但我不知道在哪裏。任何建議,非常感謝。
下面的代碼;
function [ output ] = rot_input_img_by_angle(input_img, angle)
%rot_input_img_by_angle Rotates the given image by angle about position
% Given an image in the format [y, x, c], rotates it by the given angle
% around the centre of the image
if(nargin < 2)
error('input_img and angle parameters are both required');
end
if(angle == 0)
output = input_img;
return;
end
position = [0 0];
[height, width, channels] = size(input_img);
num_pixels = height * width;
half_width = width/2 - 0.5;
half_height = height/2 - 0.5;
% Compute the translation vector to move from a top-left origin to a
% centred-origin
T = [-half_width half_height]';
% A lambda function for creating a 2D rotation matrix
rotmat = @(th) [cos(th) -sin(th); sin(th) cos(th)];
% Convert angle to radians and generate rotation matrix R for CR
% rotation
R = rotmat(deg2rad(angle));
output = zeros(height, width, channels);
for y=1:height
for x=1:width
loc = [x-1 y-1]';
% Transform the current pixel location into the
% origin-at-centre coordinate frame
loc = loc .* [1; -1] + T;
% Apply the inverse rotation mapping to this ouput pixel to
% determine the location in the original input_img that this pixel
% corresponds to
loc = R * loc;
% Transform back from the origin-at-centre coordinate frame to
% the original input_img's origin-at-top-left frame
loc = (loc - T) .* [1; -1] + [1; 1];
if((loc(1) < 1) || (loc(1) > width) || (loc(2) < 1) || (loc(2) > height))
% This pixel falls outside the input_img - leave it at 0
continue;
end
% Linearly interpolate the nearest 4 pixels
left_x = floor(loc(1));
right_x = ceil(loc(1));
top_y = floor(loc(2));
bot_y = ceil(loc(2));
if((left_x == right_x) & (top_y == bot_y))
% The sample pixel lies directly on an original input_img pixel
output(y, x, :) = input_img(y, x, :);
else
% The sample pixel lies inbetween several pixels
% Location of the nearest 4 pixels
px_locs = [left_x right_x left_x right_x; top_y top_y bot_y bot_y];
px_dists = distance(loc, px_locs);
px_dists = px_dists ./ sum(px_dists);
% Take the linearly interpolated average of each color
% channel's value
for c=1:channels
output(y, x, c) = ...
px_dists(1) * input_img(px_locs(1, 1), px_locs(2, 1), c) + ...
px_dists(2) * input_img(px_locs(1, 2), px_locs(2, 2), c) + ...
px_dists(3) * input_img(px_locs(1, 3), px_locs(2, 3), c) + ...
px_dists(4) * input_img(px_locs(1, 4), px_locs(2, 4), c);
end
end
end
end
output = cast(output, class(input_img));
end
的緩慢最有可能是由於嵌套的for循環,在內部循環中運行大量代碼(創建變量,計算矩陣,評估函數,if語句分支等)。我猜想Matlab的'imrotate'大部分速度是由於使用優化的編譯代碼(在'mex'函數中)。如果你真的想改進你的代碼,運行Matlab分析器來找出什麼是最慢的部分。然而,如果你的目標是速度,你可能會開心地使用內置的'imrotate'。 – nibot