0%

相机模型求解

1. 1 问题描述

在已经有了相机模型和已知圆的3个特征点的世界坐标及其像素坐标的情况下,我们可以用数值求解的方式求解出相机的位姿。

假设世界坐标系的圆点为圆心

2. 2 约束条件

已知相机模型
Zc[u v 1]=[fμx0cx 0fμycy 001][1000 0100 0010][RT 01][Xw Yw Zw 1]
其中
S=[fμx0cx 0fμycy 001]
是相机的内参矩阵,是一个固定的矩阵,因此可以放到等式左边,化简方程
ZcS1[u v 1]=[1000 0100 0010][RT 01][Xw Yw Zw 1]
其中
S1=[μf0Cxμf\0μfCyμf\001]
(4)中的RT矩阵用四元数的表达方式可以写成
[2y22z2+12wz+2xy2wy+2xzTx(2y22z2+1)Ty(2wz+2xy)Tz(2wy+2xz)\2wz+2xy2x22z2+12wx+2yzTx(2wz+2xy)Ty(2x22z2+1)Tz(2wx+2yz)\-2wy+2xz2wx+2yz2x22y2+1Tx(2wy+2xz)Ty(2wx+2yz)Tz(2x22y2+1)\0001]
四元数的各个数值约束为
w2+x2+y2+z2=1

2.1. 2.1 圆心特征点

考虑世界坐标系圆心坐标 P(0,0,0),像素坐标p0

对应缩放
Zc=Tx(2wy+2xz)Ty(2wx+2yz)Tz(2x22y2+1)
像素坐标
ZcS1p0=[Tx(2y22z2+1)Ty(2wz+2xy)Tz(2wy+2xz) Tx(2wz+2xy)Ty(2x22z2+1)Tz(2wx+2yz)]

2.2. 2.2 X方向直径端点

考虑世界坐标系X方向直径端点 P(L,0,0),像素坐标px

对应缩放
Zc=L(2wy+2xz)Tx(2wy+2xz)Ty(2wx+2yz)Tz(2x22y2+1)
像素坐标
ZcS1px=[L(2y22z2+1)Tx(2y22z2+1)Ty(2wz+2xy)Tz(2wy+2xz) L(2wz+2xy)Tx(2wz+2xy)Ty(2x22z2+1)Tz(2wx+2yz)

###2.3 Y方向直径端点

考虑世界坐标系X方向直径端点P(0,L,0),像素坐标py

对应缩放
Zc=L(2wx+2yz)Tx(2wy+2xz)Ty(2wx+2yz)Tz(2x22y2+1)
像素坐标
ZcS1py=[L(2wz+2xy)Tx(2y22z2+1)Ty(2wz+2xy)Tz(2wy+2xz) L(2x22z2+1)Tx(2wz+2xy)Ty(2x22z2+1)Tz(2wx+2yz)]

2.3. 2.4 总结

综上,(6)(8)(10)(12)中共有7个方程

已知的是L,f,μ,p0,px,py,Cx,Cy

未知数Tx,Ty,Tz,w,x,y,z

共有7个方程,7个未知数,因此可以求解

3. 3 代码实现

主要是用了scipy中的fsolve函数进行数值求解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def func(xx):
T_x, T_y, T_z, x, y, z, w = xx
p0x = -T_x*(-2*y**2 - 2*z**2 + 1) - T_y * \
(-2*w*z + 2*x*y) - T_z*(2*w*y + 2*x*z)
p0y = -T_x*(2*w*z + 2*x*y) - T_y*(-2*x**2 -
2*z**2 + 1) - T_z*(-2*w*x + 2*y*z)
Z_p0 = -T_x*(-2*w*y + 2*x*z) - T_y*(2*w*x + 2*y*z) - \
T_z*(-2*x**2 - 2*y**2 + 1)
pxx = -T_x*(-2*y**2 - 2*z**2 + 1) - T_y*(-2*w*z + 2*x*y) - \
T_z*(2*w*y + 2*x*z) - 2*y**2 - 2*z**2 + 1
pxy = -T_x*(2*w*z + 2*x*y) - T_y*(-2*x**2 - 2*z**2 + 1) - \
T_z*(-2*w*x + 2*y*z) + 2*w*z + 2*x*y
Z_px = -T_x*(-2*w*y + 2*x*z) - T_y*(2*w*x + 2*y*z) - \
T_z*(-2*x**2 - 2*y**2 + 1) - 2*w*y + 2*x*z
pyx = -T_x*(-2*y**2 - 2*z**2 + 1) - T_y*(-2*w*z + 2*x*y) - \
T_z*(2*w*y + 2*x*z) - 2*w*z + 2*x*y
pyy = -T_x*(2*w*z + 2*x*y) - T_y*(-2*x**2 - 2*z**2 + 1) - \
T_z*(-2*w*x + 2*y*z) - 2*x**2 - 2*z**2 + 1
Z_py = -T_x*(-2*w*y + 2*x*z) - T_y*(2*w*x + 2*y*z) - \
T_z*(-2*x**2 - 2*y**2 + 1) + 2*w*x + 2*y*z
return [p0x/Z_p0-pixels[0, 0],
p0y/Z_p0-pixels[0, 1],
pxx/Z_px-pixels[1, 0],
pxy/Z_px-pixels[1, 1],
pyx/Z_py-pixels[2, 0],
pyy/Z_py-pixels[2, 1],
w**2+x**2+y**2+z**2-1]

from scipy.optimize import fsolve
guess = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
ans = fsolve(func, guess)

4. 4 实验结果

fsolve的参数包括一个函数和一个初始值,因为是数值求解,所以只能求出一个解,但实际上有多组解(其中只有一组解是真的)

每次计算在2ms左右(个人电脑)

这里设置多个初始值的(x,y),达到近似遍历的效果,在实际可能的范围内将答案求解

image-20210701112318068

可以看到,解中包含了真实答案,但也有许多其他答案,需要后续进行继续分析排除