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

回答編集履歴

3

追記

2021/12/07 07:20

投稿

fana
fana

スコア12229

answer CHANGED
@@ -73,4 +73,13 @@
73
73
 
74
74
  アフィン変換結果と変換前画像を重ねてみた表示結果:
75
75
  (描画した図形の真ん中が一致している)
76
- ![イメージ説明](5fac13b5a91edd70cf734a639bbc585f.png)
76
+ ![イメージ説明](5fac13b5a91edd70cf734a639bbc585f.png)
77
+
78
+ ※上記コードの `//Centerの位置が変わらないような並進成分を求めてマトリクスにセット` のところを,(このマトリクスの内容を前提として)手計算した結果で書くならば,
79
+
80
+ ```C++
81
+ M(0,2) = -Center.y * M(0,1);
82
+ M(1,2) = -Center.x * M(1,0);
83
+ ```
84
+
85
+ となりますが,汎用性を考えれば(?) 上記コードのように「中心」を変換した座標から並進量を求めるので良いかと(そこに圧倒的な計算時間を要するとかいうこともないでしょうから).

2

追記

2021/12/07 07:20

投稿

fana
fana

スコア12229

answer CHANGED
@@ -5,4 +5,72 @@
5
5
  OpenCVの関数名を記しておきます.
6
6
 
7
7
  * `getAffineTransform` : 3点の対応から 2x3 の変換マトリクスが得られます.
8
- * `warpAffine` : 2x3 の変換マトリクスを用いて画像を変換します.
8
+ * `warpAffine` : 2x3 の変換マトリクスを用いて画像を変換します.
9
+
10
+ ---
11
+
12
+ [追記]
13
+ とりあえず,ある座標の位置が変わらないような変形をするコードを書いてみました.
14
+ 参考になれば.
15
+
16
+ ```C++
17
+ int main()
18
+ {
19
+ const cv::Point TopLeft( 105, 55 );
20
+ const cv::Point BottomRight( 256, 178 );
21
+ const cv::Point Center = ( TopLeft + BottomRight ) * 0.5; //※変換の中心
22
+
23
+ cv::Mat Img( 240, 320 ,CV_8UC3 );
24
+ {//※元画像に,何かてきとーに「中心」がわかるような描画
25
+ Img = cv::Scalar( 96, 0, 0 );
26
+ cv::rectangle( Img, TopLeft, BottomRight, cv::Scalar(0,0,255) );
27
+
28
+ const cv::Point TopRight( BottomRight.x, TopLeft.y );
29
+ const cv::Point BottomLeft( TopLeft.x, BottomRight.y );
30
+ cv::line( Img, TopLeft, BottomRight, cv::Scalar(0,0,255) );
31
+ cv::line( Img, BottomLeft, TopRight, cv::Scalar(0,0,255) );
32
+
33
+ cv::circle( Img, Center, 6, cv::Scalar( 0,255,255 ), 1 );
34
+ cv::circle( Img, Center, 40, cv::Scalar( 0,255,0 ), 3 );
35
+ }
36
+ cv::imshow( "Img", Img );
37
+
38
+ //変換マトリクスを作る
39
+ cv::Matx<float,2,3> M = 0;
40
+ {
41
+ //てきとーに「せん断」になる感じの値
42
+ M(0,0) = 1; M(1,1)=1; //左側2x2部分対角は1
43
+ M(0,1) = 0.25; //せん断の成分(1)
44
+ M(1,0) = 0.5; //せん断の成分(2)
45
+ //Centerの位置が変わらないような並進成分を求めてマトリクスにセット
46
+ cv::Vec2f TransedCenter = M * cv::Vec3f( (float)Center.x, (float)Center.y, 1.0f );
47
+ M(0,2) = ( Center.x - TransedCenter(0) );
48
+ M(1,2) = ( Center.y - TransedCenter(1) );
49
+ }
50
+
51
+ //マトリクスMでアフィン変換
52
+ cv::Mat ResultImg;
53
+ cv::warpAffine( Img, ResultImg, M, cv::Size(Img.cols, Img.rows) );
54
+ cv::imshow( "Affine", ResultImg );
55
+
56
+ //元画像と重ねて表示してみる
57
+ cv::addWeighted( Img, 0.5, ResultImg, 0.5, 0, ResultImg );
58
+ cv::imshow( "Result", ResultImg );
59
+
60
+ //
61
+ if( cv::waitKey() == 's' )
62
+ {
63
+ cv::imwrite( "Img.png", Img );
64
+ cv::imwrite( "Result.png", ResultImg );
65
+ }
66
+ return 0;
67
+ }
68
+ ```
69
+
70
+ 変換前の画像 `Img` の表示結果:
71
+ (「ある座標」の位置がわかるような適当な図形が描画されている)
72
+ ![イメージ説明](29e0eed404f3c542a87a0259f711080e.png)
73
+
74
+ アフィン変換結果と変換前画像を重ねてみた表示結果:
75
+ (描画した図形の真ん中が一致している)
76
+ ![イメージ説明](5fac13b5a91edd70cf734a639bbc585f.png)

1

追記

2021/12/07 06:53

投稿

fana
fana

スコア12229

answer CHANGED
@@ -1,1 +1,8 @@
1
- まずは「アフィン変換 OpenCV」とかで検索してみては.
1
+ まずは「アフィン変換 OpenCV」とかで検索してみては.
2
+
3
+ ---
4
+
5
+ OpenCVの関数名を記しておきます.
6
+
7
+ * `getAffineTransform` : 3点の対応から 2x3 の変換マトリクスが得られます.
8
+ * `warpAffine` : 2x3 の変換マトリクスを用いて画像を変換します.