teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

5

d

2018/11/20 15:52

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -84,7 +84,6 @@
84
84
  int main()
85
85
  {
86
86
  std::vector<cv::Point3f> src = {{20, 20, 20}}, dst;
87
- // 点 (30, 30) を中心に60°回転する回転行列を作成する。
88
87
  cv::Mat M = getRotationMatrix3D(CV_PI / 3, CV_PI / 4, CV_PI / 2);
89
88
  std::cout << M << std::endl;
90
89
 

4

f

2018/11/20 15:52

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -96,4 +96,8 @@
96
96
  std::cout << src[i] << "-> " << dst[i] << std::endl;
97
97
  }
98
98
  }
99
- ```
99
+ ```
100
+
101
+ ![イメージ説明](a7f433d04bc1682c74c0cddf3004c47f.png)
102
+
103
+ [オイラー角とそれが表す回転行列](http://pynote.hatenablog.com/entry/math-euler-angles)

3

d

2018/11/20 15:45

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -36,4 +36,64 @@
36
36
  [0.5000000000000001, 0.8660254037844386, -18.30127018922194;
37
37
  -0.8660254037844386, 0.5000000000000001, 68.30127018922192]
38
38
  [20, 20]-> [9.01924, 60.9808]
39
+ ```
40
+
41
+ ----
42
+
43
+ ## 追記
44
+
45
+ 変換は cv::transform() が使えますが、3次元回転行列を作成する関数はないので、オイラー角とかで適当に作ってください。
46
+
47
+ ```cpp
48
+ #include <cmath>
49
+ #include <iostream>
50
+ #include <opencv2/opencv.hpp>
51
+
52
+ /**
53
+ * @brief getRotationMatrix3D
54
+ * @param alpha x 軸周りの回転角度
55
+ * @param beta y 軸周りの回転角度
56
+ * @param gamma z 軸周りの回転角度
57
+ * @return 回転行列
58
+ */
59
+ cv::Mat getRotationMatrix3D(double alpha, double beta, double gamma)
60
+ {
61
+ // clang-format off
62
+ // X 軸周りの回転行列
63
+ cv::Mat R_x =
64
+ (cv::Mat_<double>(3, 3) << 1, 0, 0,
65
+ 0, std::cos(alpha), -std::sin(alpha),
66
+ 0, std::sin(alpha), std::cos(alpha));
67
+
68
+ // Y 軸周りの回転行列
69
+ cv::Mat R_y =
70
+ (cv::Mat_<double>(3, 3) << std::cos(beta), 0, std::sin(beta),
71
+ 0, 1, 0,
72
+ -std::sin(beta), 0, std::cos(beta));
73
+
74
+ // Z 軸周りの回転行列
75
+ cv::Mat R_z =
76
+ (cv::Mat_<double>(3, 3) << std::cos(gamma), -std::sin(gamma), 0,
77
+ std::sin(gamma), std::cos(gamma), 0,
78
+ 0, 0, 1);
79
+ // clang-format on
80
+
81
+ return R_z * R_y * R_x;
82
+ }
83
+
84
+ int main()
85
+ {
86
+ std::vector<cv::Point3f> src = {{20, 20, 20}}, dst;
87
+ // 点 (30, 30) を中心に60°回転する回転行列を作成する。
88
+ cv::Mat M = getRotationMatrix3D(CV_PI / 3, CV_PI / 4, CV_PI / 2);
89
+ std::cout << M << std::endl;
90
+
91
+ // 回転行列を適用する。
92
+ cv::transform(src, dst, M);
93
+
94
+ // 結果出力
95
+ for (size_t i = 0; i < src.size(); ++i) {
96
+ std::cout << src[i] << "-> " << dst[i] << std::endl;
97
+ }
98
+ }
39
99
  ```

2

2018/11/20 15:43

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -8,16 +8,16 @@
8
8
 
9
9
  int main()
10
10
  {
11
- cv::Mat img(100, 100, CV_8UC3, cv::Scalar(255, 255, 255));
12
-
13
11
  std::vector<cv::Point2f> src = {{20, 20}}, dst;
14
12
  // 点 (30, 30) を中心に反時計回りに60°回転する回転行列を作成する。
15
13
  cv::Mat M = cv::getRotationMatrix2D({50.f, 50.f}, 60., 1.);
16
14
  std::cout << M << std::endl;
17
15
 
16
+ // 回転行列 M に src を適用し、結果を dst で得る。
18
17
  cv::transform(src, dst, M);
19
18
 
20
- // 変換前の点
19
+ // 結果を描画する。
20
+ cv::Mat img(100, 100, CV_8UC3, cv::Scalar(255, 255, 255));
21
21
  for (size_t i = 0; i < src.size(); ++i) {
22
22
  std::cout << src[i] << "-> " << dst[i] << std::endl;
23
23
  // 変換前の点を青で描画する。

1

d

2018/11/20 14:55

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -1,8 +1,39 @@
1
1
  [cv::transform()](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga393164aa54bb9169ce0a8cc44e08ff22) が使えます。
2
2
 
3
+ 変換前及び変換後は点の一覧で指定する必要があるため、変換する点が1点の場合でも `std::vector<cv::Point2f> src = {{20, 20}}` のようにしてください。
4
+
3
5
  ```cpp
6
+ #include <iostream>
4
- cv::Mat src; // 3x1行列
7
+ #include <opencv2/opencv.hpp>
8
+
9
+ int main()
10
+ {
11
+ cv::Mat img(100, 100, CV_8UC3, cv::Scalar(255, 255, 255));
12
+
13
+ std::vector<cv::Point2f> src = {{20, 20}}, dst;
14
+ // 点 (30, 30) を中心に反時計回りに60°回転する回転行列を作成する。
15
+ cv::Mat M = cv::getRotationMatrix2D({50.f, 50.f}, 60., 1.);
5
- cv::Mat dst; // 結果を格納する行列
16
+ std::cout << M << std::endl;
6
- cv::Mat mat; // アフィン変換行列
17
+
7
- cv::transform(src, dst, mat)
18
+ cv::transform(src, dst, M);
19
+
20
+ // 変換前の点
21
+ for (size_t i = 0; i < src.size(); ++i) {
22
+ std::cout << src[i] << "-> " << dst[i] << std::endl;
23
+ // 変換前の点を青で描画する。
24
+ cv::circle(img, src[i], 2, cv::Scalar(255, 0, 0), -1);
25
+ // 変換後の点を緑で描画する。
26
+ cv::circle(img, dst[i], 2, cv::Scalar(0, 255, 0), -1);
27
+ }
28
+
29
+ cv::imshow("image", img);
30
+ cv::waitKey();
31
+ }
32
+
33
+ ```
34
+
35
+ ```
36
+ [0.5000000000000001, 0.8660254037844386, -18.30127018922194;
37
+ -0.8660254037844386, 0.5000000000000001, 68.30127018922192]
38
+ [20, 20]-> [9.01924, 60.9808]
8
39
  ```