pythonでカメラ行列と歪みパラメータの取得


Opencvを使用してカメラのカメラ行列とレンズ歪み係数を求めます．



```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import cv2
import matplotlib.pyplot as plt
import numpy as np


square_size = 2.2      # 正方形の1辺のサイズ[cm]
pattern_size = (7, 7)  # 交差ポイントの数

reference_img = 40 # 参照画像の枚数

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 = []

capture = cv2.VideoCapture(0)

while len(objpoints) < reference_img:
# 画像の取得
	ret, img = capture.read()
	height = img.shape[0]
	width = img.shape[1]

	gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

	# チェスボードのコーナーを検出
	ret, corner = cv2.findChessboardCorners(gray, pattern_size)
	# コーナーがあれば
	if ret == True:
		print("detected coner!")
		print(str(len(objpoints)+1) + "/" + str(reference_img))
		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))   #appendメソッド：リストの最後に因数のオブジェクトを追加
		objpoints.append(pattern_points)

	cv2.imshow('image', img)
	# 毎回判定するから 200 ms 待つ．遅延するのはココ
	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.save("mtx", mtx) # カメラ行列
np.save("dist", dist.ravel()) # 歪みパラメータ
# 計算結果を表示
print("RMS = ", ret)
print("mtx = \n", mtx)
print("dist = ", dist.ravel())
```

キャリブレーション用の画像はこちらを使っています．
印刷してキャリブレーションを行う場合はsquare_size変数の値を適切なサイズに変えてください．

![chessbord.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149593/c661b6c4-cb77-55a6-8514-e2cc3ce7c1fb.png)

40回キャリブレーション画像を認識すると，その認識した40枚の画像を使ってパラメータを計算します．
15枚以上あると良いので，現状で計算が遅すぎない枚数として40枚としています．

同じような画像が入らないようにするため，カメラ画像取得の更新を遅くしてあります．
変えたい場合は以下の値を変えてください．

```python
if cv2.waitKey(200) & 0xFF == ord('q'):
```

また，実行したときには距離と角度を色々変えながら認識させると良いです．



実行するとこのような結果になります．

```python
detected coner!
1/40
detected coner!
2/40
detected coner!
3/40
detected coner!
4/40
detected coner!
5/40
detected coner!
6/40
detected coner!
7/40
detected coner!
8/40
detected coner!
9/40
detected coner!
10/40
detected coner!
11/40
detected coner!
12/40
detected coner!
13/40
detected coner!
14/40
detected coner!
15/40
detected coner!
16/40
detected coner!
17/40
detected coner!
18/40
detected coner!
19/40
detected coner!
20/40
detected coner!
21/40
detected coner!
22/40
detected coner!
23/40
detected coner!
24/40
detected coner!
25/40
detected coner!
26/40
detected coner!
27/40
detected coner!
28/40
detected coner!
29/40
detected coner!
30/40
detected coner!
31/40
detected coner!
32/40
detected coner!
33/40
detected coner!
34/40
detected coner!
35/40
detected coner!
36/40
detected coner!
37/40
detected coner!
38/40
detected coner!
39/40
detected coner!
40/40
calculating camera parameter...
RMS =  0.21882789249723134
mtx = 
 [[648.04012214   0.         320.76171716]
 [  0.         652.62477735 208.35649242]
 [  0.           0.           1.        ]]
dist =  [ 0.01040599  0.12315692 -0.00503227 -0.00203478 -0.59133164]

```

カメラ行列はmtx.npy
歪み係数はdist.npy
で保存されます．





参考資料
http://pongsuke.hatenadiary.jp/entry/2018/04/19/094147
http://pynote.hatenablog.com/entry/opencv-camera-calibration
opencvでのカメラ歪み補正
http://pynote.hatenablog.com/entry/opencv-camera-calibration