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

回答編集履歴

2

d

2019/06/13 14:42

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -37,8 +37,6 @@
37
37
 
38
38
  ## 追記
39
39
 
40
- ## 追記
41
-
42
40
  > これはどう解釈すればよいでしょうか。
43
41
 
44
42
  やっている処理は以下になります。
@@ -69,4 +67,87 @@
69
67
 
70
68
  ![イメージ説明](ef33c1acf89e383e5dea138494e56737.png)
71
69
 
72
- ![イメージ説明](3405c4f32133104771a1adc8712bd0d4.png)
70
+ ![イメージ説明](3405c4f32133104771a1adc8712bd0d4.png)
71
+
72
+ ## 追記
73
+
74
+ > 追加ですが、では以下のような配列を任意の点(配列と配列の間、Xで言えば6.2なども含める)を中心に任意の角度回転させた時、その配列の各点がどこに位置するかを表すような関数ってありますか?
75
+
76
+ 行列の各成分が回転後にどの位置に写ったか知りたいということでしょうか?
77
+ 一発でそのようなことができる関数はありませんが、行列の各成分の点に対して、「ある点を中心にある角度だけ回転するアフィン変換」を行えばよいと思います。
78
+
79
+ コードにすると以下のようになります。
80
+
81
+ * 1. 行列の各成分の点一覧 `XY` を作成する。
82
+ ただし、+0.5 して点が各成分の中心となるようにする。
83
+ 例えば、行列の (2, 1) 成分の点は (1.5, 2.5) になります。
84
+
85
+ ![イメージ説明](ddfbde8f968c00ff1b725df3d2811354.png)
86
+
87
+ 上図青の点が `XY` です。
88
+
89
+ * 2. 原点中心に反時計回りに angle 度だけ回転する回転行列を作成する。
90
+
91
+ * 3. 点 `XY` に対して、アフィン変換を行う。
92
+ 回転中心を `center` にする場合、-center だけ平行移動して、回転変換を行い、+center だけ平行移動して戻す。
93
+
94
+ ![イメージ説明](ddfbde8f968c00ff1b725df3d2811354.png)
95
+
96
+ 上図緑の点が回転中心、赤の点が変換後の点の位置です。
97
+
98
+ ```python
99
+ import matplotlib.pyplot as plt
100
+ import numpy as np
101
+
102
+ a = np.array([[0, 1, 2, 3],
103
+ [0, 1, 2, 3],
104
+ [0, 1, 2, 3]])
105
+
106
+ # 行列の各成分の点一覧を作成する。
107
+ rows, cols = np.indices(a.shape)
108
+ XY = np.column_stack((cols.ravel(), rows.ravel())) + 0.5
109
+
110
+ print(XY.shape) # (12, 2)
111
+ print(XY)
112
+ # [[0.5 0.5]
113
+ # [1.5 0.5]
114
+ # [2.5 0.5]
115
+ # [3.5 0.5]
116
+ # [0.5 1.5]
117
+ # [1.5 1.5]
118
+ # [2.5 1.5]
119
+ # [3.5 1.5]
120
+ # [0.5 2.5]
121
+ # [1.5 2.5]
122
+ # [2.5 2.5]
123
+ # [3.5 2.5]]
124
+
125
+ # 原点中心に反時計回りに angle 度だけ回転する回転行列を作成する。
126
+ def create_rotation_matrix(deg):
127
+ rad = np.deg2rad(deg)
128
+ return np.array([[np.cos(rad), -np.sin(rad)],
129
+ [np.sin(rad), np.cos(rad)]])
130
+
131
+ center = (1.2, 2.2) # 回転する中心
132
+ rot = create_rotation_matrix(deg=45.0)
133
+ # center 周りに回転させるので、
134
+ # -center だけ平行移動 → 回転 → +center だけ平行移動
135
+ new_XY = (XY - center).dot(rot) + center
136
+ print(new_XY)
137
+
138
+ # 元の点がどこに移ったか
139
+ for old, new in zip(XY, new_XY):
140
+ print(f"{old} -> {new}")
141
+ # [0.5 0.5] -> [-0.49705627 1.49289322]
142
+ # [1.5 0.5] -> [0.21005051 0.78578644]
143
+ # [2.5 0.5] -> [0.91715729 0.07867966]
144
+ # [3.5 0.5] -> [ 1.62426407 -0.62842712]
145
+ # [0.5 1.5] -> [0.21005051 2.2 ]
146
+ # [1.5 1.5] -> [0.91715729 1.49289322]
147
+ # [2.5 1.5] -> [1.62426407 0.78578644]
148
+ # [3.5 1.5] -> [2.33137085 0.07867966]
149
+ # [0.5 2.5] -> [0.91715729 2.90710678]
150
+ # [1.5 2.5] -> [1.62426407 2.2 ]
151
+ # [2.5 2.5] -> [2.33137085 1.49289322]
152
+ # [3.5 2.5] -> [3.03847763 0.78578644]
153
+ ```

1

d

2019/06/13 14:42

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -33,4 +33,40 @@
33
33
  plt.show()
34
34
  ```
35
35
 
36
- ![イメージ説明](c84d9974ad491961bc0c8f9da2bd2196.png)
36
+ ![イメージ説明](c84d9974ad491961bc0c8f9da2bd2196.png)
37
+
38
+ ## 追記
39
+
40
+ ## 追記
41
+
42
+ > これはどう解釈すればよいでしょうか。
43
+
44
+ やっている処理は以下になります。
45
+
46
+ 1. アフィン変換 (中心で回転) を行う。
47
+ 2. 値をスプライン補完で内挿する。
48
+ 3. 情報がない画素は外挿する。(デフォルトは0なので画像でいうと黒になる)
49
+
50
+ ndimage.rotate() の具体的な処理は Github のソースコードで確認できます。
51
+ [scipy/interpolation.py at v1.3.0 · scipy/scipy](https://github.com/scipy/scipy/blob/v1.3.0/scipy/ndimage/interpolation.py#L627-L754)
52
+
53
+ 数値で見るとなにが起こってるのかわかりづらいと思うので、画像で試してみると、実際 45°回転していることがわかります。
54
+
55
+ ```python
56
+ import numpy as np
57
+ import matplotlib.pyplot as plt
58
+ from scipy.ndimage import rotate
59
+
60
+ img = plt.imread("sample.jpg")
61
+
62
+ rotated = rotate(img, 45, reshape=False)
63
+
64
+ plt.imshow(img)
65
+ plt.show()
66
+ plt.imshow(rotated)
67
+ plt.show()
68
+ ```
69
+
70
+ ![イメージ説明](ef33c1acf89e383e5dea138494e56737.png)
71
+
72
+ ![イメージ説明](3405c4f32133104771a1adc8712bd0d4.png)