2012-04-05 187 views
5

我正在嘗試使用OpenCV 2.3 python綁定來校準相機。我已經在matlab中使用了下面的數據,並且校準工作,但我似乎無法使它在OpenCV中工作。設置爲初始猜測的相機矩陣非常接近從matlab工具箱計算出的答案。OpenCV 2.3相機校準

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) 
+1

你是什麼意思的「似乎無法得到它的工作」 - 它會給出某種錯誤? (在這種情況下,有什麼錯誤?)還是它運行,只是沒有給你你期望的係數? – 2012-04-05 04:56:02

回答

20

首先,你的相機矩陣是錯誤的。如果你讀了,它應該看起來像:

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必須是向量向量,因爲它是可能的飼料對象/圖像點集s用於同一棋盤的多個圖像(/校準點)。

因此:

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

什麼?我仍然有同樣的錯誤?!然後,我看了一下OpenCV python2樣本(在文件夾OpenCV-2.x.x/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 .... 

什麼?!至少有一個不同的錯誤。但我did提供了一個初始的固有矩陣!

所以我回去的文件,並注意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) 

萬歲!有用!

(道德故事 - 仔細閱讀OpenCV文檔,如果您使用的是Python cv2接口,請使用最新版本(即在opencv.itseez.com上)並查閱samples/python2目錄中的示例以補充說明文檔有了這兩件事,你應該能夠解決大多數問題。)

+0

謝謝親切的先生。我在文檔中找到了「載體向量」,但無法很好地理解這意味着什麼。 – hokiebird 2012-04-09 05:24:02

+0

@ mathematical.coffee:您能否將我指向非共面鑽機OpenCV校準中使用的算法(紙張)?我相信它是由Bouguet [link](http://www.vision.caltech.edu/bouguetj/calib_doc/htmls/ref.html)從Matlab相機校準工具箱中提取出來的。但是,我不確定是蔡氏算法還是海克基拉算法? – 2012-11-05 13:08:31

+0

@SatishKumar,我不知道他們用什麼。 [文檔](http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html?highlight=calibratecamera#bouguetmct)有一個鏈接到Bouget Matlab的東西。也許你可以通讀源代碼來看看。 – 2012-11-05 23:29:17

1

在從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爲零。兌現說一個整數是必需的。這可能是因爲我不知道如何一次做多個標記,我只是這樣做,flags =(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,其餘的值將對齊。

1

使dist_coeffs向量爲5維零向量,然後使用CV_CALIB_FIX_K3標誌。您可以看到向量(K3)中的最後一個元素將爲零。

當涉及到使用多個標誌,你可以或他們。

示例:cv.CV_CALIB_USE_INTRINSIC_GUESS | cv.CV_CALIB_FIX_K3

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。

0

使用Point3fPoint2f代替Point3dPoint2d定義object_pointsimage_points,它會工作。

+0

請給opencv社區一個忙,**不要回答過時的問題** – berak 2015-05-22 19:34:43