图像的仿射变换原理和实现

     仿射变换能够保持图像的“平直性”,包括旋转,缩放,平移,错切操作。一般而言,仿射变换矩阵为2*3的矩阵,第三列的元素起着平移的作用,前面两列的数字对角线上是缩放,其余为旋转或者错切的作用。透视变换原理及实现请看我下篇博客。

    设仿射变换矩阵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时用最小二乘法求解未知参数。并且这三组点不共线。

数学展开式如下图:

图像的仿射变换原理和实现_第1张图片

下面根据上面公式给出实现代码,图像使用最近邻插值。

%% 读取原图像
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('插值后图像')


图像的仿射变换原理和实现_第2张图片

图像的仿射变换原理和实现_第3张图片

图像的仿射变换原理和实现_第4张图片

再看一个对点集的简单测试,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('仿射后点集')
图像的仿射变换原理和实现_第5张图片
reference:
https://ww2.mathworks.cn/help/images/ref/fitgeotrans.html?s_tid=srchtitle

你可能感兴趣的:(algorithm)