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

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

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

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

4339閲覧

OpenCVでの3次元回転行列

MOTOZOMBIE

総合スコア13

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/11/20 12:32

編集2018/11/20 12:49

3次元回転行列を用いて,Matに入ってる3*1行列を回転できるような関数は,OpenCVに存在していますか?
自力で関数を書いてみましたが.あっている気がしないので関数が用意されているのなら使ってみたいです.
環境

  • Opencv3.3
  • Visual Studio2015

このコードはOpenCVを使わず書いた関数です.

C++

1#define deg_to_rad(deg) deg * M_PI / 180 2 3struct matrix 4{ 5 double x; 6 double y; 7 double z; 8}; 9 10inline matrix rotation_mat_x(matrix vec, double theta) 11{ 12 matrix vec_tmp; 13 14 vec_tmp.x = vec.x; 15 vec_tmp.y = vec.y * cos(deg_to_rad(theta)) + vec.z * -sin(deg_to_rad(theta)); 16 vec_tmp.z = vec.y * sin(deg_to_rad(theta)) + vec.z * cos(deg_to_rad(theta)); 17 return vec_tmp; 18} 19 20// y 21inline matrix rotation_mat_y(matrix vec, double theta) 22{ 23 matrix vec_tmp; 24 25 vec_tmp.y = vec.y; 26 vec_tmp.x = vec.x * cos(deg_to_rad(theta)) + vec.z * -sin(deg_to_rad(theta)); 27 vec_tmp.z = vec.x * sin(deg_to_rad(theta)) + vec.z * cos(deg_to_rad(theta)); 28 return vec_tmp; 29} 30 31// z 32inline matrix rotation_mat_z(matrix vec, double theta) 33{ 34 matrix vec_tmp; 35 36 vec_tmp.z = vec.z; 37 vec_tmp.x = vec.x * cos(deg_to_rad(theta)) + vec.y * -sin(deg_to_rad(theta)); 38 vec_tmp.y = vec.x * sin(deg_to_rad(theta)) + vec.y * cos(deg_to_rad(theta)); 39 return vec_tmp; 40}

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

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

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

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

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

guest

回答1

0

ベストアンサー

cv::transform() が使えます。

変換前及び変換後は点の一覧で指定する必要があるため、変換する点が1点の場合でも std::vector<cv::Point2f> src = {{20, 20}} のようにしてください。

cpp

1#include <iostream> 2#include <opencv2/opencv.hpp> 3 4int main() 5{ 6 std::vector<cv::Point2f> src = {{20, 20}}, dst; 7 // 点 (30, 30) を中心に反時計回りに60°回転する回転行列を作成する。 8 cv::Mat M = cv::getRotationMatrix2D({50.f, 50.f}, 60., 1.); 9 std::cout << M << std::endl; 10 11 // 回転行列 M に src を適用し、結果を dst で得る。 12 cv::transform(src, dst, M); 13 14 // 結果を描画する。 15 cv::Mat img(100, 100, CV_8UC3, cv::Scalar(255, 255, 255)); 16 for (size_t i = 0; i < src.size(); ++i) { 17 std::cout << src[i] << "-> " << dst[i] << std::endl; 18 // 変換前の点を青で描画する。 19 cv::circle(img, src[i], 2, cv::Scalar(255, 0, 0), -1); 20 // 変換後の点を緑で描画する。 21 cv::circle(img, dst[i], 2, cv::Scalar(0, 255, 0), -1); 22 } 23 24 cv::imshow("image", img); 25 cv::waitKey(); 26} 27
[0.5000000000000001, 0.8660254037844386, -18.30127018922194; -0.8660254037844386, 0.5000000000000001, 68.30127018922192] [20, 20]-> [9.01924, 60.9808]

追記

変換は cv::transform() が使えますが、3次元回転行列を作成する関数はないので、オイラー角とかで適当に作ってください。

cpp

1#include <cmath> 2#include <iostream> 3#include <opencv2/opencv.hpp> 4 5/** 6 * @brief getRotationMatrix3D 7 * @param alpha x 軸周りの回転角度 8 * @param beta y 軸周りの回転角度 9 * @param gamma z 軸周りの回転角度 10 * @return 回転行列 11 */ 12cv::Mat getRotationMatrix3D(double alpha, double beta, double gamma) 13{ 14 // clang-format off 15 // X 軸周りの回転行列 16 cv::Mat R_x = 17 (cv::Mat_<double>(3, 3) << 1, 0, 0, 18 0, std::cos(alpha), -std::sin(alpha), 19 0, std::sin(alpha), std::cos(alpha)); 20 21 // Y 軸周りの回転行列 22 cv::Mat R_y = 23 (cv::Mat_<double>(3, 3) << std::cos(beta), 0, std::sin(beta), 24 0, 1, 0, 25 -std::sin(beta), 0, std::cos(beta)); 26 27 // Z 軸周りの回転行列 28 cv::Mat R_z = 29 (cv::Mat_<double>(3, 3) << std::cos(gamma), -std::sin(gamma), 0, 30 std::sin(gamma), std::cos(gamma), 0, 31 0, 0, 1); 32 // clang-format on 33 34 return R_z * R_y * R_x; 35} 36 37int main() 38{ 39 std::vector<cv::Point3f> src = {{20, 20, 20}}, dst; 40 cv::Mat M = getRotationMatrix3D(CV_PI / 3, CV_PI / 4, CV_PI / 2); 41 std::cout << M << std::endl; 42 43 // 回転行列を適用する。 44 cv::transform(src, dst, M); 45 46 // 結果出力 47 for (size_t i = 0; i < src.size(); ++i) { 48 std::cout << src[i] << "-> " << dst[i] << std::endl; 49 } 50}

イメージ説明

オイラー角とそれが表す回転行列

投稿2018/11/20 12:43

編集2018/11/20 15:52
tiitoi

総合スコア21956

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

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

MOTOZOMBIE

2018/11/20 13:23 編集

お早い返信ありがとうございます.2点質問します. 1)cv::Mat mat; // アフィン変換行列 に回転行列の式をいれるという認識であってますか? 2) 回転行列関数(Mat src, Mat dst, double xの回転角度, double yの回転角度, double zの回転角度); これで,回転行列が求まるようなみたいなものを想像していたのですが,流石にありませんか?
tiitoi

2018/11/20 14:54

cv::getRotationMatrix2D() で回転行列を作れるので、それを cv::transform() で使用する流れです。サンプルコードを追記しました。
MOTOZOMBIE

2018/11/20 15:25 編集

細かく分かりやすく書いてくださりありがとうございます. これはおそらく2次元行列ですよね! もしかすると,画像を扱うライブラリだから3次元行列の回転行列は用意されてないのでしょうか? あるのでしたら,是非3次元の方法を教えていただけないでしょうか? 自分も調べますので,自己解決したらまた返信いたします!
tiitoi

2018/11/20 15:43

追記しました。 3次元の回転行列は適当に作ってください。
MOTOZOMBIE

2018/11/20 15:49

ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問