【问题标题】:Warping an image using control points使用控制点扭曲图像
【发布时间】:2015-11-22 20:11:29
【问题描述】:

我想根据从here提取的这个方案使用控制点转换图像:

AB 包含源和目标顶点的坐标。

我将转换矩阵计算为:

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');

到目前为止,它似乎可以正常工作,因为(使用归一化坐标)源顶点会产生其目标顶点:

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

问题是imtransform 产生了意想不到的结果:

Z = imtransform(X,T,'XData',[1 info.Width], 'YData',[1 info.Height]);
imwrite(Z,'projective.png');

如何使用imtransform 来产生我预期的结果?:

有没有其他方法可以实现?

【问题讨论】:

  • 我对matlab的了解不够多,尤其不知道您的代码中tdata的含义。但我个人会尝试在 matlab 中或使用单独的工具手动重现these steps,以检查计算出的矩阵是否有意义。请注意,投影变换矩阵仅定义为标量因子,因此在比较它们之前相应地缩放您的矩阵。如果矩阵一致,则问题在于应用它们,否则问题在于找到它们。
  • 你看过imtransform的demo吗? (在 Octave 提示符下运行 demo imtransform)。如果你看看documentation,你的问题正好是第一个demo的第6个数字。
  • 您的问题是您在执行 Z = imtransform(X,T,'XData',[1 info.Width], 'YData',[1 info.Height]) 时裁剪了输出图像;使用 tformfwd 和 A 来计算 XData 和 YData 范围。

标签: matlab image-processing octave homography projective-geometry


【解决方案1】:

您必须将控制点“调整”到您正在使用的图像的大小。我这样做的方法是计算A 中控制点的角与源图像的角之间的仿射变换(最好让这些点按顺时针顺序排列)。

我要指出的一点是矩阵A 中的点顺序与您显示的图片不匹配,所以我在下面的代码中修复了它...

这是估计单应性的代码(在 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

我明白了:

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

现在让我们可视化这些点:

% 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

最后我们可以在源图像上应用转换:

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

【讨论】:

    【解决方案2】:

    您的问题是,当您在 imtransform 中指定 XDataYData 时,您不小心裁剪了输出图像。一种选择是使用tformfwd with 来转换A 以计算有效的XDataYData 范围。

    [U,V] = tformfwd(T, A(:,1), A(:,2));
    
    Z = imtransform(X,T,'XData',[min(U) max(U)], 'YData', [min(V) max(V)]);
    

    【讨论】:

    • 谢谢,使用 [U,V] 裁剪区域,imtransform 裁剪这个区域。但是输出的图片还是上面那个错误的图片(用[U,V]坐标裁剪):
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-31
    • 2014-08-13
    • 2016-03-18
    • 2016-01-02
    • 2017-02-12
    相关资源
    最近更新 更多