1. 写在前面
在前面的博客中,介绍了相移互补格雷码算法的原理与代码实践。在这篇博客中,博主将介绍采用同心双圆环靶标下的相机标定与代码实践,我们不讲解传统的棋盘格、圆点靶标(都烂大街了!),我们要玩就玩酷的:同心双圆环靶标。它能有效避免棋盘格和圆点靶标的原理误差。完成本篇博客的学习内容后,你将收获采用同心双圆环靶标下的相机标定算法与代码实践经验。
本系列博客的完整项目代码皆位于博主的Github项目SLMaster👈中:
https://github.com/Practice3DVision/SLMaster
动动你的小指头给个Star⭐并follow博主吧!你的支持是博主不懈的动力!
关注公众号,每天推送不迷路!更多技术博客在公众号与你分享!
2. 相机标定
相机标定的详细原理博主不再赘述,可参考博主文章从0到1搭建一套属于你自己的高精度实时结构光3D相机(1):硬件搭建。
我们先大致说一下相机标定的一般过程,它可以用图1来简单描述:
图1. 相机标定过程
在图1中,内参估计已经被张氏标定法霸榜了数十年,基本上没啥新东西了(不过有人用深度学习做这玩意儿还是有点噱头的),所以我们暂时忽略这个环节,用张氏标定法就完事了(对应OpenCV
中的CalibrateCamera
方法)。
最终我们把注意力放在选定靶标与查找靶标特征点上。目前普遍采用的是棋盘格靶标与圆点靶标,然而,这两种靶标都是存在各自原理误差的,让我们来分析一下吧!
1)棋盘格靶标
棋盘格靶标是由黑白格相间而成的,它的特征点被定义为黑格与白格相交的顶点,顶点与顶点之间的距离是确定的。
当棋盘格在相机视图中不以 z 轴旋转时(线条是水平或垂直的),特征点提取精度较高,所取得的标定精度也比较高。
然而,当棋盘格格在相机视图中以z轴旋转时,由于线条是倾斜的,受相机插值成像算法影响,线条成像模糊,导致特征点提取精度下降,所取得的标定精度也对应的下降。可以通过图2描述棋盘格原理误差的表现:
图2. 棋盘格原理误差
2)圆点靶标
圆点靶标是由多个圆以阵列的形式组成的,它的特征点被定义为圆的圆心,圆心与圆心的距离被确定。
上述棋盘格因为**透视变换(旋转等)**而导致线条模糊,继而导致特征点提取精度降低。圆点靶标则完全避免了这一问题,因为圆的透视变换是椭圆(可以把自己的眼睛想象成相机,从不同角度观察圆),且在一定的模糊程度下可以忽略由模糊而导致的曲线方程拟合误差 [1][1]。
尽管取得了较好的效果,然而,圆点靶标仍然存在自身的原理误差。如图3所示,空间圆被投影到相机成像平面后形成椭圆,通过曲线方程拟合所得到的椭圆中心点 O 2 O_2 O2与原空间圆圆心 O 0 O_0 O0投影到相机成像平面的真实投影点 O 1 O_1 O1存在一定的距离误差,将这种误差称为圆的投影畸变误差。
图3. 圆点靶标的原理误差
当然也有迭代圆心投影畸变校正方法用于校正这一原理误差。这个博主不在这继续展开,感兴趣的话在下面评论或私聊扣1,人数够多的话,以后再出一篇专门的迭代圆心投影畸变校正方法博客。
3. 圆环靶标下的圆心提取算法
既然棋盘格靶标与圆点靶标皆存在原理误差,那么必然也有不断的新方法涌现,那就是我们的同心双圆环靶标盛大登场了。先给大家把参考文献给出,这篇论文个人觉得算法最为精简实用且写的非常简洁明了:The Common Self-polar Triangle of Concentric Circles and Its Application to
Camera Calibration [2]。
让我们开始吧!博主将以论文中的关键点进行讲解,随后在实验小节中以代码进行实践!
1)二次曲线方程
二次曲线是平面上点的集合,且任意点皆满足下式:
x 1 2 + x 2 2 + x 3 2 = 0 , x 4 = 0 x_1^2+x_2^2+x_3^2=0, x_4 = 0 x12+x22+x32=0,x4=0
我们所熟知的圆、椭圆都是二次曲线。
2)共同自极三角形性质
一点 x x x与二次曲线 C C C定义了一条直线 p = C x p=Cx p=Cx。将这条直线称作点 x x x相对于曲线 C C C的极线,点 x x x称作极线 p p p相对于曲线 C C C的极点。如果二次曲线的极点构成了三角形的顶点且极点的对边为其对应的极线,则将该三角形称为自极三角形,如图4(a)中所示。如果一个自极三角形为两个二次曲线所共有,则将其称为共同自极三角形,如图4(b)所示。
图4. 自极三角形与公共自极三角形
对于极点与极线之间的关系,已经有如下定理被证明:
1) 点
x
x
x相对于圆锥曲线
C
C
C的极线
p
=
C
x
p=Cx
p=Cx与圆锥曲线相交于两点。与
C
C
C相切的两条直线相交于点
x
x
x。
2)如果点
x
x
x在点
y
y
y的极线上,那么点
y
y
y在点
x
x
x的极线上。
根据这两个定理可以得到两个同心圆的公共自极三角形的两个性质:
1) 两个同心圆的所有公共自极三角形都有一个共同的顶点,这个顶点的对边在同一条线上,这条线就是圆的圆心和支撑平面的无穷远处的直线。
2) 两个同心圆的自极三角形都是直角三角形。
如图5所示:

图5. C1和C2是两个同心圆,圆的圆心为o,l是支撑平面无穷远处的直线,▲zoy是一个自极三角形
重点重点来了!!!
由性质1得知,公共自极三角形的公共顶点就是圆的圆心且其极线为无穷远处的直线,那我们就可以根据这个性质去恢复圆心与极线。
假设两个同心圆的圆心的坐标为 [ x 0 y 0 1 ] T \left [ x_0 y_0 1 \right ]^T [x0y01]T,半径分别为 r 1 r_1 r1和 r 2 r_2 r2,那么这两个圆能够用矩阵方程 C 1 C_1 C1和 C 2 C_2 C2来表示:
C 1 = [ 1 0 − x 0 0 1 − y 0 − x 0 − y 0 x 0 2 + y 0 2 − r 1 2 ] C_1=\begin{bmatrix}1 & 0 & -x_0\\0 & 1 & -y_0\\-x_0 & -y_0 &x_0^2+y_0^2-r_1^2 \end{bmatrix} C1= 10−x001−y0−x0−y0x02+y02−r12
C 2 = [ 1 0 − x 0 0 1 − y 0 − x 0 − y 0 x 0 2 + y 0 2 − r 2 2 ] C_2=\begin{bmatrix}1 & 0 & -x_0\\0 & 1 & -y_0\\-x_0 & -y_0 &x_0^2+y_0^2-r_2^2 \end{bmatrix} C2= 10−x001−y0−x0−y0x02+y02−r22
从性质1可知,
C
1
C_1
C1和
C
2
C_2
C2有无限个共同的自极三角形,这表明它们有无限个共同的极点-极线对。假设点
x
x
x和直线
p
p
p是二次曲线
C
1
C_1
C1和
C
2
C_2
C2的公共极点与极线,则有:
p
=
C
1
x
p
=
λ
C
2
x
p = C_1x \\ p = \lambda C_2x
p=C1xp=λC2x
式中,
λ
\lambda
λ为标量参数,将上述两式相减得
(
C
1
−
λ
C
2
)
x
=
0
(C_1-\lambda C_2)x = 0
(C1−λC2)x=0。在等式两边同时乘以
C
2
C_2
C2得逆,则有:
(
C
2
−
1
C
1
−
λ
I
)
x
=
0
(C_2^{-1}C_1-\lambda I)x = 0
(C2−1C1−λI)x=0
从上式可以发现,
C
1
C_1
C1和
C
2
C_2
C2得公共极点是
C
2
−
1
C
1
C_2^{-1}C_1
C2−1C1的特征向量!!!进一步通过求解特征向量
V
V
V和特征值
D
D
D得到
V
=
[
1
0
x
0
0
1
y
0
0
0
1
]
V=\begin{bmatrix}1 & 0 & x_0\\0 & 1 & y_0\\0 & 0 &1 \end{bmatrix}
V=
100010x0y01
D = [ 1 0 0 0 1 0 0 0 r 1 2 / r 2 2 ] D=\begin{bmatrix}1 & 0 & 0\\0 & 1 & 0\\0 & 0 &r_1^2/r_2^2 \end{bmatrix} D= 10001000r12/r22
仔细观察特征值 D D D发现,其中的两个特征值相同且为 1 1 1,另外一个特征值则是半径平方之比。而它们的特征向量分别为 [ 1 0 0 ] T \left [ 1 \quad 0 \quad 0 \right ] ^T [100]T, [ 0 1 0 ] T \left [ 0 \quad 1 \quad 0 \right ] ^T [010]T, [ x 0 y 0 1 ] T \left [ x_0 \quad y_0 \quad 1 \right ] ^T [x0y01]T,前两个正好是位于无穷远处的直线,而最后一个则是我们所需要的圆心!这与上面提到的性质完全吻合!
那么,如果我们想要得到两个同心圆的圆心坐标,就只要得到 C 2 − 1 C 1 C_2^{-1}C_1 C2−1C1,然后通过特征值和特征向量求解即可!
4. 采用同心双圆环靶标的相机标定算法
既然两个同心圆(也就是一个圆环)已经能够避免原理误差下提取到圆心了,还要双圆环干啥?
我们来仔细分析分析双圆环靶标的精度受什么影响。没有原理误差,并且只要求解 C 2 − 1 C 1 C_2^{-1}C_1 C2−1C1的特征值和特征向量即可。那最终的真相只有一个!(名侦探柯南上身),就是曲线方程(椭圆方程)拟合精度。
这个因素有什么方法解决呢?提高标定板加工精度、打光(背光板等)、相机调节等等。当然这些只是实战经验。
如果我们采用两个甚至多个圆环呢?
我们来分析一下,如果我们采用 N N N个圆环,则有 2 N 2N 2N个圆,那么我们共有 C 2 N 2 C_{2N}^2 C2N2个可供选择的组合圆环。以博主采用的同心双圆环为例,则有 C 4 2 = 6 C_4^2=6 C42=6种可供选择的组合圆环!假设某个圆的拟合方程精度不行,则仍然有 C 3 2 = 3 C_3^2=3 C32=3种可供选择的组合圆环!这可比之前使用的单个圆环鲁棒性提升高多了!
博主在这里总结一下采用双圆环靶标下的特征提取算法:
- 相机拍摄双圆环靶标
- 提取出所有的圆并拟合椭圆方程 C C C
- 对于同心的圆依次尝试组合并求解 C 2 − 1 C 1 C_2^{-1}C_1 C2−1C1特征值和特征向量
- 根据特征值距离 r 1 2 / r 2 2 r_1^2 / r_2^2 r12/r22的 L 2 L2 L2距离选择距离最小的组合所计算的圆心
5. 代码实践与实验
由于标定算法根据靶标类型和特征提取算法,万花齐放,我们还是采用简单工厂模式,先创建一个虚基类Calibrator
,然后让棋盘格、圆点、同心双圆环靶标标定算法都继承Calibrator
并实现虚函数。
在这里,博主将对关键代码进行说明,完整代码见博主Github项目SLMaster👈中的concentricRingCalibrator.h
和concentricRingCalibrator.cpp
,请不要吝惜你的⭐,动动小手指点击右上角的Star
!
我们的双圆环长这样:
博主在这篇文章中测试一下热度如何。就不在除公众号外的平台放代码实践与实验部分了。
代码实践与实验部分放在公众号中,详情关注公众号,博主测试一下博客热度。
公众号:实战3D视觉
参考文献
[1] 安晶晶,高楠,陈超等.圆环标识的离心偏差校正方法与评价[J].激光与光电子学进展,2017,54(04):171-179.
[2] Huang, Haifei & Zhang, Hui & Cheung, Yiu-ming. (2015). The common self-polar triangle of concentric circles and its application to camera calibration. 4065-4072. 10.1109/CVPR.2015.7299033.
本系列文章将持续更新,如果有等不及想要获得代码的小伙伴,可访问博主Github中的SLMaster项目,动动你的小手指,follow and star⭐!你们的关注是博主持续的动力!