回答編集履歴
2
d
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
|

|
71
69
|
|
72
|
-

|
70
|
+

|
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
|
+

|
86
|
+
|
87
|
+
上図青の点が `XY` です。
|
88
|
+
|
89
|
+
* 2. 原点中心に反時計回りに angle 度だけ回転する回転行列を作成する。
|
90
|
+
|
91
|
+
* 3. 点 `XY` に対して、アフィン変換を行う。
|
92
|
+
回転中心を `center` にする場合、-center だけ平行移動して、回転変換を行い、+center だけ平行移動して戻す。
|
93
|
+
|
94
|
+

|
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
answer
CHANGED
@@ -33,4 +33,40 @@
|
|
33
33
|
plt.show()
|
34
34
|
```
|
35
35
|
|
36
|
-

|
36
|
+

|
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
|
+

|
71
|
+
|
72
|
+

|