仿射变换能够保持图像的“平直性”,包括旋转,缩放,平移,错切操作。一般而言,仿射变换矩阵为2*3的矩阵,第三列的元素起着平移的作用,前面两列的数字对角线上是缩放,其余为旋转或者错切的作用。透视变换原理及实现请看我
下篇博客 <https://blog.csdn.net/cuixing001/article/details/80261189>。
设仿射变换矩阵T = [a11,a12,a13 ; a21,a22,a23]; 图像上fixed points坐标为(Xk,Yk);moving
points坐标为(xk,yk),其中k=1,2,...,n。
为了求解该仿射变换矩阵T的6个未知参数,理论上至少需要6个方程联立求解,即需要3组点集对,n>=3,当n>3时用最小二乘法求解未知参数。并且这三组点不共线。
数学展开式如下图:
下面根据上面公式给出实现代码,图像使用最近邻插值。
%% 读取原图像 clear ; close all; src=rgb2gray(imread('lena.png')); imshow(src); %%
method1,用3组点集对图像进行仿射变换,调用matlab系统函数 fixedPoints = [1,1; 1,100;100,100];
movingPoints = [20,20; 120,80; 160,200]; tic; tform =
fitgeotrans(movingPoints,fixedPoints,'affine'); dst_img = imwarp(src,tform);
t_sys = toc; figure;imshowpair(src,dst_img,'montage');
title(['系统函数的仿射变换图像,耗时(s):',num2str(t_sys)]) %% method2,用3组点集对图像进行仿射变换,解方程求变换矩阵
% T = [a11,a12,a13;a21,a22,a33]; % 满足fixed_pt_matrix = T*moving_pt_matrix; tic;
fixed_pt_matrix = fixedPoints'; moving_pt_matrix =
[movingPoints';ones(1,size(movingPoints,1))]; T =
fixed_pt_matrix/moving_pt_matrix; width = size(src,2); height = size(src,1);
[moving_pt_x,moving_pt_y] = meshgrid(1:width,1:height); coridate_affine =
T*[moving_pt_x(:)';% 对原来图像所有坐标点变换到新平面上 moving_pt_y(:)'; ones(1,width*height)];
x_temp = coridate_affine(1,:); y_temp = coridate_affine(2,:); fixed_pt_x =
reshape(x_temp,... size(moving_pt_x))+... abs(min(x_temp))+1; fixed_pt_y =
reshape(y_temp,... size(moving_pt_y))+... abs(min(y_temp))+1; fixed_pt_x =
round(fixed_pt_x); fixed_pt_y = round(fixed_pt_y); dst_affine_img =
zeros(round(max(y_temp)-min(y_temp))+1,... round(max(x_temp)-min(x_temp))+1);
for i = 1:height for j = 1:width
dst_affine_img(fixed_pt_y(i,j),fixed_pt_x(i,j)) = src(i,j); end end t_manual =
toc; figure;imshowpair(src,uint8(dst_affine_img),'montage');
title(['计算的仿射变换图像,耗时(s):',num2str(t_manual)]) %% 插值处理 [index_i,index_j] =
find(dst_affine_img); for i = 1:size(dst_affine_img,1) for j =
1:size(dst_affine_img,2) [min_distance,index_near] =
min(sqrt((i-index_i).^2+(j-index_j).^2)); if dst_affine_img(i,j)==0 &&
min_distance<=1 dst_affine_img(i,j) =
dst_affine_img(index_i(index_near),index_j(index_near)); end end end figure;
imshowpair(src,uint8(dst_affine_img),'montage'); title('插值后图像')
再看一个对点集的简单测试,T = [1,1,0;2,1,0];
%% 坐标点的仿射变换 [pt_x,pt_y] = meshgrid(1:10); pt_x = pt_x(:); pt_y = pt_y(:);
figure;subplot(211);plot(pt_x,pt_y,'ro');grid on; title('原始点集') dst_pt =
zeros(length(pt_x),2); tf_affine = [1,1,0;2,1,0]; for i = 1:length(pt_x) dst =
tf_affine*[pt_x(i),pt_y(i),1]'; dst_pt(i,:) = [dst(1),dst(2)]; end
subplot(212);plot(dst_pt(:,1),dst_pt(:,2),'bo');grid on title('仿射后点集')reference:
https://ww2.mathworks.cn/help/images/ref/fitgeotrans.html?s_tid=srchtitle
<https://ww2.mathworks.cn/help/images/ref/fitgeotrans.html?s_tid=srchtitle>
热门工具 换一换