Homography Verification Pipeline

iPhoneカメラで取得したpixel座標をロボットアームのマット座標系(mm)に変換する精度を実測し、系統誤差を発見した後、マット正長方形射影で座標系を可視化するまでのプロセス。

Input pixel (x, y)
Matrix H 3 × 3
Output mat_x, mat_z
Unit mm
01 DETECT カメラからpixel座標を取得
02 TRANSFORM homography.npyでmm変換
03 VERIFY 7点の精度測定・誤差確認
04 VISUALIZE マット射影で座標系を可視化

各ステップを選択して詳細を確認

↑
01 DETECT — pixel座標の取得

iPhoneカメラ(Iriun Webcam経由、camera index 2)から取得したフレームは1920×1080px。マット上の赤ブロックや任意の既知点を検出し、その画像上の座標(px, py)を取り出す。

# pixel座標を入力に変換 pt = np.array([[[px, py]]], dtype=np.float32) # perspectiveTransformで変換 result = cv2.perspectiveTransform(pt, H)

ここで使うH(homography行列)は、LOG163でマット四隅のpixel座標とマット実寸定義(MAT_CORNERS_MM)からcv2.findHomographyで生成したもの。カメラが俯瞰視点でマットを見ているとき、任意のpixel座標をマット平面上のmm座標に変換できる。

Camera Index 2(Iriun)
Frame Size 1920 × 1080 px
Mat Coverage 620 × 450 mm
px/mm ratio ≈ 1.73 px/mm
02 TRANSFORM — homography行列の変換

homography.npyは3×3の射影変換行列で、pixel座標(x, y)をマット座標系のmm値(mat_x, mat_z)に変換する。

# 行列(LOG163生成) H = [[-5.683e-01 -4.115e-03 +5.616e+02] [-7.707e-03 +5.737e-01 -1.363e+02] [-1.022e-05 +2.009e-05 +1.000e+00]] # 座標系定義(LOG163確定・恒久) # X+ = 画面左 X- = 画面右 # Z+ = 画面下 Z- = 画面上 # 原点 = アームベース真下

マット実寸の定義(MAT_CORNERS_MM)は物理端を基準に設定されている。アームベース支柱の真下が座標原点(0, 0)で、マットの左端までX方向310mm、マット上端までZ方向89mm奥の位置にある。

MAT_CORNERS_MM = [ [+310.0, -89.0], # UL: 画面左上 [-310.0, -89.0], # UR: 画面右上 [-310.0, +361.0], # LR: 画面右下 [+310.0, +361.0], # LL: 画面左下 ]
03 VERIFY — 7点の精度測定と系統誤差

キャリブレーションに使っていない7点でpixel→mm変換の精度を実測した。実測値はアームベース原点からの距離をマット目盛りで計算。

# 実測(mm) 予測(mm) ΔX ΔZ |err|
1(+229,+244)(+222.7,+265.9)-6.3+21.922.8mm
2(-150,+300)(-155.0,+325.5)-5.0+25.526.0mm
3(-300,0)(-312.7,+30.0)-12.7+30.032.6mm
4(+250,0)(+233.1,+22.7)-16.9+22.728.3mm
5(+50,+300)(+41.4,+321.9)-8.6+21.923.5mm
6(+200,+301)(+187.6,+320.8)-12.4+19.823.3mm
7(-250,+150)(-259.4,+180.7)-9.4+30.732.1mm

系統バイアス(全7点の方向が一致)

ΔX avg
-10.2mm
ΔZ avg
+24.5mm
|err| avg
26.9mm

ΔXは全7点で負、ΔZは全7点で正。ランダムなノイズではなく、一定方向に偏った系統的なバイアスだ。補正で数値を合わせる前に、座標系そのものを可視化することを選んだ。

avg 26.9mm max 32.6mm RMSE 27.2mm 全点 同方向
04 VISUALIZE — マット射影で座標系を可視化

mat_rectify.pyは、homography.npyを使わない。検出したマット四隅pixel座標を直接使って620×450mmの正長方形に射影変換する独立ツール。

# 出力サイズ: 1240×900px (1mm = 2px) M = cv2.getPerspectiveTransform(src_corners, dst) rectified = cv2.warpPerspective(frame, M, (1240, 900)) # mm → 出力pixel の変換 def mm_to_px(mat_x, mat_z): out_x = int((310 - mat_x) * 2) out_y = int((mat_z + 89) * 2) return out_x, out_y # アーム原点 (0, 0) → px(620, 178)
ARM(0,0) X+ X- Z- Z+ UL UR LL LR X+200 X+100 X-100 X-200 Z+100 Z+200

この可視化画像があることで、赤ブロックのpixel検出結果を重畳すれば「homographyが返した座標」と「目で見た位置」が一致しているかどうかを直接確認できる。補正値を計算する前に、まず見える状態で判断できる。

Output size 1240 × 900 px
Scale 2 px / mm
ARM(0,0) px (620, 178)
Method warpPerspective