matlab - Cómo deformar una imagen usando puntos de control
image-processing octave (2)
Quiero convertir una imagen usando puntos de control de acuerdo con este esquema extraído de aquí :
A
y B
contiene las coordenadas de la fuente y los vértices de un objetivo.
Estoy computando la matriz de transformación como:
A = [51 228; 51 127; 191 127; 191 228];
B = [152 57; 219 191; 62 240; 92 109];
X = imread(''rectangle.png'');
info = imfinfo(''rectangle.png'');
T = cp2tform(A,B,''projective'');
Hasta aquí parece funcionar correctamente, porque (usando coordenadas normalizadas) un vértice fuente produce su vértice objetivo:
H = T.tdata.T;
> [51 228 1]*H
ans =
-248.2186 -93.0820 -1.6330
> [51 228 1]*H/ -1.6330
ans =
152.0016 57.0006 1.0000
El problema es que imtransform
produce un resultado inesperado:
Z = imtransform(X,T,''XData'',[1 info.Width], ''YData'',[1 info.Height]);
imwrite(Z,''projective.png'');
¿Cómo puedo usar imtransform
para producir este mi resultado esperado ?:
¿Hay alguna forma alternativa de lograrlo?
Debe "adaptar" los puntos de control al tamaño de la imagen con la que está trabajando. La forma en que lo hice es calculando una transformación afín entre las esquinas de los puntos de control en A
y las esquinas de la imagen de origen (preferiblemente quiere hacer que los puntos estén en el mismo orden en el sentido de las agujas del reloj).
Una cosa que debo señalar es que el orden de los puntos en su matriz A
no coincide con la imagen que ha mostrado, así que lo arreglé en el siguiente código ...
Aquí está el código para estimar la homografía (probado en MATLAB):
% initial control points
A = [51 228; 51 127; 191 127; 191 228];
B = [152 57; 219 191; 62 240; 92 109];
A = circshift(A, [-1 0]); % fix the order of points to match the picture
% input image
%I = imread(''peppers.png'');
I = im2uint8(checkerboard(32,5,7));
[h,w,~] = size(I);
% adapt control points to image size
% (basically we estimate an affine transform from 3 corner points)
aff = cp2tform(A(1:3,:), [1 1; w 1; w h], ''affine'');
A = tformfwd(aff, A);
B = tformfwd(aff, B);
% estimate homography between A and B
T = cp2tform(B, A, ''projective'');
T = fliptform(T);
H = T.tdata.Tinv
Yo obtengo:
>> H
H =
-0.3268 0.6419 -0.0015
-0.4871 0.4667 0.0009
324.0851 -221.0565 1.0000
Ahora visualicemos los puntos:
% check by transforming A points into B
%{
BB = [A ones(size(A,1),1)] * H; % convert to homogeneous coords
BB = bsxfun(@rdivide, BB, BB(:,end)); % convert from homogeneous coords
%}
BB = tformfwd(T, A(:,1), A(:,2));
fprintf(''error = %g/n'', norm(B-BB));
% visually check by plotting control points and transformed A
figure(1)
subplot(121)
plot(A([1:end 1],1), A([1:end 1],2), ''.-'', ''MarkerSize'',20, ''LineWidth'',2)
line(BB([1:end 1],1), BB([1:end 1],2), ''Color'',''r'', ''Marker'',''o'')
text(A(:,1), A(:,2), num2str((1:4)'',''a%d''), ...
''VerticalAlign'',''top'', ''HorizontalAlign'',''left'')
title(''A''); legend({''A'', ''A*H''}); axis equal ij
subplot(122)
plot(B([1:end 1],1), B([1:end 1],2), ''.-'', ''MarkerSize'',20, ''LineWidth'',2)
text(B(:,1), B(:,2), num2str((1:4)'',''b%d''), ...
''VerticalAlign'',''top'', ''HorizontalAlign'',''left'')
title(''B''); legend(''B''); axis equal ij
Finalmente podemos aplicar la transformación en la imagen fuente:
% transform input image and show result
J = imtransform(I, T);
figure(2)
subplot(121), imshow(I), title(''image'')
subplot(122), imshow(J), title(''warped'')
Su problema es que recortó accidentalmente la imagen de salida cuando especificó su XData
e YData
en imtransform
. Una opción sería usar tformfwd
con para transformar A
para calcular los XData
válidos de XData
e YData
.
[U,V] = tformfwd(T, A(:,1), A(:,2));
Z = imtransform(X,T,''XData'',[min(U) max(U)], ''YData'', [min(V) max(V)]);