光学設計とその周辺、そしてたまに全く関係ないやつ

学んだことを書き留めていきたいと思いますが、ありふれたことを書いても人類の進歩に貢献しないので、専門的な事柄をメインにしたいと思います。なお私の専門とは光学設計とか画像処理とかです。

ベクトル画像の回転方法

以下の左図はベクトル場(y,x)のプロットです. 右図はこの図を45°回転させた様子です(表示範囲の違いのせいで見づらいですが).

この記事ではこんな感じでベクトル場を回転させて表示させる方法を紹介します. 記事にするほどのものではないでしょうに, と思うかもしれませんが意外と考える時間が必要だったので, 同じような境遇にいる方のためにこのページにメモします.

なぜてこずったか

単に画像を回転させる方法は広く知られてます. 要は


 
\begin{pmatrix}
x'\\
y'\\
1
\end{pmatrix}
=
\begin{pmatrix}
\cos{\phi}&-\sin{\phi}&0\\
\sin{\phi}&\cos{\phi}&0\\
0&0&1
\end{pmatrix}
\begin{pmatrix}
x\\
y\\
1
\end{pmatrix}
 \tag{1} \label{1}

の式で元画像(x,y)から \phiだけ(x',y')に回転させることができます.

でも今やりたいのはベクトル場の画像を回転させる方法で本質的には同じですが少し工夫が必要だということに気づきました. しかもベクトル場の回転とググっても大体出てくるのはベクトル場のrot演算, つまりベクトル解析や電磁気学で登場するあれだったりして, なかなか求めていた情報にたどり着けませんでした. もっとも最終的にたどり着いた資料はこの電磁気学の教科書の補足箇所だったわけですが....

本題

やることはべクトル画像を \phiだけ回転させる, または元の座標xyから \phi回転した別の座標x'y'で表示させることです.

最初の図を例として, つまり以下のベクトルで表されるベクトル画像を考えていきます.


\vec{L} = [ y, x ]  \tag{2} \label{2}

まず式(2)を以下のように単位基底ベクトルを使うとわかりやすくなります.


\vec{L} = y\vec{x} + x\vec{y}  \tag{3} \label{3}

ここで \vec{x}=[1,0] ,  \vec{y}=[0,1] です.

さてこれを \phi回転させたい場合基本的には先の式(1)の変換式を使います. ただしここで注意が必要なのはスカラー部分だけでなく, 単位ベクトルの部分もこの式を使ってxyからx'y'に変換する必要があります.

つまりスカラー部分の変換
 x=\cos{\phi}x'-\sin{\phi}y', y=\sin{\phi}x' + \cos{\phi}y'
に加えてベクトル部分の変換
 \vec{x} =\cos{\phi}\vec{x'} -\sin{\phi}\vec{y'},\vec{y}=\sin{\phi}\vec{x'} + \cos{\phi}\vec{y'}
も行います.

これを式(3)に代入し, 計算を進めます.


\vec{L} = (-\sin{\phi}x'+\cos{\phi}y')(\cos{\phi}\vec{x'} +\sin{\phi}\vec{y'}) +(\cos{\phi}x'+\sin{\phi}y')(-\sin{\phi}\vec{x'} +\cos{\phi}\vec{y'})
 = (-\sin{2\phi}x'+\cos{2\phi}y')\vec{x'}  +(\cos{2\phi}x'+\sin{2\phi}y')\vec{y'} \tag{4} \label{4}

計算自体はこれで終わりです.

例としてこの式に \phi=45°とし改めてxyで表すと


\vec{L} =  -x\vec{x}  +y\vec{y} \tag{5} \label{5}

となります. これを図にすると実際最初の右図のようになります.

内容は以上.

ベクトル画像の表示方法

これまで図で示してきたベクトル画像を作るPythonコードを以下示します(式(5)の場合). matplotlibのquiverという関数がキーです.

import numpy as np
import matplotlib.pyplot as plt

datanum=9
x = np.array([i-(datanum-1)/2 for i in range(datanum)])
y = np.array([i-(datanum-1)/2 for i in range(datanum)])

X, Y = np.meshgrid(x, y)

fig, ax = plt.subplots(figsize = (12, 7))

#最初の2つの引数が座標, 次の2つがベクトル.
ax.quiver(X, Y, -X, Y, linewidths=0.5, headlength=3, headaxislength=3)
 
ax.axis([-6, 6, -6, 6])

ax.set_xticks(x)
ax.set_yticks(y)

ax.grid(which = "major", axis = "x", color = "black", alpha = 1, linestyle = "-", linewidth = 1)
ax.grid(which = "major", axis = "y", color = "black", alpha = 1, linestyle = "-", linewidth = 1)

plt.show()