粗大メモ置き場

個人用,たまーに来訪者を意識する雑記メモ

Python Opencvを用いた基本行列,基礎行列の推定

今のところただのメモ.気が向いたら説明を書きます.

コードの内容物について

Opencv3 Python3環境上

・特徴点の抽出手法の選択とマッチング,マッチング結果のソートまで
・ビルトイン関数を用いてF行列を推定.エピポーラ線を図示.
・5点法を用いてE行列を復元.F行列もそっち経由で推定

コード


E行列の推定

Geometric Image Transformations — OpenCV 2.4.13.2 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
f:id:ossyaritoori:20170625010036j:plain

1.jpg
f:id:ossyaritoori:20170625010113j:plain

結果:F行列推定+エピポーラ線図示

少しパラメータを変えるだけで大きく変わってしまいます.
これ大丈夫かよ.

AKAZE

f:id:ossyaritoori:20170625010520p:plain
歪み補正後
f:id:ossyaritoori:20170625010707p:plain
ロバスト推定→RASAC
f:id:ossyaritoori:20170625010958p:plain

ORB

RANSAC+歪み補正
f:id:ossyaritoori:20170625011105p:plain

ロバスト推定+歪み補正
f:id:ossyaritoori:20170625011153p:plain

改善について

もう少しプログラムの中について調べるべきでしょう.
以下のブログが詳しく,またOctaveのソースもあるのでMatlabでも実装できそう.
qiita.com

反省

そういえば8点アルゴリズム等で基礎行列を求めたけど画像上の点はわりと平面上にあるものが多かった。
こういった環境では線形方程式の自由度が退化して計算結果が不安定になりやすいため,あんまり良くないかもしれないという知見を得た。

そうしたらホモグラフィ行列を元にした3次元再構成をすべきだろうがこれらはどう切り替えればいいのかな?
あるいは切り替えなければ行けないという問題でもないのか。