質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

1回答

3974閲覧

2次元空間の回転行列の回帰分析

syosho

総合スコア6

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2018/11/06 12:49

前提・実現したいこと

python3.6で座標系をキャリブレーションするコードを書きたいと考えています.
2次元空間上でベクトルAとベクトルBはノルムが等しく,角度θ回転したものです.
AからBに回転する行列は図の式で書き表すことができます.
イメージ説明
AとBの角度は常に等しいですが,AとBはノルムも角度も変化するためこれらの時系列データから
ベクトルの内積と外積を計算して平均することで回転行列を作っています.

しかし,これではまだずれが大きいので回帰分析を行い角度θを算出したいと考えています.

試したこと

pythonのscipyのいくつかの関数を調べましたが,目的のものがありませんでした.
一つの式に対して重回帰分析すれば目標が達成できるのではとも考えましたが,どのようにすれば良いかわかりません.

どなたかご教授いただけませんでしょうか.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

アフィン変換の場合、OpenCV に変換前の点群と変換後の点群を与えると、その対応関係を満たすアフィン変換行列を求める関数があります。
求めるには対応する点群が3点以上あればよいです。

サンプルコード

  1. 3点及び変換行列を作成する。
  2. 行列を適用し、3点を変換する。
  3. 変換前と変換後の点群を cv2.getAffineTransform() に与えて、その対応関係を満たす点群を計算する。
  4. OpenCV は画像処理ライブラリなので、返してくるアフィン変換行列は画像座標系 (左上) のものとなっている。なので、(2, 1) 成分と (1, 2) 成分を入れ替えて、標準座標系でのアフィン変換行列にする。
  5. 原点回転ならアフィン変換行列の平行移動成分 (1, 3), (2, 3) はともに0なので、捨てる。
  6. 以上の手順で最初に作成した変換行列を求められた。
  7. 変換行列からスケール、角度を計算する。

python

1import cv2 2import numpy as np 3 4def get_rotation_matrix_2d(angle, sx, sy): 5 angle = np.deg2rad(angle) 6 return np.array([[sx * np.cos(angle), -sx * np.sin(angle)], 7 [sy * np.sin(angle), sy * np.cos(angle)]], 8 dtype=np.float32) 9 10# 行列を作成する。 11mat1 = get_rotation_matrix_2d(angle=20, sx=1.2, sy=1.5) 12 13# 点1 14pts1 = np.array([[1, 1], 15 [2, 3], 16 [4, 3]], dtype=np.float32) 17 18# 変換を適用する。 19pts2 = np.dot(pts1, mat1) 20 21# 2つの点の対応関係から変換行列を求める。 22mat2 = cv2.getAffineTransform(pts1, pts2) 23 24# 画像座標系 (左上原点) なので、標準座標系 (左下原点) の行列にする。 25mat2[0, 1], mat2[1, 0] = mat2[1, 0], mat2[0, 1] 26# 原点中心の回転なら平行移動はないので、3列目は0 27mat2 = mat2[:, :2] 28 29# 求めた行列が元の行列と一致するか 30print(np.allclose(mat1, mat2)) # True 31 32# 行列からスケール係数及び角度を計算する。 33sx = np.sign(mat1[0, 0]) * np.sqrt(mat1[0, 0] ** 2 + mat1[0, 1] ** 2) 34sy = np.sign(mat1[1, 1]) * np.sqrt(mat1[1, 0] ** 2 + mat1[1, 1] ** 2) 35angle = np.rad2deg(np.arctan2(-mat1[0, 1], mat1[0, 0])) 36print('sx: {:.2f}, sy: {:.2f}, angle: {:.2f}'.format(sx, sy, angle)) 37# sx: 1.20, sy: 1.50, angle: 20.00

投稿2018/11/06 14:56

tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問