Pixel → mm 変換パイプライン
Piカメラ視点(上から) — X+=画面左 / Z+=画面下
X+ X− Z− Z+ +310, −89 −310, −89 +310, +361 −310, +361 origin (0,0) 89mm 310mm
01
マット四隅の自動検出(OpenCV)
Iriun Webcam(index 2)から10枚のフレームを取得。Otsu二値化でマット(黒)と机(白)を分離し輪郭を抽出する。

問題: アーム本体も黒いため、マットとアームが一体の輪郭として結合され、頂点が7〜9個になり4点近似できなかった(0/10)。

解決: cv2.convexHull() で凸包を計算してアームの凹みを除去。マットの外周長方形だけが残る → 10/10成功。
02
10フレーム統計的安定化
10フレーム分の四隅座標を収集し、各頂点ごとにメディアン±2σの範囲外を外れ値として除去。残った値を平均化する。

フレーム2でOtsu閾値が134→83に変動した(照明の瞬間変化と推測)が、外れ値除去で吸収され最終結果には影響しなかった。
03
ホモグラフィ行列の計算(cv2.findHomography)
検出した4点のpixel座標と、物理マットの既知mm座標を対応付けて cv2.findHomography() で変換行列 H を計算する。

座標対応: UL(左上)→(+310,−89mm) / UR(右上)→(−310,−89mm) / LR(右下)→(−310,+361mm) / LL(左下)→(+310,+361mm)

計算された行列H(3×3):
[ -0.568304 -0.004115 561.614574 ]
[ -0.007707 0.573659 -136.335350 ]
[ -0.000010 0.000020 1.000000 ]
04
任意のpixelをmmに変換(pixel_to_mm)
homography.npy に保存した行列Hを読み込み、pixel_to_mm(px, py, H) で任意のpixel座標をマット座標系(mm)に変換できる。

cv2.perspectiveTransform() が台形歪みを含む射影変換を補正するため、カメラが完全に真上でなくても正確な変換が得られる。
キャリブレーション結果(誤差 0.00mm)
UL — 画面左上
(443.6, 88.9) px
↓
+310.0, −89.0 mm
UR — 画面右上
(1525.6, 105.1) px
↓
−310.0, −89.0 mm
LR — 画面右下
(1528.5, 888.9) px
↓
−310.0, +361.0 mm
LL — 画面左下
(429.1, 881.1) px
↓
+310.0, +361.0 mm