Obecnie muszę napisać program używający matlab do transformacji macierzy za pomocą jednorodnych współrzędnych, takich jak ta

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

Na przykład:

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

Gdzie NaN komórki oznaczają „puste spacje”. Jak widać, macierz A przesunęła 4 jednostki na osi x i 4 jednostki na osi y, pozostawiając wartości NaN. Macierz wyjściowa I musi mieć taki sam rozmiar jak A.

Jednak mój obecny program nie działa poprawnie przy użyciu obrazów (nie umieszcza wartości „NaN” w pustych miejscach, umieszcza „1”):

Oto mój 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);

Jak w łatwiejszy sposób zaimplementować transformację jednorodną za pomocą programu Matlab?

Jedyne ograniczenie: nadal używaj tej matrycy:

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

I zachowaj wartości NaN dla pustych przestrzeni.

2
auraham 24 wrzesień 2012, 00:42

2 odpowiedzi

Najlepsza odpowiedź

Problem z twoim kodem może polegać na tym, że operujesz na liczbach całkowitych, a NaN jest wartością podwójną. Nie możesz przypisać input_matrix do t_matrix. Powinieneś utworzyć t_matrix za pomocą funkcji nan:

 t_matrix = nan(size(input_matrix));

Poniżej znajduje się bezpośrednie tłumaczenie twojego kodu, właśnie usunąłem pętlę

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

Z drugiej strony możesz uzyskać ten sam wynik, co w pytaniu, po prostu uruchamiając następującą funkcję (choć bez macierzy T..)

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
1
angainor 24 wrzesień 2012, 12:24

Najłatwiejszym sposobem osiągnięcia tego celu, jeśli masz zestaw narzędzi do przetwarzania obrazu, jest użycie wbudowanych funkcji maketform i 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)
  • Macierz podana jako dane wejściowe do maketform jest transpozycją twojej macierzy
  • Ważne jest, aby ustawić XData i YData, w przeciwnym razie nie uzyskasz "efektu tłumaczenia", ponieważ imtransform znajduje najmniejszy zakres wyjściowy.
  • Jeśli chcesz uzyskać taki sam rozmiar jak obraz początkowy, użyj następującej składni:

.

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

Obraz przed:

enter image description here

Obraz po:

enter image description here

Obraz po (zachowując ten sam rozmiar):

enter image description here

0
Andrey Rubshtein 24 wrzesień 2012, 01:17