0
0

カメラキャリブレーションを簡単に!自分用の手順まとめ

Posted at

はじめに

カメラキャリブレーション毎回準備するのに手間がかかるから、自分用に手順をまとめる。このブログの通り実行すれば、値得られるというところまでやる。

GitHubだけじゃわからない人用に以下GPTによる解説。

準備

Python環境構築

まずはPython環境を整えましょう。Pythonがインストールされていない場合は、Python公式サイトから最新版をインストールしてください。

必要なものをインストール

次に、キャリブレーションに必要なライブラリをインストールします。以下のコマンドで必要なライブラリをインストールします。

pip install -r requirements.txt

これで、カメラキャリブレーションに必要な環境の準備が完了です。

チェスボードの準備

キャリブレーションにはチェスボードパターンが必要です。checkerboard.pngという名前のチェスボード画像を使用します。この画像を印刷して、キャリブレーション時に撮影用の対象物として使用します。

  1. チェスボード画像の印刷: checkerboard.pngをA4サイズで印刷してください。絶対的なサイズは重要ではないですが、カメラがチェスボード全体を撮影できるよう、適切なサイズに印刷しましょう。

  2. 撮影時の注意点: 撮影する際は、チェスボードを水平、斜め、上下左右など様々な角度から撮影し、キャリブレーションの精度を向上させます。

キャリブレーション用の画像を撮影

キャリブレーションを行うには、チェスボードパターンの画像が必要です。手動で撮影するのは面倒なので、以下のスクリプトで自動的にチェスボードの画像をキャプチャしましょう。

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キャリブレーションが正常に完了している場合、上記のパラメータが合理的な値であることを確認します。")

おわりに

また他のファイル形式で欲しくなったときには、簡単に変更できるよう書き換えるかもしれない。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0