文章目录
- 相机的标定
- 标定步骤
- 标定结果
- 影响因素
- 参数分析
- 精度提升
- 一、拍摄棋盘格
- 二、提升标定精度
- 标定代码实现
相机的标定
双目相机的标定是确保它们能够准确聚焦和成像的关键步骤。以下是详细的标定步骤和可能的结果,同时考虑了不同光照条件和镜头光圈大小等因素对标定结果的影响。
标定步骤
-
准备标定板:
- 使用一个具有明显特征点的标定板,如棋盘格标定板。
- 确保标定板平整且特征点清晰可辨。
-
固定相机位置:
- 将双目相机固定在稳定的三脚架或支架上。
- 调整相机位置,确保标定板完全位于相机的视野内。
-
采集标定图像:
- 在不同的角度和距离下,移动标定板并拍摄多组图像(通常建议至少15组)。
- 确保图像中标定板的特征点清晰可见。
-
使用标定软件:
- 可以使用OpenCV、MATLAB等提供的相机标定工具。
- 导入拍摄的标定图像,并识别标定板上的特征点。
-
计算标定参数:
- 通过软件计算相机的内参(如焦距、主点坐标等)和外参(如旋转矩阵和平移向量)。
- 同时,软件还会给出畸变系数等参数。
-
立体校正和验证:
- 使用标定参数进行立体校正,确保左右相机的图像在同一水平线上对齐。
- 通过拍摄实际场景验证标定的准确性,观察立体匹配的效果。
标定结果
- 标定参数:包括相机的内参(焦距、主点等)、外参(旋转矩阵、平移向量)和畸变系数。
- 误差分析:标定软件通常会给出重投影误差等指标,用于评估标定的准确性。重投影误差越小,说明标定越准确。
影响因素
-
光照条件:
- 强光或弱光条件下,标定板的特征点可能不够清晰,影响标定的准确性。
- 建议在均匀且适度的光照条件下进行标定。
-
镜头光圈大小:
- 光圈大小影响景深和图像亮度。过大或过小的光圈都可能导致标定板上的特征点模糊。
- 选择适中的光圈大小,以获得清晰的标定图像。
综上所述,双目相机的标定是一个精确且细致的过程,需要考虑多种因素以确保标定的准确性。通过遵循上述步骤并注意影响因素,可以获得高质量的标定结果,从而实现双目相机的准确聚焦和成像。
角点的数量:如果标定板格子是12x9的,那么格点的数据则是11x8
像下面这幅图格点的数据就是11x8
参数分析
以下是标定的结果,标定代码放在文末。
Calibration Error: 0.26985438768011444
Intrinsic Matrix:
[[9.64900471e+04 0.00000000e+00 4.00956403e+02]
[0.00000000e+00 9.84639627e+04 5.17965206e+02]
[0.00000000e+00 0.00000000e+00 1.00000000e+00]]
Distortion Coefficients:
[-7.27106948e+00 4.02668787e-02 -2.75489644e-02 -1.58608135e-02
2.25903054e-04]
这些参数通常与计算机视觉中的相机标定(Camera Calibration)相关。相机标定是确定相机的内部参数(内参)和畸变系数的过程,以便更准确地从图像中获取信息。下面我会解释这些参数的含义:
Calibration Error:
Calibration Error: 0.26985438768011444
表示相机标定的误差。这个数值越小,说明标定越准确。误差是通过比较标定板上角点的实际图像坐标与通过标定参数计算得到的图像坐标之间的差异来计算的。Intrinsic Matrix:
这个矩阵描述了相机的内部几何和光学特性,通常包含焦距(fx, fy)、主点(cx, cy)等参数。矩阵的形式一般为:
[fx 0 cx] [ 0 fy cy] [ 0 0 1]
在你给出的数据中:
fx = 9.64900471e+04
和fy = 9.84639627e+04
是相机在x和y方向上的焦距(以像素为单位)。cx = 4.00956403e+02
和cy = 5.17965206e+02
是图像坐标系中相机的主点坐标。- 矩阵的第三行是标准形式,表示这是一个齐次坐标变换。
Distortion Coefficients:
- 这些系数用于纠正由于相机镜头畸变引起的图像变形。常见的畸变包括径向畸变和切向畸变。
- 给出的数据中,有五个畸变系数:
k1 = -7.27106948e+00
通常是径向畸变的主要系数。k2 = 4.02668787e-02
,k3 = -2.75489644e-02
可能是径向畸变的高阶系数。p1 = -1.58608135e-02
,p2 = 2.25903054e-04
通常是切向畸变的系数。通过这些参数,可以对相机拍摄的图像进行畸变校正,以及从图像坐标转换到真实世界坐标等。这在许多计算机视觉应用中,如三维重建、目标跟踪、机器人导航等,都是非常重要的。
在相机标定过程中,内参和外参是否会随着标定板的变化而变化,这个问题可以从两个方面来分析:
一、内参
- 内参是描述相机内部属性的参数,包括焦距、主点(光学中心)坐标、畸变系数等。
- 这些参数通常在相机标定时确定,并且对于特定相机型号是固定的,不随时间变化。
- 因此,内参不会随着标定板的变化而变化。无论标定板的形状、大小或位置如何改变,相机的内部属性如焦距、主点坐标等保持不变。
二、外参
- 外参是描述相机在世界坐标系中的位置和姿态的参数,包括旋转矩阵和平移向量。
- 这些参数与相机和标定板之间的相对位置关系密切相关。
- 当标定板的位置或方向发生变化时,相机的外参也会随之变化。例如,如果移动相机或更改拍摄角度,外参会随之调整以反映这些变化。
- 因此,外参会随着标定板的变化而变化。具体来说,当标定板与相机的相对位置或姿态发生改变时,需要重新进行标定以获取准确的外参。
三、畸变系数
-
畸变系数的定义:
- 畸变系数是描述相机镜头制造偏差等因素导致的成像失真系数,主要包括径向畸变系数和切向畸变系数。
- 这些畸变系数是相机本身的固有属性,与相机的制造和组装过程有关。
-
标定板的作用:
- 标定板在相机标定过程中主要用于提供已知的几何特征(如棋盘格的角点),以便通过图像处理算法来估计相机的内外参数和畸变系数。
- 标定板的变化可能包括其位置、方向或图案的变化。
-
畸变系数与标定板的关系:
- 虽然标定板用于估计畸变系数,但畸变系数本身并不会因为标定板的变化而变化。
- 畸变系数是相机镜头的固有特性,与标定板无关。标定板只是用于测量和估计这些系数的工具。
-
实验观察与结论:
- 在实际标定过程中,可能会观察到畸变系数的估计值随着标定板的不同设置(如不同位置、角度或图案)而有所差异。然而,这种差异主要是由于标定过程中的误差、图像噪声或算法的不稳定性引起的,并非畸变系数本身发生了变化。
- 因此,可以归纳出结论:畸变系数不会随着标定板的变化而变化。它们是相机的固有属性,只与相机的镜头质量和组装工艺有关。
综上所述,
内参是相机的固有属性,不会因标定板的变化而改变;而外参则与相机和标定板之间的相对位置关系密切相关,当这种关系发生变化时,外参也需要相应地进行调整。
畸变系数是相机的固有特性,不会因标定板的变化而改变。标定板只是用于测量和估计这些系数的工具,而估计值的差异主要来源于标定过程中的各种误差和不确定性。
精度提升
一、拍摄棋盘格
为获得最佳效果,请使用至少10到20张包含校准图案的图像。 校准器至少需要三个图像。 尽量使用未压缩或压缩损失很小的图像格式(如png或bmp)。 为了更高的校准精度你需要:
-
获取一部分你所关注的距离处的棋盘格图片,比如你要测量2米远的物体,那么请将棋盘放在距离相机2米左右的地方拍摄一部分图片
-
棋盘表面和相机成像平面的夹角必须小于45度
不要修改图像,比如对其进行剪切
不要使用自动聚焦模式或改变图像的放大倍率
以相对于相机的不同方向拍摄棋盘图像
尽量采集各种不同的棋盘图像。镜头的畸变从图像中心径向增加,并且有时在图像各帧上表现不均匀, 为了获取图像的畸变信息,棋盘应当处在图像的各种不同边缘处
确保棋盘图案在左右两幅图像中都能被完整的显示
在每一对图像中尽量保持棋盘静止,也就是在同一时间拍摄。 若棋盘在两幅图像中发生了相对运动,会对标定精度产生负面影响
若想对远距离的重建获得更高的精度,需要将两个相机的距离调整的更大。
二、提升标定精度
添加或删除图像
添加图像:
- 少于10张图像时
- 棋盘没有覆盖足够的图像帧时
- 棋盘与相机的相对方向变化不够多时
删除图像:
- 删除具有较大重投影误差的图像
- 删除太模糊的图像
- 删除棋盘平面与相机平面夹角超过45度的图像
标定代码实现
import cv2
import numpy as np
import glob
def main():
# 参数设置
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
w, h = 11, 8 # 棋盘格内角点数量(亲自数)
objp = np.zeros((w * h, 3), np.float32)
objp[:, :2] = np.mgrid[0:w, 0:h].T.reshape(-1, 2)
# 存储角点信息
objpoints = [] # 三维世界坐标
imgpoints = [] # 二维图像坐标
# 加载并处理图像
images = glob.glob('data/d2/*.jpg')
for fname in images:
img = cv2.imread(fname)
# img = cv2.resize(img, (768, 1024)) # 统一图像大小
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# gray = cv2.GaussianBlur(gray, (11, 11), 0) # 滤波处理
# 寻找棋盘格角点
ret, corners = cv2.findChessboardCorners(gray, (w, h), None)
if ret:
corners = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
# 亚像素级角点检测
m = [c[0] for c in corners]
objpoints.append(objp)
imgpoints.append(corners)
# 可视化和保存结果
cv2.drawChessboardCorners(img, (w, h), corners, True)
cv2.imshow('Corners Found', img)
cv2.waitKey(100)
# 根据需要保存图像,这里以序号命名
cv2.imwrite(f"result/mm_{len(imgpoints)}.jpg", img)
else:
print(f"Calibration failed for image: {fname}")
cv2.destroyAllWindows()
# 相机标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, (768, 1024), None, None)
# 输出标定结果
print("Calibration Error:", ret)
print("Intrinsic Matrix:\n", mtx)
print("Distortion Coefficients:\n", dist.ravel())
# 如果需要,可以保存或进一步处理旋转向量和平移向量
# print("Rotation Vectors:\n", rvecs)
# print("Translation Vectors:\n", tvecs)
if __name__ == '__main__':
main()