图像透视变换原理及实现【转发】

转自https://blog.csdn.net/cuixing001/article/details/80261189

上篇博客讲解了图像的仿射变换原理及实现,这篇博客讲讲透视变换的原理和实现,透视变换也叫投影变换,仿射变换是透视变换的特例。主要是透视变换能保持“直线性”,即原图像里面的直线,经透视变换后仍为直线。下面给出数学推导:

透视变换矩阵变换公式为:


其中透视变换矩阵:

               

要移动的点,即源目标点为:

                          

另外定点,即移动到的目标点为:

                       

这是一个从二维空间变换到三维空间的转换,因为图像在二维平面,故除以Z,  (X';Y';Z')表示图像上的点:


,展开上面公式,得到一个点的情况:

                                    

4个点可以得到8个方程,即可解出A。

                            

下面代码是上面公式的具体实现,getPerspective()是根据4组点对获取的透视变换矩阵。

function perspective_mat = getPerspective(moving_points,fixed_points)
% GETPERSPECTIVE 根据点获取透视变换矩阵
% 输入:
%     moving_pointsn*2点集坐标(x,y)
%     fixed_pointsn*2点集坐标(x,y),点顺序要对应moving_points
% 输出:
%     perspective_mat:3*3透视变换矩阵
% 
%  perspective_mat矩阵形式为[a11,a12,a13; a21,a22,a23; a31,a32,1];
%   满足fixed_points = perspective_mat*moving_points
% author: cuixing158@foxmail.com
%

assert(size(moving_points,1) == size(fixed_points,1)&& …
size(moving_points,1)>=4);

nums = size(moving_points,1);
coefficient_mat = zeros(2*nums,8);
b = zeros(2*nums,1);
for i = 1:nums
currentPoint = moving_points(i,:);
currentFixedPoint = fixed_points(i,:);
coefficient_mat(2*i-1? = [currentPoint(1),currentPoint(2),1,…
0,0,0,…
-currentPoint(1)*currentFixedPoint(1),-currentFixedPoint(1)*currentPoint(2)];
b(2*i-1) = currentFixedPoint(1);

coefficient_mat(<span class="hljs-number">2</span>*i,:) = [<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,...
    currentPoint(<span class="hljs-number">1</span>),currentPoint(<span class="hljs-number">2</span>),<span class="hljs-number">1</span>,...
    -currentPoint(<span class="hljs-number">1</span>)*currentFixedPoint(<span class="hljs-number">2</span>),-currentPoint(<span class="hljs-number">2</span>)*currentFixedPoint(<span class="hljs-number">2</span>)];
b(<span class="hljs-number">2</span>*i) = currentFixedPoint(<span class="hljs-number">2</span>);

end
perspective_mat = coefficient_mat\b; % 大于4个点时候为最小二乘法计算
perspective_mat = reshape([perspective_mat;1],3,3)’;

上面函数是通过4组点(大于等于)获取透视变换矩阵。下面给出测试代码,分别用手写的和系统的函数,对比时间加以说明。


%% prepare
img = rgb2gray(imread(‘book.jpg’));
width = size(img,2);
height = size(img,1);
figure;imshow(img)
% moving_points = [0,0;
% 100,50;
% 0,50;
% 50,100];
moving_points = ginput(4);
hold on ; plot(moving_points(:,1),moving_points(:,2),‘ro’);
fixed_points = [0,0;
100,0;
0,200;
100,200];

%% method 1,use matlab function
tfom = fitgeotrans(moving_points,fixed_points,‘projective’);

X = moving_points(:,1);
Y = moving_points(:,2);
[x,y] = transformPointsForward(tfom,X(?,Y(?);
figure;plot(x,y,‘ro’);title(‘验证坐标点对齐’)
grid on
tic;
dst_img = imwarp(img,tfom);
t_sys = toc;
figure;imshow(dst_img);title([‘图像仿射变换后(系统函数),耗时(s):’,num2str(t_sys)])

%% method 2, get perspective matrix
perspective_mat = getPerspective(moving_points,fixed_points);
A = perspective_mat;
X = [1;width;1;width]; % 原图片的四个角点x坐标
Y = [1;1;height;height]; % 原图片的四个角点y坐标
moving_points_mat = [X(?’;Y(?’;ones(1,size(X(?,1))];
dst_points = A*moving_points_mat;
for i = 1:size(dst_points,2)
dst_points(1:2,i) = dst_points(1:2,i)/dst_points(3,i);
end
figure;plot(dst_points(1?,dst_points(2?,‘bo’);title(‘原图像仿射变换后的坐标范围’)
grid on;

%% 仿射变换后图像逐像素进行插值赋值
min_x = min(dst_points(1?);
max_x = max(dst_points(1?);
min_y = min(dst_points(2?);
max_y = max(dst_points(2?);
W = round(max_x - min_x);
H = round(max_y -min_y);
wrapImg = zeros(H,W);
tic;
for i = 1:H
for j = 1:W
x = min_x+j; % 使得x,y的范围在原坐标范围内
y = min_y+i;
moving_point = A[x;y;1];
temp_point = [moving_point(1);moving_point(2)]./moving_point(3);
if temp_point(1)>=1&&temp_point(1)<width&& …
temp_point(2)>=1&&temp_point(2)<height
wrapImg(i,j) = img(round(temp_point(2)),round(temp_point(1)));
end
end
end
t_manual = toc;
figure;
imshow(uint8(wrapImg));title([‘图像仿射变换后(手写函数),耗时(s):’,num2str(t_manual)])


红色圆圈为鼠标点选的点,顺序为书籍左上点、右上点、左下点、右下点。图中对比可以看出,效果是一样的,不过系统的函数效率高,耗时较少。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值