カメラキャリブレーション – 内部パラメータ・外部パラメータから3次元復元まで

はじめに

カメラキャリブレーションは、コンピュータビジョンにおいて基礎的かつ重要な技術です。実世界の3次元空間をカメラで撮影し2次元画像として取得する過程で、カメラレンズの歪みやカメラの位置・姿勢などの情報を正確に把握する必要があります。この記事では、カメラキャリブレーションの基本概念から実践的な応用まで、体系的に解説します。

この記事を書いたひと

デジタルリアクタ合同会社 代表
機械学習・統計、数値計算などの領域を軸としたソフトウェアエンジニアリングを専門としています。スタートアップからグローバル企業まで、さまざまなスケールの企業にて、事業価値に直結する計算システムを設計・構築してきました。主に機械学習の応用分野において、出版・発表、特許取得等の実績があり、また、IT戦略やデータベース技術等の情報処理に関する専門領域の国家資格を複数保有しています。九州大学理学部卒業。日本ITストラテジスト協会正会員。

対象読者:

  • コンピュータビジョン初心者から中級者
  • カメラキャリブレーションの実践的な知識を学びたいエンジニア
  • 3次元復元、AR、ロボットビジョンなどの分野に関心のある方

記事のポイント:

  • カメラキャリブレーションの必要性と原理を分かりやすく解説
  • 内部パラメータと外部パラメータの概念と推定方法を説明
  • OpenCVを用いた実践的なキャリブレーション手順を紹介
  • キャリブレーション精度向上のためのヒントやよくある問題への対処法を提示

カメラキャリブレーションとは

カメラキャリブレーションとは、カメラの特性や位置・姿勢に関するパラメータを推定するプロセスです。具体的には、以下のパラメータを推定します。

  • 内部パラメータ(Intrinsic Parameters): カメラの光学的特性(焦点距離、レンズ歪みなど)
    • カメラごとに特定されるパラメータです。
  • 外部パラメータ(Extrinsic Parameters): カメラの位置と姿勢(回転と並進)
    • カメラ同士のペアに対して特定されるパラメータです。典型的にはステレオカメラのカメラ間の位置関係が該当します。1つのカメラしか使わない場合には計算しません。

なぜカメラキャリブレーションが必要か

カメラキャリブレーションは、以下のような応用で必要不可欠です。

  • 拡張現実(AR)アプリケーション
  • 3次元再構成
  • ロボットビジョン
  • 産業用の計測・検査システム
  • マルチカメラシステムでの3D復元

実際の現場では、カメラキャリブレーションの重要性は想像以上に大きなものです。例えば、工場での製品検査において0.1mmの精度が要求される場合、適切なキャリブレーションなしでは全く使い物になりません。キャリブレーションの精度が悪いために、開発したシステムが使えなくなってしまうケースもあります。

カメラの内部パラメータ(Intrinsic Parameters)

内部パラメータは、カメラの光学的特性を表すパラメータです。

カメラ行列

内部パラメータは通常、以下のような3×3のカメラ行列で表現されます。

| fx  0   cx |
| 0   fy  cy |
| 0   0   1  |

ここで、

  • fx, fy: x方向とy方向の焦点距離(ピクセル単位)
  • cx, cy: 画像中心(主点)の座標(ピクセル単位)

歪み係数

レンズの歪みは以下の係数で表現されます。

  • 放射歪み係数(k1, k2, k3
  • 接線歪み係数(p1, p2

実務上のポイント:
最近の高品質なカメラレンズでは、k3p1, p2の値がほぼゼロになることが多いです。特にスマートフォンのカメラは工場出荷時に高精度なキャリブレーションが行われているため、k1k2のみで十分な補正が可能です。一方で、広角レンズや魚眼レンズを使用する場合は、高次の歪み係数も重要になってきます。

OpenCVでは、cv2.calibrateCamera()関数で以下のように歪み係数を推定します。

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(
    objpoints, imgpoints, gray.shape[::-1], None, None
)

カメラの外部パラメータ(Extrinsic Parameters)

外部パラメータは、カメラの位置と姿勢を表すパラメータです。

回転行列と並進ベクトル

外部パラメータは以下の2つの要素で構成されます。

  • 回転行列 R(3×3行列): カメラの姿勢を表す
  • 並進ベクトル t(3×1ベクトル): カメラの位置を表す

これらは以下の変換行列として表現されます。

| R11 R12 R13 t1 |
| R21 R22 R23 t2 |
| R31 R32 R33 t3 |
| 0   0   0   1  |

座標変換

ワールド座標系の点Pwからカメラ座標系の点Pcへの変換は以下の式で表されます。

Pc = R * Pw + t

ステレオカメラのキャリブレーション

ステレオカメラのキャリブレーションでは、2台のカメラ間の位置関係(外部パラメータ)を求めます。OpenCVではcv2.stereoCalibrate()関数を使用します。

# ステレオキャリブレーションの実行
ret, mtx1, dist1, mtx2, dist2, R, t, E, F = cv2.stereoCalibrate(
    objpoints,          # 3D点群(チェッカーボードの世界座標)
    imgpoints1,         # カメラ1での2D点群
    imgpoints2,         # カメラ2での2D点群
    cameraMatrix1,      # カメラ1の内部パラメータ行列
    distCoeffs1,        # カメラ1の歪み係数
    cameraMatrix2,      # カメラ2の内部パラメータ行列
    distCoeffs2,        # カメラ2の歪み係数
    imageSize,          # 画像サイズ
    flags=cv2.CALIB_FIX_INTRINSIC  # 内部パラメータを固定
)

この関数は以下のパラメータを返します:

  • R: カメラ2からカメラ1への回転行列
  • t: カメラ2からカメラ1への並進ベクトル
  • E: Essential行列(画像のステレオ補正に使用します)
  • F: Fundamental行列(画像のステレオ補正に使用します)

実践的なヒント:

  1. キャリブレーション手順:
    • まず各カメラを個別にキャリブレーションして内部パラメータを求める
    • 両方のカメラで同時にチェッカーボードを撮影
    • cv2.stereoCalibrate()で外部パラメータを計算
  2. 精度向上のためのポイント:
    • チェッカーボードは両方のカメラから十分見える位置に配置
    • 様々な角度・距離でのデータを取得(最低15枚以上)
    • キャリブレーション時のRMS誤差を確認(一般的に1ピクセル以下が望ましい)
# キャリブレーション結果の評価
print(f"キャリブレーションのRMS誤差: {ret}")

# ステレオ補正行列の計算
R1, R2, P1, P2, Q, roi1, roi2 = cv2.stereoRectify(
    mtx1, dist1,
    mtx2, dist2,
    imageSize, R, t
)

ステレオ補正(Rectification)により、エピポーラ線が画像の水平線と平行になるように画像を変換できます。これにより、ステレオマッチングが容易になります。

三角測量とOpenCV関数

三角測量の基本原理

三角測量は、2つ以上のカメラで撮影された画像から3次元点の位置を復元する技術です。異なる視点からの2次元座標情報を用いて、幾何学的に3次元位置を計算します。

主要なOpenCV関数

OpenCVではいくつかの関数が三角測量に利用できますが、ここでは、2つのカメラからの投影行列と対応点から3D点を復元するtriangulatePoints関数を紹介します。まず、次のように使用します。

points4D = cv2.triangulatePoints(projMatr1, projMatr2, points1, points2)

この関数は4次元の同次座標を出力します。ここから3次元座標への変換は以下のように行います。

# 同次座標から3次元座標への変換
points3D = points4D[:3] / points4D[3]

# より具体的な実装例
def homogeneous_to_3d(points4D):
    """
    同次座標系(4次元)から3次元ユークリッド座標系に変換

    Args:
        points4D: shape (4, N) の同次座標系の点群
    Returns:
        points3D: shape (3, N) の3次元座標系の点群
    """
    # 最後の要素(w)で他の要素を割る
    points3D = points4D[:3] / points4D[3]
    return points3D

# 使用例
points3D = homogeneous_to_3d(points4D)
print(f"3D座標: X={points3D[0]}, Y={points3D[1]}, Z={points3D[2]}")

実務上のヒント:

  • 同次座標の第4成分(w)が非常に小さい場合(ゼロに近い場合)は、点が無限遠にあることを示唆します。
  • このような点は、キャリブレーションの誤差や対応点のミスマッチによって生じることが多いため、フィルタリングすることをお勧めします。
  • 一般的には、w成分の絶対値が一定のしきい値(例:1e-8)より小さい点は除外します。

実践的なキャリブレーション手順

キャリブレーションパターンの準備

一般的に以下のパターンが使用されます。

  • チェッカーボードパターン
  • ChArUcoパターン
  • 円形グリッドパターン

実践的なアドバイス:
チェッカーボードパターンを使用する場合は、光沢のない用紙に印刷し、硬い板に貼り付けることが重要です。光沢紙を使用すると反射が発生し、コーナー検出の精度が著しく低下します。また、パターンが少しでも歪んでいると、キャリブレーション結果に大きく影響するため、完全に平面になるように注意が必要です。

ChArUcoパターンは照明条件の変化に強く、より安定した結果が得られます。特に産業用途では、ChArUcoパターンの使用をお勧めします。

コーナー検出

チェッカーボードのコーナー検出には以下の関数を使用します。

ret, corners = cv2.findChessboardCorners(
    gray, (9,6), None
)

画像の前処理(照明条件が安定しない場合):

# コントラストの改善
gray = cv2.equalizeHist(gray)

# ノイズ除去
gray = cv2.GaussianBlur(gray, (5,5), 0)

応用例とベストプラクティス

キャリブレーション精度向上のためのヒント

  1. 十分な数のキャリブレーション画像を使用(最低15枚程度)
  2. パターンを様々な角度・距離で撮影
  3. カメラ設定(フォーカス、露出など)を固定
  4. 高品質なキャリブレーションパターンを使用

実践的なコツ:

キャリブレーション画像は以下のような構成で撮影すると良い結果が得られます。

  • パターンを画像中心に配置した正面からの撮影(3-4枚)
  • パターンを画像の四隅に寄せた撮影(各隅2-3枚)
  • パターンを30度以上傾けた撮影(4-5枚)
  • パターンをカメラに近づけた撮影(2-3枚)

オートフォーカスを使用している場合は、撮影の度にフォーカスが変わってしまい、正確なキャリブレーションができません。可能な限り、マニュアルフォーカスを使用することをお勧めします。

よくある問題と解決策

問題 考えられる原因 解決策
再投影誤差が大きい キャリブレーション画像の品質が低い、画像枚数が少ない キャリブレーション画像の品質を確認、不適切な画像を除外、より多くのキャリブレーション画像を使用
歪み補正が不適切 高次の歪み係数が考慮されていない 高次の歪み係数を考慮、キャリブレーションパターンの位置を調整

まとめ

カメラキャリブレーションは、コンピュータビジョンにおける重要な基礎技術です。本記事で解説した内容を理解し、適切に実装することで、より精度の高い3次元復元や位置推定が可能になります。

お気軽にご相談ください!

弊社のデジタル技術を活用し、貴社のDXをサポートします。

基本的な設計や実装支援はもちろん、機械学習・データ分析・3D計算などの高度な技術が求められる場面でも、最適なソリューションをご提案します。

初回相談は無料で受け付けております。困っていること、是非お聞かせください。