Как я могу повернуть изображение, используя только affine2d и transformPointsForward в Matlab?

Я хотел бы повернуть (30 градусов) изображение в Matlab, но без использования imwarp, imtranslate, imrotate, imresize.

Мой код следующий:

      image = imread('image.jpg');
theta = 30;
tform = affine2d([cosd(theta) sind(theta) 0; -sind(theta) cosd(theta) 0; 0 0 1]);
[X,Y] = transformPointsForward(tform,1:800,1:800);

Я считаю, что мне следует использовать imref2d, но я не совсем уверен, как это сделать. Как мне назначить новые координаты? Я бы хотел, чтобы остальное пространство (используемое изображением) было черным (значение пикселя = 0).

1 ответ

Правильный способ сделать это не так уж и тривиально.

  • Матрица вращения в вашем сообщении «центрирована» - (0,0) - координата центра.
    Нам нужна матрица преобразования, в которой (1,1) - левая верхняя координата.
  • Вам нужно преобразовать все координаты изображения.
    В своем сообщении вы только преобразовываете координаты (1,1), (2,2), (3,3)...
  • Использование прямого преобразования создает «дыры» - не все пиксели в конечном изображении заполняются.
    Нам нужно использовать обратное преобразование, и для каждого целевого пикселя получить координату исходного пикселя (преобразование из целевого в исходное считается «обратным преобразованием»).
    Используя обратное преобразование с transformPointsForwardэквивалентно обратному преобразованию.
    Примечание. Ваша матрица преобразования на самом деле является «обратным преобразованием».

Вот как это решить (читайте комментарии):

      I = rgb2gray(imread('peppers.png')); % Read sample image and convert to gray.

[rows, cols] = size(I);

theta = 30;

% The rotation matrix is "centered" - coordinate (0, 0) is the center:
cT = [cosd(theta) -sind(theta) 0; sind(theta) cosd(theta) 0; 0 0 1];

top2cen = [1          0          0
           0          1          0
           (cols+1)/2 (rows+1)/2 1];
       
cen2top = [1            0          0
           0            1          0
           -(cols+1)/2 -(rows+1)/2 1];

% We need the rotation matrix to be "top left" - coordinate (1, 1) is the top left coordinate:
T = cen2top*cT*top2cen; % Note: you don't really need to use matrix multiplications for solving this.

tform = affine2d(T);

% All the combinations of u,v coordinates
[U, V] = meshgrid(1:cols, 1:rows);

% Transform all the (u, v) coordinates of the input I.
[X, Y] = transformPointsForward(tform, U, V);

% Round the coordinates - the interpolation method is going to Nearest Neighbor.
X = round(X);
Y = round(Y);

J = zeros(size(I), 'like', I);

% Limit the X,Y coordinates to the valid range.
limX = max(min(X, cols), 1);
limY = max(min(Y, rows), 1);

% Copy the (u,v) pixel in I to position (x,y) in J.
J(sub2ind(size(I), limY, limX)) = I(sub2ind(size(I), V, U));

% Oops... J has many holes...
figure;imshow(J);
imwrite(J, 'fwJ.png');

% Correct way:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% We must inverse the transformation - use backward transformation instead of forward transformation.
%cT = inv([cosd(theta) -sind(theta) 0; sind(theta) cosd(theta) 0; 0 0 1]);
cT = [cosd(theta) sind(theta) 0; -sind(theta) cosd(theta) 0; 0 0 1]; % Inverse transformation matrix.

% Repeate the process with inversed transformation.
T = cen2top*cT*top2cen;
tform = affine2d(T);
[U, V] = meshgrid(1:cols, 1:rows);

% Transform all the (x, y) coordinates of the input I.
[X, Y] = transformPointsForward(tform, U, V);  % Name the coordinates U, V

% Round the coordinates - the interpolation method is going to Nearest Neighbor.
X = round(X);
Y = round(Y);

J = zeros(size(I), 'like', I);

% Limit the X,Y coordinates to the valid range.
limX = max(min(X, cols), 1);
limY = max(min(Y, rows), 1);

J(sub2ind(size(I), V, U)) = I(sub2ind(size(I), limY, limX));

% Zero the margins (place zeros where X, Y are outside of the valid range):
J((X < 1) | (Y < 1) | (X > cols) | (Y > rows)) = 0;

figure;imshow(J)
imwrite(J, 'J.png');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


% Testing
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Reference:
K = imrotate(I, 30, 'nearest', 'crop');
figure;imshow(K)

% Display the difference from imrotate (images are equal).
figure;imagesc(double(K) - double(J));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Результат прямого преобразования (неправильный путь):

Результат обратного преобразования (верный путь):

Другие вопросы по тегам