らんだむな記憶

blogというものを体験してみようか!的なー

FFTとIFFT

高速Fourier変換と逆高速Fourier変換を画像にかましてみる。

import sys
import numpy as np
from matplotlib import pyplot as plt

img = plt.imread(sys.argv[1], 1)
# FFT
f = np.fft.fft2(img)
# IFFT
img_back = np.fft.ifft2(f)
# complex -> uint8
img_back = img_back.real
img_back = img_back.astype(np.uint8)

plt.subplot(121), plt.imshow(img)
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img_back)
plt.title('IFFT after FFT'), plt.xticks([]), plt.yticks([])
plt.show()

以下のようにほぼ同じ画像になる。実際にはRGBの各チャンネルの中にちょっとだけ誤差はあるのだが。
f:id:derwind:20160130192049p:plain

また、imshow は pyplot にも cv2 にもあるが、pyplot.imshow で表示するなら pyplot.imread で画像を読みこむべきのようだ。というか混ぜると色相が変になった...。

理論上のFourie変換と逆変換ならキッチリ戻ってくるが、計算機での計算なので誤差が出る。虚部もあるし、実部も理論値からはちょっと揺らいでいるはずだ。ということで、ユニバーサル関数で良い感じにした。
NumPy配列を対象としたユニバーサル関数 | hydroculのメモにもあるが、mapとかイテレータみたいなもので各要素を変更したかったが、そういうことができそうにはなくて、大分考えてしまった...。最初は実部をとって整数に落として、0から255に収まるように補正をするようにforループを書いたが、まぁ、イマイチだね。そこまでやっても、numpy,array.astype で型変換を明示しないと、複素素型の配列のままで、pyplot.imshow に怒られた。面倒くさい。numpy は中身が C だから、こういう時に急に型というものを意識させられる。