私はsolvePnPを使用しており、翻訳ベクトルを取得しています。ここで、いくつかのオイラー角をsolvePnPの結果と比較する必要があります。そして、私はオイラー角を「ロドリーグ」に変換したい/必要があります。
ResolvePnPからの並進ベクトルはオイラー角に等しいですか。変換行列は、ロドリゲスと関係がある唯一のものですか?または、3つのオイラー角とはまったく異なる特別なロドリゲ角がありますか?両方の間の数学はどうですか?見つからなかったOpenCV関数はありますか?
まず、translationベクトルは、rotationとは関係がないため、忘れてください。 :平行移動は物事を動かし、回転はそれらの向きを変えます。
ロドリゲスパラメーターは 軸-角度回転 とも呼ばれます。それらは4つの数_[theta, x, y, z]
_で形成されます。つまり、単位ベクトル_v=[x, y, z]
_で表される軸を中心に角度「シータ」を回転させる必要があります。 cv :: Rodrigues 関数参照を見ると、OpenCVはロドリゲス表記の「コンパクト」表現を3つの要素_rod2=[a, b, c]
_を持つベクトルとして使用しているようです。ここで:
theta
は、入力ベクトルtheta = sqrt(a^2 + b^2 + c^2)
のモジュールです。v
は、正規化された入力ベクトルです:_v = rod2/theta = [a/theta, b/theta, c/theta]
_したがって、solvePnPからのロドリゲスベクトルは、 オイラー角表記とわずかに関連していません。これは、 X、Y、Z軸。
両方の回転を比較する方法は?これは良い質問です。オイラー表現とロドリゲス表現の両方に、特異点やその他の問題があります。たとえば、2つのオイラーアジサシまたは2つのロドリゲスパラメーターを比較すると、完全に異なって見える場合がありますが、実際にはほぼ同じ回転を表しています。両方の回転が同じ(または約)であるかどうかを確認する必要がある場合は、次のアプローチに従うことができます。
@dunadarの優れた答えに追加:
Rodrigues
は、rvec
を回転行列Rに変換します(またはその逆)。回転している(平行移動)ベクトルと内積を取ることにより、オイラー角から構築された回転行列を使用するのと同じ方法で、Rを直接使用できます。v_rotate = R*v
あなたはロドリゲスの回転行列からオイラー角に変換できますが、複数の解決策があります。その理由は、オイラー回転の順序(ピッチ、ヨー、ロール)が重要であるため、ロドリゲスの回転を表す方法は複数あるためです。参照: http://www.staff.city.ac.uk/~sbbh653/publications/euler.pdf
ここで他の回答を補足するために、より具体的な回答を追加します。オイラー角の代わりに方向ベクトルが必要な場合は、行列の乗算を使用してプロセスを実際に簡略化できます。簡単な解決策は次のとおりです。
// The output is a direction vector in OpenGL coordinate system:
// +X is Right on the screen, +Y is Up, +Z is INTO the screen
static Vector3 ToDirectionVectorGL(const Mat& rodrigues1x3) noexcept
{
Mat rotation3x3;
cv::Rodrigues(rodrigues1x3, rotation3x3);
// direction OUT of the screen in CV coordinate system, because we care
// about objects facing towards us - you can change this to anything
// OpenCV coordsys: +X is Right on the screen, +Y is Down on the screen,
// +Z is INTO the screen
Vec3d axis{ 0, 0, -1 };
Mat direction = rotation3x3 * Mat(axis, false);
// normalize to a unit vector
double dirX = direction.at<double>(0);
double dirY = direction.at<double>(1);
double dirZ = direction.at<double>(2);
double len = sqrt(dirX*dirX + dirY*dirY + dirZ*dirZ);
dirX /= len;
dirY /= len;
dirZ /= len;
// Convert from OpenCV to OpenGL 3D coordinate system
return { float(dirX), float(-dirY), float(dirZ) };
}
これを頭のポーズの推定に使用している場合は、ロドリゲスの1x3回転が{0,0,0}の周りに正しく形成されていることを確認してください。そうしないと、奇妙な結果が得られる可能性があります。