对整个图像进行透视变换

对整个图像进行透视变换

常见的教程都是对所选的四个点内部的区域进行透视变换,但是其他区域都被裁剪掉了。如何利用所选的局部区域对整个图像进行透视变换?

透视变换

透视变换的算法:OpenCV文档

dst ( x , y ) = src ( M 11 x + M 12 y + M 13 M 31 x + M 32 y + M 33 , M 21 x + M 22 y + M 23 M 31 x + M 32 y + M 33 ) \texttt{dst} (x,y) = \texttt{src} \left ( \frac{M_{11} x + M_{12} y + M_{13}}{M_{31} x + M_{32} y + M_{33}} , \frac{M_{21} x + M_{22} y + M_{23}}{M_{31} x + M_{32} y + M_{33}} \right ) dst(x,y)=src(M31x+M32y+M33M11x+M12y+M13,M31x+M32y+M33M21x+M22y+M23)
推导过程:
通过getPerspectiveTransform()函数得到一个线性变换的矩阵 M M M,随后的透视变换过程如下
[ x ′ y ′ z ′ ] = [ M 11 M 12 M 13 M 21 M 22 M 23 M 31 M 32 1 ] [ x y 1 ] \begin{bmatrix} x' \\ y' \\ z' \end{bmatrix} = \begin{bmatrix} M_{11} & M_{12} & M_{13} \\ M_{21} & M_{22} & M_{23} \\ M_{31} & M_{32} & 1 \\ \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} xyz=M11M21M31M12M22M32M13M231xy1
由于原始图像中没有 z z z轴上的维度,所以设置为1,但经过变换后的图像上的 z ′ z' z不为1,所以将其归一化,得到
[ x ′ ′ y ′ ′ 1 ] = 1 z ′ [ x ′ y ′ z ′ ] \begin{bmatrix} x'' \\ y'' \\ 1 \end{bmatrix} = \frac{1}{z'} \begin{bmatrix} x' \\ y' \\ z' \end{bmatrix} xy1=z1xyz
也就得到了OpenCV的公式

解决方案

解决方案参考:Stack Overflow的方案
被裁剪的原因是因为经过变换的坐标变换到了画布范围之外,因此需要确定新画布的大小,并将变换后的图像平移到画布内。
透视变换的矩阵记作M,格式如下:
[ M 11 M 12 M 13 M 21 M 22 M 23 M 31 M 32 1 ] \begin{bmatrix} M_{11} & M_{12} & M_{13} \\ M_{21} & M_{22} & M_{23} \\ M_{31} & M_{32} & 1 \\ \end{bmatrix} M11M21M31M12M22M32M13M231
设原始图片的四角分别为

(0,0) ________ (0, w)
     |        |
     |________|
(h,0)          (h,w)

只要对四角进行变换,就可以确定新画布的边界。
首先坐标点写作矩阵的形式,三行分别代表 x , y , z x,y,z x,y,z轴坐标
P = [ 0 w w 0 0 0 h h 1 1 1 1 ] P = \begin{bmatrix} 0 & w & w & 0 \\ 0 & 0 & h & h \\ 1 & 1 & 1 & 1 \end{bmatrix} P=001w01wh10h1
类似地, P ′ = M P P'=MP P=MP,并将 P ′ P' P的各列除以各列的最后一行的那个元素进行归一化,得到 P ′ ′ P'' P
P ′ ′ = [ p 11 p 12 p 13 p 14 p 21 p 22 p 23 p 24 1 1 1 1 ] P'' = \begin{bmatrix} p_{11} & p_{12} & p_{13} & p_{14} \\ p_{21} & p_{22} & p_{23} & p_{24} \\ 1 & 1 & 1 & 1 \end{bmatrix} P=p11p211p12p221p13p231p14p241
获取 x x x上的(第一行)最大最小值 x m i n , x m a x x_{min}, x_{max} xmin,xmax
获取 y y y上的(第一行)最大最小值 y m i n , y m a x y_{min}, y_{max} ymin,ymax
Δ x = x m a x − x m i n , Δ y = y m a x − y m i n \Delta x= x_{max}-x_{min},\Delta y= y_{max}-y_{min} Δx=xmaxxmin,Δy=ymaxymin即为新画布的宽和高。


以上都是基于Stack Overflow上的回答所写,但正如其中的评论所述,第四步存在错误,但评论也表述不太清楚,在此详细分析一下

为了进一步将变换后的图像平移到画布内,已知了透视变换是通过 M M M乘以坐标进行的,可以对 M M M进行更改来加入平移操作。
创建单位矩阵,并在第三列放入矩阵 P ′ ′ P'' P对应行的最小值的负值,称为矩阵 T T T
T = [ 1 0 − x m i n 0 1 − y m i n 0 0 1 ] T= \begin{bmatrix} 1 & 0 & -x_{min}\\ 0 & 1 & -y_{min} \\ 0 & 0 & 1 \end{bmatrix} T=100010xminymin1
则新的变换矩阵 M ′ = T M M'=TM M=TM。可以简单验证一下,将 M ′ M' M与坐标相乘并展开,可以发现刚好得到
[ x ′ ′ ′ y ′ ′ ′ 1 ] = [ x ′ ′ − x m i n y ′ ′ − y m i n 1 ] \begin{bmatrix} x''' \\ y''' \\ 1 \end{bmatrix}= \begin{bmatrix} x''-x_{min} \\ y''-y_{min} \\ 1 \end{bmatrix} xy1=xxminyymin1
因此最后的透视变换的参数为:
warpPerspective(src=src, M=M', dsize=(delta_x, delta_y))

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值