よくわからないですが,以前にあげた画像のフーリエ変換のページがアクセス多いので,その続きを書きましょう.
以前のページ
werry-chan.hatenablog.com
以前のページでは,具体的な画像に対して二次元フーリエ変換(2DFFT)を行っていました.
さらに,2DFFTの後にハイパスorローパスフィルタをかけることで成分分析を行いました.
応用編↓画像のフーリエ変換でSTM像を鮮明化
画像のフーリエ変換3: 走査トンネル顕微鏡(STM)でグラファイト(HOPG)を撮像し,FFTで鮮明化する. - werry-chanの日記.料理とエンジニアリング
さて,今回は2DFFTについて更なる理解を深めるために,単純なsin波画像を2DFFTしてみましょう.
今回使う画像はこちらです.
横向きにsin波が輝度で表されていますね.
画像の縦方向に関しては変化がなく,横方向に波が生じています.
これを2DFFTし,象限を入れ替え,パワースペクトル画像にするとこのようになります.
よーく見てもらうと真ん中あたりに線があります.
線は横方向に伸びていますね.
このように横方向の変化を持つ波画像を2DFFTすると,波の方向に応じた成分が表示されます.
詳しくは後に語るとして,その他の方向に関しても試してみましょう.
次は縦方向の波画像とその2DFFTパワースペクトル画像がこうなります.↓.
よーく見ると縦方向の線が見えます.
次に斜め方向の波画像(傾き30°)です.
画像の生成過程でアフィン変換という回転方法を使ったため,少し画像が劣化しましたが,まぁ良いでしょう.
斜め方向の波画像(傾き30°)と2DFFTパワースペクトル画像がこうなります.↓
アフィン変換による劣化の影響は,2DFFTで顕著に現れましたが,斜め30°方向に線が見えるかと思います.
このように,2DFFTによって画像中に含まれる単調な波の成分の方向が分かります.
さて,次に波の周波数を変えてみると,どのように2DFFTの結果が変わるか確認しましょう.
周波数1, 10, 100の横波画像を見てみます.
これらの2DFFTパワースペクト画像が以下のようになります.
かなり細い線なので,違いが分かりにくいですね.
30°傾いた画像で見てみると,画像の劣化のおかげか少し見やすくなっていますので,そちらも見てみましょう.
原点から傾き30°の線上にある輝度に注目しましょう.
まず基本として,象限入れ替えを行ったパワースペクトル画像は,原点周辺が低周波成分,辺縁部にかけて次第に高周波成分を示しています.
画像のフーリエ変換 - werry-chanの日記.料理とエンジニアリング
こちらでも図で説明がありますので参考に↑
ということは周波数1は,原点周辺が明るく,周波数が高くなるにつれて辺縁部が明るくなると予想できます.
しかながら,出力されたパワースペクトル画像からはこのような傾向は顕著ではありません.
その理由として,高調波(主成分の周波数の整数倍の波)の影響が存在します.
具体的に説明しましょう.
周波数50の画像をみてみましょう.
最も中央に近い白マークが周波数50の斜め波成分になります.
次にその隣に存在する白マークは周波数100,さらにその隣が周波数150と,次第に輝度が減少しながら高調波が表れます.
周波数100の2DFFTパワースペクトル画像の場合は,主成分が十分に大きいため,高調波が見えません.
周波数10の2DFFTパワースペクトル画像の場合は,拡大して確認すると,周波数10とその高調波の成分(20,30,...)が確認できます.
周波数1の2DFFTパワースペクトル画像の場合は,主成分と高調波の間隔が狭すぎるため,見た目上は直線になっています.
同様のことが横方向・縦方向の波でも拡大することで確認できます.
しかしながら縦方向・横方向の波は,ノイズのない画像のため,2 px幅の線で表されています.
かなり拡大しないと確認は難しいでしょう.
以上のようにして,2DFFTパワースペクトル画像の各点の表す意味が理解できたかと思います.
・中央からの方向は,波の進行方向を表す.
・輝度は,波の強度(振幅)を表している.
・FFTは,高調波成分も検出する.
簡単に試せるソースコードを置いておきますね.
import cv2 import numpy as np width,length = 800,800 #画像のサイズ img = np.zeros((width,length),dtype = np.uint8) #画像の生成 wave_number = 100 #周波数 sin_row = np.sin(np.linspace(-wave_number*np.pi, wave_number*np.pi, 800)) #sin波の生成 sin_row = np.array(np.abs(sin_row*200), dtype = np.uint8) #輝度値に変換(max200とした) #横波画像の生成 for i in range(len(img)): img[i] = sin_row #img = np.transpose(img) #縦波に変換 #アフィン変換 degree = 30 #回転角度(°) scale = 2 #拡大縮尺 trans = cv2.getRotationMatrix2D((int(width/2),int(length/2)), degree, scale) img = cv2.warpAffine(img, trans, (width,length)) cv2.imwrite("sin.jpg",img) #画像の二次元フーリエ変換 fimg=np.fft.fft2(img) fimg = np.fft.fftshift(fimg) #パワースペクトル化する fimg= np.array(10*np.log(np.abs(fimg)+1),dtype = np.uint8) print(np.where(fimg == np.max(fimg))) cv2.imwrite("fft.jpg",fimg)