OpenCV的2.3摄像机标定(OpenCV 2.3 camera calibration)

2019-06-23 10:12发布

我试图使用OpenCV 2.3 Python绑定来校准相机。 我在MATLAB中使用下面的数据和校准工作,但我似乎无法得到它的OpenCV的工作。 相机矩阵我设置为初始猜测非常接近从MATLAB工具箱计算出答案。

import cv2
import numpy as np

obj_points = [[-9.7,3.0,4.5],[-11.1,0.5,3.1],[-8.5,0.9,2.4],[-5.8,4.4,2.7],[-4.8,1.5,0.2],[-6.7,-1.6,-0.4],[-8.7,-3.3,-0.6],[-4.3,-1.2,-2.4],[-12.4,-2.3,0.9],    [-14.1,-3.8,-0.6],[-18.9,2.9,2.9],[-14.6,2.3,4.6],[-16.0,0.8,3.0],[-18.9,-0.1,0.3],    [-16.3,-1.7,0.5],[-18.6,-2.7,-2.2]]
img_points = [[993.0,623.0],[942.0,705.0],[1023.0,720.0],[1116.0,645.0],[1136.0,764.0],[1071.0,847.0],[1003.0,885.0],[1142.0,887.0],[886.0,816.0],[827.0,883.0],[710.0,636.0],[837.0,621.0],[789.0,688.0],[699.0,759.0],[768.0,800.0],[697.0,873.0]]

obj_points = np.array(obj_points)
img_points = np.array(img_points)

w = 1680
h = 1050
size = (w,h)

camera_matrix = np.zeros((3, 3))
camera_matrix[0,0]= 2200.0
camera_matrix[1,1]= 2200.0
camera_matrix[2,2]=1.0
camera_matrix[2,0]=750.0
camera_matrix[2,1]=750.0 

dist_coefs = np.zeros(4)
results = cv2.calibrateCamera(obj_points, img_points,size, 
    camera_matrix, dist_coefs)

Answer 1:

首先,你的相机矩阵是错误的。 如果你读的文档 ,它应该是这样的:

fx  0 cx
 0 fy cy
 0  0  1

如果你看一下你的,你知道了南辕北辙:

fx  0  0
 0 fy  0
cx cy  1

因此,首先,设置camera_matrixcamera_matrix.T (或更改你如何构建camera_matrix 。请记住, camera_matrix[i,j] i j )。

camera_matrix = camera_matrix.T

接下来,我跑了你的代码,我看到“似乎无法得到它的工作”是指以下错误(顺便说一句 - 总是说你的意思是“似乎无法得到它的工作”,在你的问题 - 如果它是一个错误,发布错误。如果它运行,但给你怪人号码,说的话)。

OpenCV Error: Assertion failed (ni >= 0) in collectCalibrationData, file /home/cha66i/Downloads/OpenCV-2.3.1/modules/calib3d/src/calibration.cpp, line 3161
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
cv2.error: /home/cha66i/Downloads/OpenCV-2.3.1/modules/calib3d/src/calibration.cpp:3161: error: (-215) ni >= 0 in function collectCalibrationData

然后我读取文档 (顺便非常有用),并注意到obj_pointsimg_points必须载体的载体 ,因为它有可能在集对象/图像点的对于相同棋盘的多个图像进料(/校准点) 。

因此:

cv2.calibrateCamera([obj_points], [img_points],size, camera_matrix, dist_coefs)

什么? 我仍然得到同样的错误?

然后,我看了一下OpenCV的python2样本(在文件夹OpenCV-2.xx/samples/python2 ),并注意到calibration.py向我展示了如何使用校准功能(永远不要低估样本,他们经常比文档更好!)。

我试图运行calibration.py ,但它不运行,因为它不提供camera_matrixdistCoeffs参数,这是必要的。 所以,我修改了它在虚拟养活camera_matrixdistCoeffs ,哎,它的作品!

唯一的区别我可以在我看到之间obj_points / img_points与他们的,是他们具有dtype=float32同时矿井没有。

所以,我改变我的obj_pointsimg_points也有D型FLOAT32(在python2接口的OpenCV是有点意思,往往当矩阵没有功能不起作用dtype ):

obj_points = obj_points.astype('float32')
img_points = img_points.astype('float32')

然后我再试试:

>>> cv2.calibrateCamera([obj_points], [img_points],size, camera_matrix, dist_coefs)
OpenCV Error: Bad argument 
(For non-planar calibration rigs the initial intrinsic matrix must be specified) 
in cvCalibrateCamera2, file ....

什么?! 一个不同的错误最少。 但我确实提供初始内在矩阵!

所以,我回去的文件,并注意flags参数:

标志 - 不同的标记,它们可以是零或以下的值的组合:

CV_CALIB_USE_INTRINSIC_GUESS cameraMatrix包含被进一步优化FX,FY,CX,CY的有效初始值

...

啊哈,所以我要明确地告诉函数使用我提供了最初的猜测:

cv2.calibrateCamera([obj_points], [img_points],size, camera_matrix.T, dist_coefs,
                    flags=cv2.CALIB_USE_INTRINSIC_GUESS)

欢呼! 有用!

(这个故事告诉我们-如果你正在使用Python仔细阅读OpenCV的文档,并使用最新的版本(在opencv.itseez.com IE) cv2接口另外,咨询的例子中, samples/python2目录来补充文档。有了这两样东西,你应该能够制定出最多的问题。)



Answer 2:

对于什么是值得的,下面的代码片段当前工作2.4.6.1下:

    pattern_size = (16, 12)
    pattern_points = np.zeros( (np.prod(pattern_size), 3), np.float32)
    pattern_points[:, :2] = np.indices(pattern_size).T.reshape(-1, 2).astype(np.float32)
    img_points = pattern_points[:, :2] * 2  + np.array([40, 30], np.float32)
    print(cv2.calibrateCamera([pattern_points], [img_points], (400, 400), flags=cv2.CALIB_USE_INTRINSIC_GUESS))

需要注意的是camera_matrix并且不需要dist_coefs。



Answer 3:

从mathematical.coffee后帮我有这个3D校准运行。

import cv2
from cv2 import cv
import numpy as np

obj_points = [[-9.7,3.0,4.5],[-11.1,0.5,3.1],[-8.5,0.9,2.4],[-5.8,4.4,2.7],[-4.8,1.5,0.2],[-6.7,-1.6,-0.4],[-8.7,-3.3,-0.6],[-4.3,-1.2,-2.4],[-12.4,-2.3,0.9],[-14.1,-3.8,-0.6],[-18.9,2.9,2.9],[-14.6,2.3,4.6],[-16.0,0.8,3.0],[-18.9,-0.1,0.3],[-16.3,-1.7,0.5],[-18.6,-2.7,-2.2]]
img_points = [[993.0,623.0],[942.0,705.0],[1023.0,720.0],[1116.0,645.0],[1136.0,764.0],[1071.0,847.0],[1003.0,885.0],[1142.0,887.0],[886.0,816.0],[827.0,883.0],[710.0,636.0],[837.0,621.0],[789.0,688.0],[699.0,759.0],[768.0,800.0],[697.0,873.0]]

obj_points = np.array(obj_points,'float32')
img_points = np.array(img_points,'float32')

w = 1680
h = 1050
size = (w,h)

camera_matrix = np.zeros((3, 3),'float32')
camera_matrix[0,0]= 2200.0
camera_matrix[1,1]= 2200.0
camera_matrix[2,2]=1.0
camera_matrix[0,2]=750.0
camera_matrix[1,2]=750.0 

dist_coefs = np.zeros(4,'float32')

retval,camera_matrix,dist_coefs,rvecs,tvecs = cv2.calibrateCamera([obj_points],[img_points],size,camera_matrix,dist_coefs,flags=cv.CV_CALIB_USE_INTRINSIC_GUESS)

我现在唯一的问题是,为什么是从校准函数返回时dist_coefs向量是5个元素长。 的文档说“如果载体含有四个元素,这意味着K3 = 0”。 但实际上K3被使用时,无论dist_coefs的长度(4或5)。 此外,我似乎无法获得标志CV_CALIB_FIX_K3工作,捆绑使用该标志可以强制K3为零。 钱圈说的整数是必需的。 这可能是因为我不知道怎么一下子,我只是在做这个做多的旗帜,旗帜=(cv.CV ...,cv.CV ...)。

Just to compare, from the matlab camera cal routine the results are...
    Focal length: 2210. 2207.
    principal point: 781. 738.
    Distortions: 4.65e-2 -9.74e+0 3.9e-3 6.74e-3 0.0e+0
    Rotation vector: 2.36 0.178 -0.131
    Translation vector: 16.016 2.527 69.549

From this code,
    Focal length: 1647. 1629.
    principal point: 761. 711.
    Distortions: -2.3e-1 2.0e+1 1.4e-2 -9.5e-2 -172e+2
    Rotation vector: 2.357 0.199 -0.193
    Translation vector: 16.511 3.307 48.946

我想,如果我能想出如何强制K3 = 0,该值的其余部分将右对齐的。



Answer 4:

使dist_coeffs矢量作为5维零向量,然后使用CV_CALIB_FIX_K3标志。 你可以看到在矢量(K3)是最后一个元素将是零。

当涉及到使用多个标志,你可以或者将它们。

例如:cv.CV_CALIB_USE_INTRINSIC_GUESS | cv.CV_CALIB_FIX_K3



Answer 5:

使用Point3fPoint2f而不是Point3dPoint2d定义object_pointsimage_points ,它会工作。



文章来源: OpenCV 2.3 camera calibration