はじめに
カメラキャリブレーション毎回準備するのに手間がかかるから、自分用に手順をまとめる。このブログの通り実行すれば、値得られるというところまでやる。
GitHubだけじゃわからない人用に以下GPTによる解説。
準備
Python環境構築
まずはPython環境を整えましょう。Pythonがインストールされていない場合は、Python公式サイトから最新版をインストールしてください。
必要なものをインストール
次に、キャリブレーションに必要なライブラリをインストールします。以下のコマンドで必要なライブラリをインストールします。
pip install -r requirements.txt
これで、カメラキャリブレーションに必要な環境の準備が完了です。
チェスボードの準備
キャリブレーションにはチェスボードパターンが必要です。checkerboard.png
という名前のチェスボード画像を使用します。この画像を印刷して、キャリブレーション時に撮影用の対象物として使用します。
-
チェスボード画像の印刷:
checkerboard.png
をA4サイズで印刷してください。絶対的なサイズは重要ではないですが、カメラがチェスボード全体を撮影できるよう、適切なサイズに印刷しましょう。 -
撮影時の注意点: 撮影する際は、チェスボードを水平、斜め、上下左右など様々な角度から撮影し、キャリブレーションの精度を向上させます。
キャリブレーション用の画像を撮影
キャリブレーションを行うには、チェスボードパターンの画像が必要です。手動で撮影するのは面倒なので、以下のスクリプトで自動的にチェスボードの画像をキャプチャしましょう。
take.py
- チェスボード画像の撮影
take.py
はカメラを起動し、チェスボードパターンを検出したときに画像を自動的に保存します。撮影が終了したら、"q"キーを押して終了します。
import cv2
import numpy as np
import os
# チェスボードの内角の数(縦・横のマス数 - 1)
CHECKERBOARD = (6, 9)
# 出力フォルダの作成
output_dir = 'captured_images'
os.makedirs(output_dir, exist_ok=True)
# カメラの設定(カメラIDを0に設定)
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("カメラを開くことができませんでした")
exit()
# 画像の保存カウント
img_counter = 0
while True:
ret, frame = cap.read()
if not ret:
print("フレームを取得できませんでした")
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, None)
# チェスボードが見つかった場合
if ret:
cv2.drawChessboardCorners(frame, CHECKERBOARD, corners, ret)
# チェスボードが検出された場合に画像を保存
img_name = os.path.join(output_dir, f"image_{img_counter:03d}.jpg")
cv2.imwrite(img_name, frame)
print(f"{img_name} を保存しました")
img_counter += 1
cv2.imshow('Camera', frame)
# キー入力待ち(qを押すと終了)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# リソースの解放
cap.release()
cv2.destroyAllWindows()
キャリブレーション実行
撮影が完了したら、次にカメラキャリブレーションを行います。以下のスクリプトcarib.py
を使ってキャリブレーションを実行します。
carib.py
- カメラキャリブレーションの実行
import glob
import cv2
import numpy as np
# チェスボードの内角の数(縦・横のマス数 - 1)
CHECKERBOARD = (6, 9)
# 3Dのワールド座標系の点を生成
objpoints = []
for i in range(CHECKERBOARD[1]):
for j in range(CHECKERBOARD[0]):
objpoints.append([j, i, 0])
objpoints = np.array(objpoints, dtype=np.float32)
# 2Dと3Dの点を保存するリスト
objpoints_list = [] # 3Dのワールド座標系の点
imgpoints_list = [] # 2Dの画像上の点
# 画像の読み込み
images = glob.glob('captured_images/*.jpg') # 撮影した画像のパス
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, None)
if ret:
# 3Dのワールド座標系の点と2Dの画像上の点をリストに追加
objpoints_list.append(objpoints)
imgpoints_list.append(corners)
# カメラキャリブレーション
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(
objpoints_list, imgpoints_list, gray.shape[::-1], None, None)
# キャリブレーションパラメータの保存
np.savez('calib.npz', mtx=mtx, dist=dist, rvecs=rvecs, tvecs=tvecs)
print("キャリブレーションが完了しました。")
値の確認
キャリブレーションが完了したら、保存されたパラメータを確認して正しく実行されたかをチェックします。以下のcheck.py
で確認できます。
check.py
- キャリブレーション結果の確認
import numpy as np
# 保存されたキャリブレーションパラメータの読み込み
data = np.load('calib.npz')
mtx = data['mtx']
dist = data['dist']
rvecs = data['rvecs']
tvecs = data['tvecs']
# カメラ行列、歪み係数、回転ベクトル、平行移動ベクトルの確認
print("カメラ行列 (mtx):\n", mtx)
print("\n歪み係数 (dist):\n", dist)
print("\n回転ベクトル (rvecs):\n", rvecs)
print("\n平行移動ベクトル (tvecs):\n", tvecs)
print("\nキャリブレーションが正常に完了している場合、上記のパラメータが合理的な値であることを確認します。")
おわりに
また他のファイル形式で欲しくなったときには、簡単に変更できるよう書き換えるかもしれない。