Python Opencvを用いた基本行列,基礎行列の推定
今のところただのメモ.気が向いたら説明を書きます.
コードの内容物について
Opencv3 Python3環境上
・特徴点の抽出手法の選択とマッチング,マッチング結果のソートまで
・ビルトイン関数を用いてF行列を推定.エピポーラ線を図示.
・5点法を用いてE行列を復元.F行列もそっち経由で推定
コード
E行列の推定
Geometric Image Transformations — OpenCV 2.4.13.3 documentation
一応流れとしては,画像上の座標をカメラ行列の逆行列で焦点距離が1の歪みのない画像へと変換した後に,8点アルゴリズムと同じような線形手法で求解します。
undistortPointsで座標を変換した後にE行列を推定する流れになっています。
その後,カメラ行列を用いてF行列を再現しようとしたのですが正直あんまりうまくいかないなぁといった印象。
どちらがよりまともな計測結果を出しているのかちょっと測りかねます。
3次元の点群の座標を逆算できるのでそれで図示してみればいいだろうか。
#https://stackoverflow.com/questions/33906111/how-do-i-estimate-positions-of-two-cameras-in-opencv # Normalize for Esential Matrix calaculation pts1_norm = cv2.undistortPoints(np.expand_dims(pts1, axis=1), cameraMatrix=K, distCoeffs=None) pts2_norm = cv2.undistortPoints(np.expand_dims(pts2, axis=1), cameraMatrix=K, distCoeffs=None) E, mask = cv2.findEssentialMat(pts1_norm, pts2_norm, focal=1.0, pp=(0., 0.), method=cv2.RANSAC, prob=0.999, threshold=3.0) points, R, t, mask = cv2.recoverPose(E, pts1_norm, pts2_norm) M_r = np.hstack((R, t)) M_l = np.hstack((np.eye(3, 3), np.zeros((3, 1)))) P_l = np.dot(K, M_l) P_r = np.dot(K, M_r) point_4d_hom = cv2.triangulatePoints(P_l, P_r, np.expand_dims(pts1, axis=1), np.expand_dims(pts2, axis=1)) point_4d = point_4d_hom / np.tile(point_4d_hom[-1, :], (4, 1)) point_4d = point_4d[:3, :].T Kinv = np.linalg.inv(K) Kinvt = np.transpose(Kinv) F = np.multiply(Kinvt,E,Kinv)
カメラ行列と歪み行列
Camera matrix
8.203220199617171602e+02 0.000000000000000000e+00 3.096245711568477077e+02 0.000000000000000000e+00 8.197741669830913906e+02 2.506989838404120974e+02 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00
dist_coeff
-3.122683970392000144e-02 1.165913262734599998e-01 5.941855154279999593e-03 3.277340995399999845e-04 -3.251456801179700151e-01
images
0.jpg
1.jpg
結果:F行列推定+エピポーラ線図示
少しパラメータを変えるだけで大きく変わってしまいます.
これ大丈夫かよ.
AKAZE
歪み補正後
ロバスト推定→RASAC
ORB
RANSAC+歪み補正

ロバスト推定+歪み補正

改善について
もう少しプログラムの中について調べるべきでしょう.
以下のブログが詳しく,またOctaveのソースもあるのでMatlabでも実装できそう.
qiita.com
反省
そういえば8点アルゴリズム等で基礎行列を求めたけど画像上の点はわりと平面上にあるものが多かった。
こういった環境では線形方程式の自由度が退化して計算結果が不安定になりやすいため,あんまり良くないかもしれないという知見を得た。
そうしたらホモグラフィ行列を元にした3次元再構成をすべきだろうがこれらはどう切り替えればいいのかな?
あるいは切り替えなければ行けないという問題でもないのか。