【问题标题】:How can I rotate an image using only affine2d and transformPointsForward in Matlab?如何在 Matlab 中仅使用 affine2d 和 transformPointsForward 旋转图像?
【发布时间】:2021-04-29 05:43:26
【问题描述】:

我想在 Matlab 中旋转(30 度)图像,但不使用 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)。

【问题讨论】:

    标签: image matlab image-translation


    【解决方案1】:

    正确的做法并不是那么简单。

    • 您帖子中的旋转矩阵是“居中”的 - (0,0) 是中心坐标。
      我们需要转换矩阵,其中 (1,1) 是左上角坐标。
    • 您需要转换图像的所有坐标。
      在您的帖子中,您只是在转换坐标 (1,1)、(2,2)、(3,3)...
    • 使用正向变换会创建“空洞” - 目标图像中的所有像素都不会被填充。
      我们需要使用反向变换,并且对于每个目标像素,获取源像素的坐标(目标到源的变换被认为是“反向变换”)。
      transformPointsForward 使用逆变换等效于反向变换。
      注意:您的变换矩阵实际上是“反向变换”。

    以下是解决方法(请阅读 cmets):

    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));
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    

    前向变换的结果(错误的方式):

    后向变换的结果(正确的方式):

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 2011-04-29
      • 1970-01-01
      • 2017-03-07
      • 2017-02-16
      相关资源
      最近更新 更多