正确的做法并不是那么简单。
- 您帖子中的旋转矩阵是“居中”的 - (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));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
正向变换的结果(错误的方式):
后向变换的结果(正确的方式):