werry-chanの日記.料理とエンジニアリング

料理!コーディング!研究!日常!飯!うんち!睡眠!人間の全て!

画像のフーリエ変換

親戚の家でモフモフの猫に囲まれながらブログ書いてるウェリーちゃんです.

早く暖かいペット可アパートに引っ越して,毎日モフモフ生活したいです.

 

閑話休題

それでは,今回の題材は"画像のフーリエ変換"です.

フーリエ変換って何ぞ?って人に教えてあげます.

F(\xi)=\int^\infty_{-\infty}f(x)e^{-2\pi ix\xi}dx

式で表すとこういうことです.

すいません.フーリエ変換については,また今度説明します.

でも一応,非常に簡単にですが説明します.

元の関数f(x)を周波数成分ごとに分解し,周波数\xiの成分がF(\xi)になっているということを表しています.

詳しくは以下のリンクなどを参考にしてください.

フーリエ変換 - Wikipedia

【画像45枚あり】フーリエ変換を宇宙一わかりやすく解説してみる | ロボット・IT雑食日記

このページで画像のフーリエ変換について詳しく説明しています↓
werry-chan.hatenablog.com


応用編↓
画像のフーリエ変換3: 走査トンネル顕微鏡(STM)でグラファイト(HOPG)を撮像し,FFTで鮮明化する. - werry-chanの日記.料理とエンジニアリング


 

僕的には画像のフーリエ変換については

周波数領域における画像処理
↑このサイトが一番分かりやすいです.

 

まぁ今回の題材は"画像のフーリエ変換"なので,とりあえず一発フーリエ変換やってやりましょう.

あ,最後にpython3のソースコード載せます.


f:id:werry-chan:20181229133815j:plain
↑こいつは僕の自作キャラクター"目玉ハッカー君"です.

可愛いですね.ハッカー(ハッキングする奴)なので,悪魔っぽく角と尻尾つけて悪そうにしてやりました.めっちゃ可愛い.

話がそれましたね.

 

それでは,この"目玉ハッカー君"の画像を二次元フーリエ変換します.


f:id:werry-chan:20181229134358j:plain
フーリエ変換後の"目玉ハッカー君"画像

これがフーリエ変換画像になります.(正しくは,二次元フーリエ変換パワースペクトル画像です.)

なんかよく分からんが幾何学的な模様ができましたね.

これは画像の中心から外縁にかけて,次第に周波数成分の高いスペクトルを表してます.

通常この二次元フーリエ変換画像を扱う際は,第一象限と第四象限,第二象限と第三象限を入れ替えて扱います.


f:id:werry-chan:20181229215446j:plain
↑入れ替えたものがこれです.

 

フーリエ変換画像とその象限入れ替えを模式図にしたものは,以下のようになります.


f:id:werry-chan:20181229215844p:plain
【画像処理】フーリエ変換の原理・実装例 | アルゴリズム雑記 より引用画像です.

この図によると入れ替え後,真ん中に低周波成分が集まっているとなってますね.

入れ替え後のフーリエ変換画像の真ん中の低周波成分のみ抽出すると


f:id:werry-chan:20181229224608j:plain
フーリエ変換画像ではこのようになります.

それでは,この低周波数成分のみになったと思われるフーリエ変換画像を逆変換して再生してみましょう.


f:id:werry-chan:20181229224757j:plain
↑再生され,低周波数成分抽出された"目玉ハッカー君"画像

 

次は逆に高周波成分のみを抽出してみましょう.


f:id:werry-chan:20181229225347j:plain
↑高周波成分のみ抽出したフーリエ変換

これを逆変換により再生して


f:id:werry-chan:20181229225449j:plain
↑再生され,高周波成分のみ抽出された"目玉ハッカー君"画像

 

低周波成分と高周波成分って何を表してるの?と言う方のために,

これらの高周波成分抽出画像と低周波成分抽出画像を見比べて見よう.

 

"目玉ハッカー君"画像において,最も細かい描き込みの多い角の部分に注目してもらいたい.角の細かい模様を低周波成分では全く描けていないが,高周波成分では細かい描き込みがみられる.

また輪郭線のシャープさを比べると,低周波成分では輪郭線がボヤけて何重にも描かれているが,高周波成分ではかなり正確に元の輪郭線上をズレないでプロットしている.(画像の端に向かうと計算機上のフーリエ変換の癖で描画が甘くなる)

大方な見た目の点で言うと,低周波成分は全体的な雰囲気をボヤけた状態だが表せている.

 

などなどの点が比較によって見受けられる.

 

まぁ言いたいことを簡単にまとめると,”画像の高周波成分は細かい描き込みの成分”で”画像の低周波成分は大方の輪郭などの成分”と言うことだ.

 

応用面で言うと,フーリエ変換を使うことで細かい成分で構成されたノイズなどを排除できたり,輪郭線の抽出で画像処理に用いられてたりする.

 

ソースコード

import cv2
import numpy as np

#入力画像の読み込み
img=cv2.imread("werry-icon.jpg",0)#0はグレースケールで読み込み

#入力画像のサイズ取得
width,height=img.shape

#画像の二次元フーリエ変換
fimg=np.fft.fft2(img)

#パワースペクトル化する
#fimg= 20*np.log(np.abs(fimg))

#第1象限と第3象限,第2象限と第4象限の入れ替え
fimg = np.fft.fftshift(fimg)#高周波透過フィルタの場合,ここはコメントアウト

#入力画像と同じサイズの値0のnumpy array作成
dst=np.zeros(img.shape, dtype=complex)

#中心の値のみ透過(今回はローパス)
a=0.2#aは中心からのフィルターサイズ比率
dst[int(height*(0.5-a)):int(height*(0.5+a)), int(width*(0.5-a)):int(width*(0.5+a))] = fimg[int(height*(0.5-a)):int(height*(0.5+a)), int(width*(0.5-a)):int(width*(0.5+a))]

#再び第1象限と第3象限,第2象限と第4象限の入れ替え
dst= np.fft.fftshift(dst)#高周波透過フィルタの場合,ここはコメントアウト

#二次元逆フーリエ変換
dst = np.fft.ifft2(dst)

#実数部のみ抽出
low_img=np.uint8(dst.real)

#画像の書き込み
cv2.imwrite("werry-icon-low.jpg",low_img)