介绍BBK软件中采用的简易内参标定, 用于计算相机焦距, 本文主要用于老版本HUD和轮眉软件.
新版本相机内参在公司出厂前就会标定好, 不需要现场标定, 并且标定方式也与本文不同
BBK使用的内参标定方法一
原理
小孔成像图自行脑补
其中, $D$为感光芯片到物体的距离, $f$为相机焦距, $L$为物体实际尺寸, $p$为物体在图像中的像素尺寸
由于无法准确测量像距所以近似认为,$D= D_{\text{物距}} + f(近似认为像距=焦距)$
推导出焦距计算公式为:
误差说明
- 首先公式中唯一需要测量的D即标靶到相机感光芯片的距离要求测量准确
- 其次由于近似认为物体成像在一倍焦距上, 所以$D-f$会根据焦距大小不同存在几毫米到到十几毫米的误差, 被测图像越远误差越小
示例: $D = 2400$, $p = 1983 0.00167$, $L = 280$
$f = 2400 1983 0.00167 / (280 + 1983 0.00167) = 2400 3.3116 / (280 + 3.3116) = 28.0533518571$
测量误差和像距误差均体现在D上, 假设误差为10mm, 会导致$f = 2410 3.3116 / (280 + 3.3116) = 28.17024$, 焦距误差为0.116888
焦距误差对测量值的影响如下:
体现在投影距离上:
单目:
测量值: $Distance = 1082 / (2495 0.00167 / 28.0533518571) = 7284.92471$
实际值: $Distance = 1082 / (2495 0.00167 / 28.17024) = 7315.25928$
焦距误差导致的投影距离误差约为: 30mm
双目:
测量值: $Distance = 28.0533518571 / 0.00167 65 / (1584 - 1169) = 28.0533518571 / 0.00167 65 / 150 = 7279.31$
实际值: $Distance = 28.17024 / 0.00167 65 / 150 = 7309.643$
焦距误差导致的*投影距离误差约为: 30mm
体现在角度上:
测量值: $Lda = atan(132 0.00167 / 28.0533518571) = 0.45°$
实际值: $Lda = atan(132 0.00167 / 28.17024) = 0.448°$
焦距误差导致的角度误差约为:0.002°
BBK软件实现
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 32 33
| Camera.IntrinsicsCalibriton(_calibrationAgorithm.DotLeftTop, _calibrationAgorithm.DotRightTop, _calibrationAgorithm.DotLeftBottom, _calibrationAgorithm.DotRightBottom, _calibrationAgorithm.DotHorLength, _calibrationAgorithm.DotVerLength, _calibrationAgorithm.DotDistance);
public void IntrinsicsCalibriton(PointF LeftTop, PointF RightTop, PointF LeftBottom, PointF RightBottom, double LengthHor, double LengthVer, double Distance) { double L1 = Math.Sqrt((RightTop.X - LeftTop.X) * (RightTop.X - LeftTop.X) + (RightTop.Y - LeftTop.Y) * (RightTop.Y - LeftTop.Y)); double L2 = Math.Sqrt((LeftBottom.X - LeftTop.X) * (LeftBottom.X - LeftTop.X) + (LeftBottom.Y - LeftTop.Y) * (LeftBottom.Y - LeftTop.Y)); double L3 = Math.Sqrt((RightBottom.X - LeftBottom.X) * (RightBottom.X - LeftBottom.X) + (RightBottom.Y - LeftBottom.Y) * (RightBottom.Y - LeftBottom.Y)); double L4 = Math.Sqrt((RightBottom.X - RightTop.X) * (RightBottom.X - RightTop.X) + (RightBottom.Y - RightTop.Y) * (RightBottom.Y - RightTop.Y));
double diffPixelX = (L1 + L3) / 2; double diffPixelY = (L2 + L4) / 2;
if ((diffPixelX == 0) || (diffPixelY == 0)) throw new ArgumentOutOfRangeException("boardParam.RightTop , boardParam.LeftTop , boardParam.RightBottom , boardParam.LeftBottom"); double fx = (Distance * diffPixelX * PixelSize) / (LengthHor + diffPixelX * PixelSize); double fy = (Distance * diffPixelY * PixelSize) / (LengthVer + diffPixelY * PixelSize); Intrinsics_f = fx / 2 + fy / 2; Intrinsics_Fx = (fx / PixelSize).Round(4); Intrinsics_Fy = (fy / PixelSize).Round(4); Intrinsics_Cx = PixelWidth / 2; Intrinsics_Cy = PixelHeight / 2; }
|