MotoJapan's Tech-Memo

技術めも

【opencv 基礎知識 #5】透視投影変換行列に関連する関数まとめ (getPerspectiveTransform, calibrateCamera, warpPerspective, perspectiveTransform, undistort, remap)

忘れやすい透視投影変換行列周りの関数をメモ。(python)

具体的に前回の投稿でも使っている。
motojapan.hateblo.jp

1. 透視投影変換行列を求める方法

1.1. 台形補正の場合 [getPerspectiveTransform]

#pts_src 変換前座標 ※台形補正であれば4点
#pts_dst 変換先座標 ※台形補正であれば4点
M = cv2.getPerspectiveTransform(pts_src, pts_dst)

1.2. レンズ歪み補正の場合 [calibrateCamera]

# object_points  チェスボードのパターンの点群
# image_points   チェスボードのコーナーの点群
rms, camera_M, dist_coef, r, t = cv2.calibrateCamera(object_points,image_points,(img.shape[1],img.shape[0]),None,None)

2. 透視投影変換行列による変換方法

2.1. 画像を変換する [warpPerspective]

#img       変換前画像
#img_trans 変換後画像
img_trans = cv2.warpPerspective(img, M, (w, h))

2.2. 座標を変換する [perspectiveTransform]

#pts       変換前座標
#pts_trans 変換後座標
pts_trains = cv2.perspectiveTransform(pts, M)

2.3. 画像を変換する1[undistort](レンズ歪み補正)

img_undistort = cv2.undistort(img, camera_M, dist_coef)

2.4. 画像を変換する2[remap](レンズ歪み補正)

cam_M_ = cv2.getOptimalNewCameraMatrix(camera_M, dist_coef, (img.shape[1], img.shape[0]), 1)[0]
mapx, mapy = cv2.initUndistortRectifyMap(camera_M, dist_coef, np.eye(3), cam_M_, (img.shape[1], img.shape[0]), cv2.cv.CV_32FC1)
img_undistort = cv2.remap(img, mapx, mapy, cv2.cv.CV_INTER_AREA)

おまけ

逆行列について

透視投影変換行列Mの逆行列は、np.linalg.inv(M)
これでimage <-> iamge_trans間を行き来できる

レンズ歪み補正について

  • 歪み種類
    • 放射状歪み
    • 接線歪み
      • この2つはdist_coefで補正する

  • 補正に必要なパラメータ
    • 上記dist_coef
    • カメラの内部パラメータ
      • カメラ固有の焦点距離(fx, fy)や光学中心(cx, cy)
      • camera_Mで補正する
    • カメラの外部パラメータ
      • ある座標系における3次元点の座標を別の座標系での座標に変換するための回転と並進のパラメータ
  • 補正に必要な画像数
    • チェスボードが写った画像10枚程度

camera_M、dist_coefの定義

camera\_M = \begin{pmatrix} f_x&0&c_x \\ 0&f_y&c_y \\ 0&0&1 \end{pmatrix}
dist\_coef = \begin{pmatrix} k_1&k_2&p_1&p_2&p_3  \end{pmatrix}

詳細はここ
カメラ・キャリブレーション — OpenCV-Python Tutorials

具体的な camera_M、dist_coefの中身の例

 In [1]: camera_M
 Out[1]:
 array([[ 452.30622078,    0.        ,  332.44877655],
        [   0.        ,  453.36588503,  267.73560929],
        [   0.        ,    0.        ,    1.        ]])

 In [2]: dist_coef
 Out[2]: array([-0.19224447,  0.07401813,  0.0044831 ,  0.00214658, -0.02052423])

以上。