Reputation: 1739
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
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
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)
maketform
is a transpose of yours matrixXData
and YData
, otherwise you will not get the "translation effect', since imtransform
finds the smallest output range..
J = imtransform(I,tform,'XData',[0 size(I,2)],'YData',[0 size(I,1)]);
Image Before:
Image After:
Image After (Keeping the same size):
Upvotes: 0