auraham
auraham

Reputation: 1739

Implement matrix transformations with homogeneous coordinates

Currently, I need to write a program using matlab to transformate a matrix using homogeneous coordinates like this

% for translation
T = [1 0 dx; 0 1 dy; 0 0 1];

For example:

A =
    92    99     1     8    15    67    74    51    58    40
    98    80     7    14    16    73    55    57    64    41
     4    81    88    20    22    54    56    63    70    47
    85    87    19    21     3    60    62    69    71    28
    86    93    25     2     9    61    68    75    52    34
    17    24    76    83    90    42    49    26    33    65
    23     5    82    89    91    48    30    32    39    66
    79     6    13    95    97    29    31    38    45    72
    10    12    94    96    78    35    37    44    46    53
    11    18   100    77    84    36    43    50    27    59

>> I = translate(A, 4, 4)
I =

   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN    92    99     1     8    15    67
   NaN   NaN   NaN   NaN    98    80     7    14    16    73
   NaN   NaN   NaN   NaN     4    81    88    20    22    54
   NaN   NaN   NaN   NaN    85    87    19    21     3    60
   NaN   NaN   NaN   NaN    86    93    25     2     9    61
   NaN   NaN   NaN   NaN    17    24    76    83    90    42

Where NaN cells means 'empty spaces'. As you can see, A matrix was translate 4 units on x axis and 4 units on y axis, leaving NaN values. The output matrix I must be the same size like A.

However, my current program don't work fine using images (It does not put 'NaN' values on empty spaces, it puts '1'):

So, this is my program:

function t_matrix = translate(input_matrix, dx, dy)

    [rows cols] = size(input_matrix);

    t_matrix = input_matrix;
    t_matrix(:) = NaN;

    T = [1 0 dx; 0 1 dy; 0 0 1];

    for n = 1:numel(input_matrix)


        [x y] = ind2sub([rows cols], n);

        v = [x y 1]';

        v = T*v;

        a = floor(v(1));
        b = floor(v(2));

        if a > 0 && b > 0
            t_matrix(a, b) = input_matrix(x,y);
        end
    end

    t_matrix = t_matrix(1:rows, 1:cols);

How can I implement homogeneous transformation using matlab in a easier way?

Only restriction: keep using this matrix:

% for translation
T = [1 0 dx; 0 1 dy; 0 0 1];

And keep NaN values for empty spaces.

Upvotes: 2

Views: 3747

Answers (2)

angainor
angainor

Reputation: 11810

The problem with you code might be that you operate on integers, and NaN is a double value. You can not assign input_matrix to t_matrix. You should create t_matrix using nan function:

 t_matrix = nan(size(input_matrix));

The following is a direct translation of your code, I just removed the loop

function I = translate(input_matrix, dx, dy)
    % get matrix dimensions
    [rows cols] = size(input_matrix);
    T = [1 0 dx; 0 1 dy; 0 0 1];
    % create a nan's output matrix
    I = nan(size(input_matrix));

    % create row-column index pairs
    [R C] = meshgrid(1:cols, 1:rows);
    % append 1 at the end
    IDX = [R(:) C(:) ones(numel(input_matrix),1)]';
    % transform coordinates
    V = floor(T*IDX);
    % find indices that fall into [rows, cols] range
    keep = find(V(1,:)>0 & V(1,:)<=rows & V(2,:)>0 & V(2,:)<=cols);
    % assign output only to the correct indices
    I(sub2ind([rows cols], V(1,keep), V(2,keep))) = input_matrix(sub2ind([rows cols], R(keep), C(keep)))
end

On the other hand, you can obtain the same result as in the question just by running the following function (no T matrix though..)

function I = translate(A, dx, dy)
    I = nan(size(A));
    I(dx+1:end, dy+1:end) = A(1:end-dx, 1:end-dy);
end

Upvotes: 1

Andrey Rubshtein
Andrey Rubshtein

Reputation: 20915

The easiest way achieving it, if you have the image processing toolbox, is to use the built-in functions maketform and imtransform:

I = imread('cameraman.tif');
dx = 40;  
dy = 100;
tform = maketform('affine',[1 0 0; 0 1 0; dx dy 1]);  %#Create a translation matrix
J = imtransform(I,tform,'XData',[0 size(I,2)+dx],'YData',[0 size(I,1)+dy]);
imshow(I), figure, imshow(J)
  • The matrix given as input to maketform is a transpose of yours matrix
  • It is important to set the XData and YData, otherwise you will not get the "translation effect', since imtransform finds the smallest output range.
  • If you want to get the same size as inital image, use the following syntax:

.

 J = imtransform(I,tform,'XData',[0 size(I,2)],'YData',[0 size(I,1)]);

Image Before:

enter image description here

Image After:

enter image description here

Image After (Keeping the same size):

enter image description here

Upvotes: 0

Related Questions