如何利用鱼眼镜头测距
校准
每个图像都提供了一个专用的校准文件,包括内在和外在参数以及描述性名称。
名称是“FV”、“MVR”、“MVL”或“RV”之一,是“Front View”、“Mirror View Right”、“Mirror View Left”、“Rear View”的缩写。
外参 Extrinsic
遵循 ISO 8855 公约的车辆坐标系固定在后轴中点下方的地面上。 X 轴指向行驶方向,Y 轴指向车辆左侧,Z 轴指向地面上方。 相机传感器的坐标系基于 OpenCV。 X 轴沿传感器水平轴指向右侧,Y 轴沿传感器垂直轴指向下方,Z 轴沿光轴指向观察方向,以保持右手系。 平移的值以米为单位,旋转以四元数的形式给出。它们描述了从相机坐标系到车辆坐标系的坐标变换。可以使用例如获得旋转矩阵scipy.spatial.transform.Rotation.from_quat 。
内参
内在校准在校准模型中给出,该模型使用 4 阶多项式描述径向失真
r
h
o
(
t
h
e
t
a
)
=
k
1
?
t
h
e
t
a
+
k
2
?
t
h
e
t
a
?
?
2
+
k
3
?
t
h
e
t
a
?
?
3
+
k
4
?
t
h
e
t
a
?
?
4
,
rho(theta) = k1 * theta + k2 * theta ** 2 + k3 * theta ** 3 + k4 * theta ** 4,
rho(theta)=k1?theta+k2?theta??2+k3?theta??3+k4?theta??4,
其中theta是相对于光轴的入射角,rho是图像中心和投影点之间的距离。系数 k1、k2、k3 和 k4 在校准文件中给出。
主点的图像width和height以及偏移量(cx,cy)以像素为单位。
为了完整起见,以相机坐标给出的 3D 点 (X, Y, Z) 到图像坐标 (u, v) 的投影如下所示:
chi = sqrt( X ** 2 + Y ** 2)
theta = arctan2( chi, Z ) = pi / 2 - arctan2( Z, chi )
rho = rho(θ)
u' = rho * X / chi if chi != 0 else 0
v' = rho * Y / chi if chi != 0 else 0
u = u' + cx + width/2 - 0.5
v = v' * aspect_ratio + cy + height/2 - 0.5
最后两行显示了图像坐标系的最终转换,假设图像坐标系的原点位于左上角,左上角像素位于 (0, 0)。
20200302 我好像写错了
下图片中的计算,rho是图像中心点到投影点的距离。采用相似三角形计算 u‘=rho*X/chi。不是采用等距投影。我不清楚为什么我早上认为是等距投影公式,我可能以为rho代表距离,K1,K2,K3,K4 和X/chi 联合计算的可能就是入射角a,这样好像也能够说的通顺。
20200303 我昨天好像写错了
是采用等距投影模型,以入射角为一个自变量。
我看了两套相机模组的K1,K2,K3,K4 的系数不一样。我仔细分析后: 1、四个系数是畸变系数,这个系数可以把很多参数藏在里面。如果是物理坐标XYZ直接到sensor的坐标,则系数里面可能藏在一个焦距值f,
参数1 :
r
h
o
(
t
h
e
t
a
)
=
k
1
?
t
h
e
t
a
+
k
2
?
t
h
e
t
a
?
?
2
+
k
3
?
t
h
e
t
a
?
?
3
+
k
4
?
t
h
e
t
a
?
?
4
,
rho(theta) = k1 * theta + k2 * theta ** 2 + k3 * theta ** 3 + k4 * theta ** 4,
rho(theta)=k1?theta+k2?theta??2+k3?theta??3+k4?theta??4,
"intrinsic": {
"aspect_ratio": 1.0,
"cx_offset": 3.942,
"cy_offset": -3.093,
"height": 966.0,
"k1": 339.749,
"k2": -31.988,
"k3": 48.275,
"k4": -7.201,
"model": "radial_poly",
"poly_order": 4,
"width": 1280.0
},
另外一个模组提供的系数是经过3×3投影矩阵后的xyz与sensor的坐标的调节系数,这些值就比较小了都是0.0几的值。而且给出的计算方程是
参数2 :
r
h
o
(
t
h
e
t
a
)
=
t
h
e
t
a
+
k
1
?
t
h
e
t
a
?
?
2
+
k
2
?
t
h
e
t
a
?
?
4
+
k
3
?
t
h
e
t
a
?
?
6
+
k
4
?
t
h
e
t
a
?
?
8
rho(theta) = theta+k1 * theta**2 + k2 * theta ** 4 + k3 * theta ** 6 + k4 * theta ** 8
rho(theta)=theta+k1?theta??2+k2?theta??4+k3?theta??6+k4?theta??8
<intrinsic_matrix>
3.1064417199616088e+02 0. 6.4211426421732665e+02 0.
3.0902232061164585e+02 3.5986474570742291e+02 0. 0. 1.</intrinsic_matrix>
<distortion_coeffs>
8.3833457351696380e-02 9.0871594056932698e-03 -8.6395467343150674e-04
-1.2068752796059838e-03 0.</distortion_coeffs>
</opencv_storage>
我感觉,把参数1 除以 焦距值(好像是K1值代表焦距),就和参数2 比较相似了 方案1:修改为
r
h
o
(
t
h
e
t
a
)
=
t
h
e
t
a
+
k
2
/
k
1
?
t
h
e
t
a
?
?
2
+
k
3
/
k
1
?
t
h
e
t
a
?
?
3
+
k
4
/
k
1
?
t
h
e
t
a
?
?
4
,
rho(theta) = theta + k2/k1 * theta ** 2 + k3/k1 * theta ** 3 + k4/k1 * theta ** 4,
rho(theta)=theta+k2/k1?theta??2+k3/k1?theta??3+k4/k1?theta??4,
反正,K1,K2,K3,K4 与具体计算方法有重大关系。这个可能还是得和相机模组厂商拿到方案吧。
我下面关于等距投影的估计都是错的:
投影本身在 projection.py 中实现,可以在 https://github.com/valeoai/WoodScape/tree/master/scripts/calibration 找到。
输入与输出
|