opencv チュートリアルチャレンジ カメラキャリブレーション

カメラキャリブレーション — OpenCV-Python Tutorials 1 documentation

Aruco で estimatePoseSingleMarkers を試したいと思ったところ、cameraMatrix と distCoeffs が必要だと判明。

OpenCV: ArUco Marker Detection

estimatePoseSingleMarkers
 Pose estimation for single markers.

cameraMatrix と distCoeffs は、カメラ行列(内部パラメータ) レンズ歪みパラメータ らしい。

Camera Calibration and 3D Reconstruction — OpenCV 3.0.0-dev documentation

Python: cv2.calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs[, rvecs[, tvecs[, flags[, criteria]]]]) → retval, cameraMatrix, distCoeffs, rvecs, tvecs

とにかく取得しましょう。

チェスボードを用意する

https://github.com/opencv/opencv/tree/master/samples/data

こちらから、chessboard.png を取得し、印刷。

曲がらないように、板に貼り付けました。

画像を用意する

キャリブレーションしたいカメラ(今回はWEBカメラ)で、チェスボード用紙を、いろんな角度から撮影します。

(背景にいろいろ写り込んでいたので、写真の掲載は控えます)

ディレクトリ calib を作成し、入れ込んでおきます。

パラメーターを算出する

こちらを参考(ほぼそのまま)にしました。

csharp/calibration.py at master · tanaka0079/csharp · GitHub

myCalib.py

# -*- coding: utf-8 -*-

import numpy as np
import cv2
from glob import glob

def main():
    square_size = 1.0      # 正方形のサイズ
    pattern_size = (7, 7)  # 交差ポイントの数
    pattern_points = np.zeros( (np.prod(pattern_size), 3), np.float32 ) #チェスボード(X,Y,Z)座標の指定 (Z=0)
    pattern_points[:,:2] = np.indices(pattern_size).T.reshape(-1, 2)
    pattern_points *= square_size
    objpoints = []
    imgpoints = []

    for fn in glob("calib/*.jpg"):
        # 画像の取得
        gray = cv2.imread(fn, 0)
        print("loading..." + fn)

        # チェスボードのコーナーを検出
        ret, corner = cv2.findChessboardCorners(gray, pattern_size)
        # コーナーがあれば
        if ret == True:
            term = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1)
            cv2.cornerSubPix(gray, corner, (5,5), (-1,-1), term)
        else:
            print('Chessboard not found!')
            continue
        imgpoints.append(corner.reshape(-1, 2))   #appendメソッド:リストの最後に因数のオブジェクトを追加
        objpoints.append(pattern_points)
        #corner.reshape(-1, 2) : 検出したコーナーの画像内座標値(x, y)

    # 内部パラメータを計算
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
    # 計算結果を表示
    print("RMS = ", ret)
    print("mtx = \n", mtx)
    print("dist = ", dist.ravel())
    # 計算結果を保存
    np.savetxt("ret.csv", np.array([ret]), delimiter =',',fmt="%0.14f")
    np.savetxt("mtx.csv", mtx, delimiter =',',fmt="%0.14f")

if __name__ == '__main__':
    main()

私の結果は、

mtx

1420.68234847996541,0.00000000000000,949.20851179562965
0.00000000000000,1374.16684667116965,539.62205073603297
0.00000000000000,0.00000000000000,1.00000000000000

ret

1.129281781

でした。