2012-04-05 36 views
5

Tôi đang cố gắng sử dụng các liên kết python OpenCV 2.3 để hiệu chỉnh máy ảnh. Tôi đã sử dụng các dữ liệu dưới đây trong MATLAB và hiệu chuẩn làm việc, nhưng tôi dường như không thể làm cho nó hoạt động trong OpenCV. Ma trận máy ảnh tôi thiết lập như một dự đoán ban đầu rất gần với câu trả lời được tính từ hộp công cụ MATLAB.Hiệu chỉnh máy ảnh 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

Bạn có ý nghĩa gì bởi "dường như không làm cho nó hoạt động" - nó có gây ra lỗi nào đó không? (trong trường hợp đó, lỗi gì?) Hoặc nó chạy và chỉ không cung cấp cho bạn hệ số bạn mong đợi? –

Trả lời

20

Trước hết, ma trận máy ảnh của bạn sai. Nếu bạn đọc , nó sẽ giống như thế:

fx 0 cx 
0 fy cy 
0 0 1 

Nếu bạn nhìn vào bạn, bạn đã có nó một cách sai lầm tròn:

fx 0 0 
0 fy 0 
cx cy 1 

Vì vậy, đầu tiên, thiết lập camera_matrix-camera_matrix.T (hoặc hãy thay đổi cách bạn xây dựng camera_matrix. Hãy nhớ rằng camera_matrix[i,j]hàngi, cộtj).

camera_matrix = camera_matrix.T 

Tiếp theo, tôi đã chạy mã của bạn nó hoạt động" trong câu hỏi của bạn - nếu nó là một lỗi, gửi lỗi Nếu nó chạy nhưng mang đến cho bạn lập dị số, nói như vậy):

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 

sau đó tôi đọc (rất hữu ích bằng cách này) và. nhận thấy rằng obj_pointsimg_points phải là vectơ của vectơ, bởi vì nó có thể nạp vào tập hợp các điểm đối tượng/hình ảnh s cho nhiều hình ảnh của cùng một bàn cờ (/ điểm hiệu chuẩn).

Do đó:

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

gì? Tôi vẫn nhận được cùng một lỗi ?! Sau đó, tôi đã xem xét các mẫu python2 OpenCV (trong thư mục OpenCV-2.x.x/samples/python2), và nhận thấy một calibration.py chỉ cho tôi cách sử dụng các hàm hiệu chuẩn (không bao giờ đánh giá thấp các mẫu, chúng thường tốt hơn tài liệu!) .

Tôi đã cố gắng chạy calibration.py nhưng không chạy vì nó không cung cấp các đối số camera_matrixdistCoeffs cần thiết. Vì vậy, tôi đã sửa đổi nó để nạp vào một số giả camera_matrixdistCoeffs và hey, nó hoạt động!

Sự khác biệt duy nhất tôi có thể thấy giữa số obj_points/img_points và của họ, là của họ có dtype=float32, trong khi tôi thì không.

Vì vậy, tôi thay đổi tôi obj_pointsimg_points cũng có dtype float32 (giao diện python2 để OpenCV là hài hước như thế, thường các chức năng không hoạt động khi ma trận không có một dtype):

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

Sau đó, tôi thử lại:

>>> 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 .... 

Cái gì ?! Một lỗi khác ít nhất.Nhưng tôi đã làm cung cấp ma trận nội tại ban đầu!

Vì vậy, tôi quay trở lại tài liệu, và chú ý đến flags tham số:

cờ - cờ khác nhau mà bạn có thể không hoặc kết hợp cả giá trị sau:

CV_CALIB_USE_INTRINSIC_GUESS cameraMatrix chứa ban đầu có hiệu lực giá trị của fx, fy, cx, cy được tối ưu hóa thêm

...

Aha, vì vậy tôi phải nói với các chức năng một cách rõ ràng sử dụng dự đoán ban đầu tôi cung cấp:

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

Hurrah! Nó hoạt động!

(đạo đức của câu chuyện - đọc tài liệu OpenCV cẩn thận và sử dụng phiên bản mới nhất (ví dụ: trên opencv.itseez.com) nếu bạn đang sử dụng giao diện Python cv2. Ngoài ra, hãy tham khảo các ví dụ trong thư mục samples/python2 bổ sung tài liệu. Với hai điều này, bạn sẽ có thể giải quyết được nhiều vấn đề nhất.)

+0

cảm ơn các bạn. Tôi đã tìm thấy "vectơ của vectơ" trong tài liệu, nhưng không thể tìm thấy một nắm bắt tốt về ý nghĩa của nó. – hokiebird

+0

@ math.coffee: Bạn có thể chỉ cho tôi thuật toán (giấy) được sử dụng trong hiệu chuẩn OpenCV cho các giàn khoan không đồng phẳng không? Tôi tin rằng nó được lấy từ hộp công cụ hiệu chỉnh máy ảnh Matlab bởi Bouguet [link] (http://www.vision.caltech.edu/bouguetj/calib_doc/htmls/ref.html). Nhưng, tôi không chắc đó là thuật toán của Tsai hay thuật toán của Heikkila? –

+0

@SatishKumar, tôi sẽ không có một đầu mối những gì họ sử dụng. [Tài liệu] (http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html?highlight=calibratecamera#bouguetmct) có liên kết đến công cụ Bouget Matlab. Có lẽ bạn có thể đọc qua mã nguồn để xem. –

1

Sau khi được trợ giúp từ math.coffee, tôi đã có hiệu chuẩn 3d này để chạy.

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) 

Vấn đề duy nhất tôi có bây giờ là tại sao vector dist_coefs dài 5 phần tử khi được trả về từ hàm hiệu chuẩn. tài liệu nói rằng "nếu vectơ chứa bốn phần tử, nó có nghĩa là K3 = 0". Nhưng trên thực tế, K3 được sử dụng, bất kể độ dài của dist_coefs (4 hoặc 5). Hơn nữa tôi không thể có vẻ để có được cờ CV_CALIB_FIX_K3 để làm việc, gắn liền với sử dụng lá cờ đó để buộc K3 là số không. tiền mặt nói số nguyên là bắt buộc. điều này có thể là bởi vì tôi không biết làm thế nào để làm nhiều cờ cùng một lúc, tôi chỉ làm điều này, 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 

Tôi nghĩ nếu tôi có thể tìm ra cách ép k3 = 0, phần còn lại của giá trị sẽ căn chỉnh ngay.

1

Tạo véc tơ dist_coeffs làm véc tơ 5 chiều và sau đó sử dụng cờ CV_CALIB_FIX_K3. Bạn có thể thấy phần tử cuối cùng trong vectơ (K3) sẽ bằng không.

Khi nói đến việc sử dụng nhiều cờ, bạn có thể HOẶC chúng.

Ví dụ: cv.CV_CALIB_USE_INTRINSIC_GUESS | cv.CV_CALIB_FIX_K3

2

Đối với những gì nó có giá trị, đoạn mã sau đây hiện đang làm việc dưới 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)) 

Lưu ý rằng camera_matrix và dist_coefs không cần thiết.

0

Sử dụng Point3fPoint2f thay vì Point3dPoint2d để xác định object_pointsimage_points và nó sẽ làm việc.

+0

xin vui lòng, làm cho cộng đồng opencv một ưu tiên và ** không trả lời câu hỏi đã lỗi thời ** – berak