我试图使用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_matrix
到camera_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_points
和img_points
必须载体的载体 ,因为它有可能在集对象/图像点的对于相同棋盘的多个图像进料(/校准点) 。
因此:
cv2.calibrateCamera([obj_points], [img_points],size, camera_matrix, dist_coefs)
什么? 我仍然得到同样的错误?
然后,我看了一下OpenCV的python2样本(在文件夹OpenCV-2.xx/samples/python2
),并注意到calibration.py
向我展示了如何使用校准功能(永远不要低估样本,他们经常比文档更好!)。
我试图运行calibration.py
,但它不运行,因为它不提供camera_matrix
和distCoeffs
参数,这是必要的。 所以,我修改了它在虚拟养活camera_matrix
和distCoeffs
,哎,它的作品!
唯一的区别我可以在我看到之间obj_points
/ img_points
与他们的,是他们具有dtype=float32
同时矿井没有。
所以,我改变我的obj_points
和img_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:
使用Point3f
和Point2f
而不是Point3d
和Point2d
定义object_points
和image_points
,它会工作。
文章来源: OpenCV 2.3 camera calibration