この記事では、Python版OpenCVとNumPyを用いてフーリエ変換とローパスフィルタを実装し、画像から輪郭を取り出す方法をソースコード付きで解説します。
ローパスフィルタ
ローパスフィルタとは、その名の通り、信号の低周波数成分のみを通過させます。
画像データの場合は、画素値の変化が小さい部分が低周波成分となります。(ノイズは高周波成分)
つまり、画像処理においてはローパスフィルタでノイズ除去などに利用できます。
– | 関連記事 |
---|---|
原理の詳細 | 【画像処理】フーリエ変換(DFT、FFT) |
画像のフーリエ変換 | 【Python/OpenCV】高速フーリエ変換で周波数領域に変換 |
今回は、Python+OpenCVを用いて画像をローパスフィルタに通しました。
– | 処理手順 |
---|---|
① | 高速フーリエ変換で画像データを空間領域から空間周波数領域に変換します。 |
② | 零周波数成分を中心に移動します。(空間周波数領域の中心ほど低周波数成分) |
③ | ハイパスフィルタで高周波成分のみを取り出します。(空間周波数領域の中心のデータは0に置換) |
③ | 高速逆フーリエ変換で空間領域に戻します。 |
ソースコード(Python3+OpenCV3)
サンプルプログラムのソースコードです。
# -*- coding: utf-8 -*- import numpy as np import cv2 def lowpass_filter(src, a = 0.5): # 高速フーリエ変換(2次元) src = np.fft.fft2(src) # 画像サイズ h, w = src.shape # 画像の中心座標 cy, cx = int(h/2), int(w/2) # フィルタのサイズ(矩形の高さと幅) rh, rw = int(a*cy), int(a*cx) # 第1象限と第3象限、第1象限と第4象限を入れ替え fsrc = np.fft.fftshift(src) # 入力画像と同じサイズで値0の配列を生成 fdst = np.zeros(src.shape, dtype=complex) # 中心部分の値だけ代入(中心部分以外は0のまま) fdst[cy-rh:cy+rh, cx-rw:cx+rw] = fsrc[cy-rh:cy+rh, cx-rw:cx+rw] # 第1象限と第3象限、第1象限と第4象限を入れ替え(元に戻す) fdst = np.fft.fftshift(fdst) # 高速逆フーリエ変換 dst = np.fft.ifft2(fdst) # 実部の値のみを取り出し、符号なし整数型に変換して返す return np.uint8(dst.real) def main(): # 入力画像を読み込み img = cv2.imread("input.png") # グレースケール変換 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) # ローパスフィルタ処理 himg = lowpass_filter(gray, 0.3) # 処理結果を出力 cv2.imwrite("output.png", himg) if __name__ == "__main__": main()
実行結果
サンプルプログラムの実行結果です。
■入力画像(左)と出力画像(右)
おすすめ記事
PythonでOpenCV入門 サンプル集
【Python】画像処理プログラミング入門
【画像処理入門】アルゴリズム&プログラミング
コメント