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

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

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

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

Q&A

解決済

1回答

1740閲覧

scipy.ndimage.interpolation.rotateについて

mega_ne

総合スコア16

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

0グッド

0クリップ

投稿2019/06/13 06:27

python

1import numpy as np 2import matplotlib.pyplot as plt 3from scipy.ndimage import rotate 4 5x = [i for i in range(20)] 6X = np.array(x).reshape(4,-1) 7Y = rotate(X, 90, reshape=False) 8 9print(X) 10print('\n') 11print(Y) 12 13plt.imshow(X) 14plt.colorbar() 15plt.show() 16 17plt.imshow(Y) 18plt.colorbar() 19plt.show()

配列Xを4×5の行列にreshapeして図を作成しました。
これをscipy.ndimage.interpolation.rotateで90度回転させたYの図も作成したのですが、Yの中身が理解できませんでした。
どのような回転が施されているのか教えていただきたいです。

X
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]

Y
[[ 0 5 11 17 0]
[ 0 4 10 16 0]
[ 0 3 9 15 0]
[ 0 2 8 14 0]]

はじめの配列Xより作成した図↓
はじめの配列

90度回転後の配列Yより作成した図↓
回転後の配列

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

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

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

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

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

guest

回答1

0

ベストアンサー

scipy.ndimage は主に画像を対象として回転させる関数ですので、行列を 90°ずつ回転させたい場合は、numpy.rot90 をお使いください。

numpy.rot90 — NumPy v1.15 Manual

python

1import matplotlib.pyplot as plt 2import numpy as np 3from scipy.ndimage import rotate 4 5X = np.arange(20).reshape(4, -1) 6# Y = rotate(X, 90, reshape=False) 7Y = np.rot90(X, k=1) # 反時計回りに90° (90*k°) 回転する。 8 9print(X) 10# [[ 0 1 2 3 4] 11# [ 5 6 7 8 9] 12# [10 11 12 13 14] 13# [15 16 17 18 19]] 14print() 15print(Y) 16# [[ 4 9 14 19] 17# [ 3 8 13 18] 18# [ 2 7 12 17] 19# [ 1 6 11 16] 20# [ 0 5 10 15]] 21 22plt.imshow(X) 23plt.colorbar() 24plt.show() 25 26plt.imshow(Y) 27plt.colorbar() 28plt.show()

イメージ説明

追記

これはどう解釈すればよいでしょうか。

やっている処理は以下になります。

  1. アフィン変換 (中心で回転) を行う。
  2. 値をスプライン補完で内挿する。
  3. 情報がない画素は外挿する。(デフォルトは0なので画像でいうと黒になる)

ndimage.rotate() の具体的な処理は Github のソースコードで確認できます。
scipy/interpolation.py at v1.3.0 · scipy/scipy

数値で見るとなにが起こってるのかわかりづらいと思うので、画像で試してみると、実際 45°回転していることがわかります。

python

1import numpy as np 2import matplotlib.pyplot as plt 3from scipy.ndimage import rotate 4 5img = plt.imread("sample.jpg") 6 7rotated = rotate(img, 45, reshape=False) 8 9plt.imshow(img) 10plt.show() 11plt.imshow(rotated) 12plt.show()

イメージ説明

イメージ説明

追記

追加ですが、では以下のような配列を任意の点(配列と配列の間、Xで言えば6.2なども含める)を中心に任意の角度回転させた時、その配列の各点がどこに位置するかを表すような関数ってありますか?

行列の各成分が回転後にどの位置に写ったか知りたいということでしょうか?
一発でそのようなことができる関数はありませんが、行列の各成分の点に対して、「ある点を中心にある角度だけ回転するアフィン変換」を行えばよいと思います。

コードにすると以下のようになります。

    1. 行列の各成分の点一覧 XY を作成する。

ただし、+0.5 して点が各成分の中心となるようにする。
例えば、行列の (2, 1) 成分の点は (1.5, 2.5) になります。

イメージ説明

上図青の点が XY です。

    1. 原点中心に反時計回りに angle 度だけ回転する回転行列を作成する。
    1. XY に対して、アフィン変換を行う。

回転中心を center にする場合、-center だけ平行移動して、回転変換を行い、+center だけ平行移動して戻す。

イメージ説明

上図緑の点が回転中心、赤の点が変換後の点の位置です。

python

1import matplotlib.pyplot as plt 2import numpy as np 3 4a = np.array([[0, 1, 2, 3], 5 [0, 1, 2, 3], 6 [0, 1, 2, 3]]) 7 8# 行列の各成分の点一覧を作成する。 9rows, cols = np.indices(a.shape) 10XY = np.column_stack((cols.ravel(), rows.ravel())) + 0.5 11 12print(XY.shape) # (12, 2) 13print(XY) 14# [[0.5 0.5] 15# [1.5 0.5] 16# [2.5 0.5] 17# [3.5 0.5] 18# [0.5 1.5] 19# [1.5 1.5] 20# [2.5 1.5] 21# [3.5 1.5] 22# [0.5 2.5] 23# [1.5 2.5] 24# [2.5 2.5] 25# [3.5 2.5]] 26 27# 原点中心に反時計回りに angle 度だけ回転する回転行列を作成する。 28def create_rotation_matrix(deg): 29 rad = np.deg2rad(deg) 30 return np.array([[np.cos(rad), -np.sin(rad)], 31 [np.sin(rad), np.cos(rad)]]) 32 33center = (1.2, 2.2) # 回転する中心 34rot = create_rotation_matrix(deg=45.0) 35# center 周りに回転させるので、 36# -center だけ平行移動 → 回転 → +center だけ平行移動 37new_XY = (XY - center).dot(rot) + center 38print(new_XY) 39 40# 元の点がどこに移ったか 41for old, new in zip(XY, new_XY): 42 print(f"{old} -> {new}") 43# [0.5 0.5] -> [-0.49705627 1.49289322] 44# [1.5 0.5] -> [0.21005051 0.78578644] 45# [2.5 0.5] -> [0.91715729 0.07867966] 46# [3.5 0.5] -> [ 1.62426407 -0.62842712] 47# [0.5 1.5] -> [0.21005051 2.2 ] 48# [1.5 1.5] -> [0.91715729 1.49289322] 49# [2.5 1.5] -> [1.62426407 0.78578644] 50# [3.5 1.5] -> [2.33137085 0.07867966] 51# [0.5 2.5] -> [0.91715729 2.90710678] 52# [1.5 2.5] -> [1.62426407 2.2 ] 53# [2.5 2.5] -> [2.33137085 1.49289322] 54# [3.5 2.5] -> [3.03847763 0.78578644]

投稿2019/06/13 06:42

編集2019/06/13 14:42
tiitoi

総合スコア21956

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

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

mega_ne

2019/06/13 07:13

任意の角度、例えば45度回転させると Y_45↓ [[ 0 0 4 10 0] [ 0 3 8 12 18] [ 1 7 11 16 0] [ 0 9 15 0 0]] となるのですが、これはどう解釈すればよいでしょうか。
tiitoi

2019/06/13 07:49

追記しました。 回転したあと、内挿 (スプライン補完) と外挿が行われた結果です。90°回転した場合も中心で回転したあとにこの処理が行われているので、numpy.rot90 のように元の行列と同じ数値が並んでいるわけではありません。
mega_ne

2019/06/13 13:25

なるほど... 単純に回転しているわけではないのですね。 勉強いたします。 ありがとうございます。 追加ですが、では以下のような配列を任意の点(配列と配列の間、Xで言えば6.2なども含める)を中心に任意の角度回転させた時、その配列の各点がどこに位置するかを表すような関数ってありますか? [[0,1,2,3,4] [0,1,2,3,4] [0,1,2,3,4] [0,1,2,3,4]]
tiitoi

2019/06/13 14:46

追記しました。 行列の各成分の座標を作成して、回転変換すると、回転後の座標になります。 ある点を中心に回転するのは、平行移動と回転行列をかけることで計算できます。 詳しくは以下参照 http://imagingsolution.blog.fc2.com/blog-entry-111.html
mega_ne

2019/06/14 11:53

追加での回答ありがとうございます。 丁寧に回答いただきありがとうございます。 アフィン変換というものを知らないのでこの機会に勉強しようと思います。 コードも参考にさせていただきます。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問