在拍摄文件时,如果手机和待拍摄的文件不是正对时,拍摄的文件会产生扭曲。可以使用 ARKit 对拍摄的图形进行矫正,获取到垂直拍摄的效果。
下面是实现的思路和过程。
前提条件
在拍摄的过程中,默认待拍摄的图像在一个水平面或者垂直平面上(因为 ARKit 目前只能检测到水平面或者垂直平面)。
思路
- 通过 ARKit 获取到待拍摄的平面,推导出表达平面的方程式
- 根据相机内参,相机当前的位置,取拍摄图片上的左上、左下、右上、右下四个点,推算出这四个点所拍摄的三维世界中的线
- 计算步骤 2 中的四条线和步骤 1 中的平面的四个交点,相机所拍摄的图像即是这四个交点内的内容
- 根据投影变换,将拍摄图片的左上、左下、右上、右下四个点和步骤 3 中的四个交点进行对应变换,得出矫正后的图片
计算过程
获取待拍摄的平面的方程式
可以通过一个平面上的三个点(不在一条直线上),计算一个平面的方程表达式。
ARKit 可以提供的能力:
- 识别出世界空间中的水平、垂直的平面
- 射线检测:可以测试手机图像上的点和特征点的交点
平面的一般式为:Ax+By+Cz+D=0。
可以选取手机平面正中间相邻的、不再一条直线上的三个点,根据射线检测,看是否在同一个平面上。如果在同一个平面上,则获取到对应的三个点,来计算平面公式。
假设三个交点为 P1(x1,y1,z1),P2(x2,y2,z2),P3(x3,y3,z3),根据三点坐标分别求得 A、B、C、D的值,推到公式为:
A=(y3−y1)∗(z3−z1)−(z2−z1)∗(y3−y1)B=(x3−x1)∗(z2−z1)−(x2−x1)∗(z3−z1)C=(x2−x1)∗(y3−y1)−(x3−x1)∗(y2−y1)D=−(Ax1+By1+Cz1)
相机图片坐标和世界坐标之间的对应关系
通过相机内参获取平面上点和相机坐标的三维点
可以通过相机内参,推到出图像上的点和相机左边空间的点的对应关系。
假设:平面上的点的坐标为 P(xphoto,yphoto),相机空间的对应的点为:P(xcamera,ycamera,zcamera),相机内参为:⎣⎡fx000fy0oxoy1⎦⎤ ,则:
⎣⎡fx000fy0oxoy1⎦⎤⎣⎡xcameraycamerazcamera⎦⎤=⎣⎡xphoto′yphoto′zphoto′⎦⎤→⎣⎡xphoto′yphoto′zphoto′⎦⎤/zphoto′=⎣⎡xphotoyphoto1⎦⎤
所以 P(xphoto,yphoto) 和 P(xcamera,ycamera,zcamera) 的关系为:
xphoto=fxxcamera/zcamera+oxyphoto=fyycamera/zcamera+oy
计算世界坐标和相机坐标的对应关系
通过相机的位姿(transform),可以获取相机坐标和世界坐标之间的关系。
即:(P相机坐标,1)=T相加位姿−1(P世界坐标,w)
假设相机的坐标点为:P(xcamera,ycamera,zcamera),对应的世界的坐标为 P(xworld,yworld,zworld),相机的位姿(transform)为 T相机位姿,相机的位姿的逆矩阵为T−1,即⎣⎡t00′t01′t02′t03′t10′t11′t12′t13′t20′t21′t22′t23′t30′t31′t32′t33′⎦⎤
则:
⎣⎡xcameraycamerazcamera1⎦⎤=⎣⎡t00′t01′t02′t03′t10′t11′t12′t13′t20′t21′t22′t23′t30′t31′t32′t33′⎦⎤⎣⎡xworldyworldzworldw⎦⎤
综上条件,可以得出相机图片坐标P(xphoto,yphoto)和世界坐标P(xworld,yworld,zworld)之间的对应关系:
⎩⎨⎧⎣⎡xcameraycamerazcamera1⎦⎤=⎣⎡t00′t01′t02′t03′t10′t11′t12′t13′t20′t21′t22′t23′t30′t31′t32′t33′⎦⎤⎣⎡xworldyworldzworldw⎦⎤xphoto=fxxcamera/zcamera+oxyphoto=fyycamera/zcamera+oy
可以推导出:
{(fxt00′+fxt02′−xphotot02′)xworld+(fxt10′+oxt12′−xphotot12′)yworld+(t20′fx+oxt22′−xcameratxx)zworld+t30′fx+oxt32′−xphotot32′=0(fyt01′+oyt02′−yphotot02′)xworld+(fyt11′+oyt12′−yphotot12′)yworld+(fyt21′+oyt22′−yphotot22′)zworld+fyt31′+oyt32′−yphotot32′=0
计算 ARKit 拍摄图片上的四个点和平面的焦点
有了相机拍摄图片的坐标和世界坐标的关系,再加上平面方程式,则可以计算出,相机拍摄的图片坐标在指定平面上的交点。
相机拍摄的图片上的一点对应世界中的一条射线,即求:这条射线和平面的焦点。
假设平面为:Ax+By+Cz+D=0,则可以得出一个三元一次方程组:
⎩⎨⎧(fxt00′+fxt02′−xphotot02′)xworld+(fxt10′+oxt12′−xphotot12′)yworld+(t20′fx+oxt22′−xcameratxx)zworld+t30′fx+oxt32′−xphotot32′=0(fyt01′+oyt02′−yphotot02′)xworld+(fyt11′+oyt12′−yphotot12′)yworld+(fyt21′+oyt22′−yphotot22′)zworld+fyt31′+oyt32′−yphotot32′=0Axworld+Byworld+Czworld+D=0
当确定相机拍摄的图片上一个点之后,带入上面的方程组,就是确定平面上的一点P(xworld,yworld,zworld)的三个方程组,
⎩⎨⎧A1xworld+B1yworld+C1zworld+D1=0A2xworld+B2yworld+C2zworld+D2=0Axworld+Byworld+Czworld+D=0
根据克莱姆法则
,可以计算得出 P(xworld,yworld,zworld) 的值。
使用同样的过程,我们就可以获得相机照片上的4的点对应的世界坐标。
投影变换
获取到照片拍摄的图片上四个顶点的世界坐标之后,就可以应用投影变换
,对图片进行矫正。