Matlab OpenCV 2.3摄像机校准
我正在尝试使用Matlab OpenCV 2.3摄像机校准,matlab,opencv,computer-vision,vision,camera-calibration,Matlab,Opencv,Computer Vision,Vision,Camera Calibration,我正在尝试使用opencv2.3python绑定来校准相机。我在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
opencv2.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)
首先,你的相机矩阵是错误的。如果您阅读了,它应该如下所示:
fx 0 cx
0 fy cy
0 0 1
如果你看你的,你就错了:
fx 0 0
0 fy 0
cx cy 1
因此,首先,将camera\u matrix
设置为camera\u matrix.T
(或者更改构建camera\u matrix
的方式。记住camera\u matrix[i,j]
是行i
,列j
)
接下来,我运行了你的代码,我发现“似乎无法让它工作”意味着以下错误(顺便说一句——在你的问题中总是说出你所说的“似乎无法让它工作”的意思——如果是错误,就发布错误。如果它运行了,但给你奇怪的数字,就这样说):
什么?我还是会犯同样的错误
然后,我查看了OpenCV python2示例(在文件夹OpenCV-2.x.x/samples/python2
中),并注意到一个calibration.py
向我展示了如何使用校准函数(永远不要低估示例,它们通常比文档更好!)
我试图运行calibration.py
,但它没有运行,因为它没有提供必要的camera\u矩阵
和distcoefs
参数。所以我修改了它,加入了一个虚拟的camera\u矩阵
和distcoefs
,嘿,它工作了
我能看到我的obj_点
/img_点
和他们的唯一区别是他们的dtype=float32
,而我的没有
因此,我将我的obj_点
和img_点
更改为也有dtype float32(OpenCV的python2接口就是这样有趣;当矩阵没有dtype
时,函数通常不起作用):
然后我再试一次:
>>> 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 ....
什么?!至少是一个不同的错误。但我确实提供了一个初始的内在矩阵
因此,我回到文档中,注意到标志
参数:
标志–不同的标志,可能为零,也可能为
以下数值:
CV\u CALIB\u USE\u intrinsive\u GUESS
cameraMatrix包含有效的首字母
进一步优化的fx、fy、cx、cy值
啊哈,所以我必须明确地告诉函数使用我提供的初始猜测:
cv2.calibrateCamera([obj_points], [img_points],size, camera_matrix.T, dist_coefs,
flags=cv2.CALIB_USE_INTRINSIC_GUESS)
万岁!它起作用了
(故事的寓意——仔细阅读OpenCV文档,如果您使用的是Python
cv2
接口,请使用最新版本(即OpenCV.itsez.com)。此外,请参考samples/python2
目录中的示例以补充文档。通过这两件事,您应该能够解决大多数问题。)在Mathematic.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”。但事实上,无论距离系数(4或5)的长度如何,都使用K3。此外,我似乎无法让标志CV_CALIB_FIX_K3起作用,只能使用该标志强制K3为零。表示需要整数的现金。这可能是因为我不知道如何一次做多个标志,我只是这样做,标志=(cv.cv…,cv.cv…)
我想如果我能想出如何强制k3=0,其余的值就会对齐 将距离系数向量设置为5维零向量,然后使用CV_CALIB_FIX_K3标志。可以看到向量(K3)中的最后一个元素为零 当涉及到使用多个标志时,您可以选择或使用它们
示例:cv.cv_CALIB_USE_instruction_GUESS | cv.cv_CALIB_FIX_K3以下代码片段目前在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))
请注意,不需要摄像机矩阵和距离系数。使用
点3f
和点2f
而不是点3d
和点2d
来定义对象点
和图像点
,它会工作。你所说的“似乎无法工作”是什么意思?它会给出某种错误吗?(在这种情况下,出现了什么错误?)或者它运行时没有给出您期望的系数?谢谢您,先生。我在文档中找到了“向量中的向量”,但无法很好地理解这意味着什么。@mathematic.coffee:你能给我指出OpenCV校准非共面钻机时使用的算法(论文)吗?我相信这是从Matlab相机校准工具箱的布格。但是,我不确定是蔡的算法还是海基拉的算法?@SatishKumar,我不知道他们使用了什么。有一个指向Bouget Matlab的链接。也许你可以通读源代码看看。我希望我能+10阅读你的示例。我希望他们也能在他们的网站上记录“float32”要求。@mathematic.coffee,您好,您是否能够使用非平面校准设备成功校准?我得到了一个非常高的重投影误差和一个非常接近我作为输入提供的初始猜测的校准矩阵。
>>> 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 ....
cv2.calibrateCamera([obj_points], [img_points],size, camera_matrix.T, dist_coefs,
flags=cv2.CALIB_USE_INTRINSIC_GUESS)
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)
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
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))