自分用の覚え書きです。
Python でのキャリブレーション
こちらの記事のコードが参考になります。(大枠はほぼそのまんま)
元がビデオキャプチャデバイスから画像を取得しているので、弟氏に撮影済みの複数の画像ファイルからできるように変更してもらったのをさらにちょっと修正しています。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import cv2
import numpy as np
import glob
size = 263.0/11.0
v = 7
h = 10
pattern_size = (v, h)
pattern_points = np.zeros((np.prod(pattern_size), 3), np.float32)
pattern_points[:,:2] = np.indices(pattern_size).T.reshape(-1, 2)
pattern_points *= size
objpoints = []
imgpoints = []
gray = None
images = glob.glob('/path/to/images/*')
nb_images = len(images)
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corner = cv2.findChessboardCorners(gray, pattern_size)
if ret == True:
print("detected coner! : " + fname)
print(str(len(objpoints)+1) + "/" + str(nb_images))
term = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1)
cv2.cornerSubPix(gray, corner, (5,5), (-1,-1), term)
imgpoints.append(corner.reshape(-1, 2))
objpoints.append(pattern_points)
if cv2.waitKey(200) & 0xFF == ord('q'):
break
print("calculating camera parameter...")
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
np.savetxt("./mtx.txt", mtx)
np.savetxt("./dist.txt", dist.ravel())
print("RMS: \n", ret)
print("mtx: \n", mtx)
print("dist: \n", dist.ravel())
size
, v
, h
と glob
先を変更して使います。7×10 のチェスパターンは OpenCV の公式配布の PDFが使えます。印刷するのが面倒だったので、ディスプレイに表示してマスサイズを定規で実測してキャリブレーションしても使える模様。
結果
正常に終了するとカレントディレクトリに mtx.txt と dist.txt が出力されます。例として GoPro HERO9 の標準レンズで SuperView 1080p 撮影した動画を連番静止画に切り出した画像ファイル群をキャリブレーションした結果を貼っておきます。
mtx.txt の例:
カメラ行列です。
1.525072331909339482e+03 0.000000000000000000e+00 1.926770394330916361e+03
0.000000000000000000e+00 1.387841932880385684e+03 1.090097485910696832e+03
0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00
各パラメーターは次に対応しています。
dist.txt の例:
歪み係数です。
-2.260311850138516376e-01
1.311762174153588145e-01
1.140927530495202584e-03
-2.000404311812659601e-05
-3.805798738035257728e-02
上から
の値となります。