Warping an image using control points

后端 未结 2 1506
慢半拍i
慢半拍i 2020-12-09 18:10

I want to convert an image using control points according to this scheme extracted from here:

A and B contains the coordinates of

相关标签:
2条回答
  • 2020-12-09 19:05

    You have to "adapt" the control points to the size of the image you're working with. The way I did this is by computing an affine transformation between the corners of the control points in A and the corners of the source image (preferrably you want to make the points are in the same clockwise order).

    One thing I should point out is that the order of points in your matrix A does not match the picture you've shown, so I fixed that in the code below...

    Here is the code to estimate the homography (tested in 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
    

    I get:

    >> H
    H =
       -0.3268    0.6419   -0.0015
       -0.4871    0.4667    0.0009
      324.0851 -221.0565    1.0000
    

    Now let's visualize the points:

    % 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
    

    Finally we can apply the transformation on the source image:

    % transform input image and show result
    J = imtransform(I, T);
    figure(2)
    subplot(121), imshow(I), title('image')
    subplot(122), imshow(J), title('warped')
    

    0 讨论(0)
  • 2020-12-09 19:11

    Your problem is that you accidentally cropped the output image when you specified your XData and YData in imtransform. One option would be to use tformfwd with to transform A to compute the valid XData and YData ranges.

    [U,V] = tformfwd(T, A(:,1), A(:,2));
    
    Z = imtransform(X,T,'XData',[min(U) max(U)], 'YData', [min(V) max(V)]);
    
    0 讨论(0)
提交回复
热议问题