1、完整报错
报错代码如下:
ret, cameraMatrix, distCoeffs, rvecs, tvecs = cv2.calibrateCamera(cal_img.object_points, cal_img.corners, img_size,None, None)
cv2.error: OpenCV(4.8.0) /io/opencv/modules/calib3d/src/calibration.cpp:3408: error: (-210:Unsupported format or combination of formats) objectPoints should contain vector of vectors of points of type Point3f in function 'collectCalibrationData'
官方API对参数的描述,点我进入OpenCV库cv2.calibrateCamera的API。
calibrateCamera (
InputArrayOfArrays objectPoints,
InputArrayOfArrays imagePoints,
Size imageSize,
InputOutputArray cameraMatrix,
InputOutputArray distCoeffs,
OutputArrayOfArrays rvecs,
OutputArrayOfArrays tvecs,
int flags = 0,
TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON)
)
参数调试截图(错误代码行):
给cv2.calibrateCamera
函数 cal_img.object_points, cal_img.corners,均是np
类型数组,如下图1所示:
实际上,cv2.calibrateCamera
函数需要多张输入图片,读取成list
或者np
类型,该类型中每一个存储都是np
类型,且objectPoints
必须是整数,如下图2所示,读者可以好好比对一下。
2、报错原因
在做相机标定时候,我采用了OpenCV库中的cv2.calibrateCamera
来标定内参,但是因为对相机标定没那么熟悉,想着把标定板的坐标[[0, 0, 0], [1, 0, 0], [2, 0, 0], ...]
直接加上实际标定板距离世界坐标系原点的相对位置坐标[x, y, z]
,标定板的黑色正方形边长d,就把标定板的坐标变成了[[0+x+d, y, 0+z], [0+x+2d, y, 0+z], [0+x+3d, y, 0+z], ...]
,妄想一步就求出外参,实则用错函数,我也不知道读者是不是跟我一样的思想,我只是一个小白,这是学习中踩下的坑。 话不多说,直接说解决方案。
3、解决方案
3.1 求内参
注意看上图2即可,objectPoints
与imagePoints
必须是list
或者np
类型,列表中包含多张图片数据(np
类型)。且objectPoints
中的每个点必须是整数,如上图2所示,读者可以好好比对一下。
这样修改可以使得代码不报错,但是没求出来的内外参没有那么准确,因为您只用了一张图片来求,我无非是帮你生维度了,建议读入多张图片。
ret, cameraMatrix, distCoeffs, rvecs, tvecs = cv2.calibrateCamera(np.expand_dims(objectPoints, axis=0), np.expand_dims(imagePoints, axis=0), img_size,None, None)
3.2 求外参
如果读者是只有一张图片,读取的变量如图一所示,那么什么也不需要改,将你的变量直接放入下列函数中,但需要相机内参与畸变矩阵已知!!!
_, rvecs, tvecs = cv2.solvePnP(object_points, corners, self.cameraMatrix, self.distCoeffs)
4、更为简单的方法
4.1 拉取代码
拉取我写的标定代码,把cfg.yml
中的文件地址改为自己的地址即可,我也上传了一些图片,用于跑代码,作者可以仿照着给图片。【点我进入GitHub代码】
git clone https://github.com/Wei-JL/camera_calibration.git
cfg.yml
文件如下:
CameraID: 1 # 该属性没有用到
CamerName: HSCamera1 # 该属性没有用到
ImageSize: [640, 480]
Pattern: "INVAILD_STRING" # 该属性没有用到
BoardSize: [13, 9] # 标定板的角点13 x 9
FrameNum: 30 # 该数字没有用到,尽可能大于30张用于求内参和畸变矩阵
SquareSize: 0.018 # 标定板的黑色正方形的边长,单位M
DistanceFromOrigin: [0.555, 0.55, 0.96] # X-Y-Z 右手坐标系,单位M, y轴向前
DemarcateEdgeDistance: [0.021, 0.012] #标定板一端的多余留白的宽,以及多余留白的长
SaveIMGPath: [False, "./out_draw_img/"]
# 求内参所用的图片文件夹路径
InternalImgPath: "./imgData/InternalParametersIMG/"
# 求外参所用的图片文件夹路径
ExternalImgPath: "./imgData/ExternalParametersIMG/"
# 保存生成的内外参
SaveYMLPath: "./ymlResult/CameraPropertiesYML.yml"
直接运行main.py
,得到 ymlResult/CameraPropertiesYML.yml
内容如下:
%YAML:1.0
---
cameraMatrix: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 5.8872269401549318e+02, 0., 3.1396526288061324e+02, 0.,
5.8916193444451278e+02, 2.3596852375684645e+02, 0., 0., 1. ]
distCoeffs: !!opencv-matrix
rows: 1
cols: 5
dt: d
data: [ 2.3846216967883582e-02, 3.1566029814152891e-01,
-3.4342893273889208e-03, -3.9197758689113425e-03,
-1.2329393625222367e+00 ]
external_rot_index0: !!opencv-matrix
rows: 3
cols: 1
dt: d
data: [ -5.0544041998692286e-02, 9.4373234595587441e-02,
-2.3742117741779416e-02 ]
external_tra_index0: !!opencv-matrix
rows: 3
cols: 1
dt: d
data: [ -1.2322397186032250e+01, 1.7099433969274160e+00,
3.0594561071329622e+01 ]
external_rot_index1: !!opencv-matrix
rows: 3
cols: 1
dt: d
data: [ -5.0544053387929486e-02, 9.4373100695407761e-02,
-2.3742107968675215e-02 ]
external_tra_index1: !!opencv-matrix
rows: 3
cols: 1
dt: d
data: [ -1.2322397408243795e+01, 1.7099434779488030e+00,
3.0594561991082113e+01 ]