numpyとopenCVを使った画像のフーリエ変換と逆変換

openCVを使い画像読み込み、fftで周波数データに変換。その後逆変換で元の画像に戻すテスト。

入力に使用する画像は↓。サイズは360×240。
input data to fft

まず画像入力、グレースケールで取り込む。

###########
# code 1
###########
import cv2
from PIL import Image

image = cv2.imread("mt_fuji.jpg", cv2.IMREAD_GRAYSCALE)
cv2.imshow("original",image)
cv2.waitKey(0)
cv2.destroyWindow()

実行すると元の画像がグレースケールで表示される。
imreadは引数2つ、1つ目は読み込みファイル、2つ目は読み込みオプションで以下3つ(1,0,-1でも指定可)。

  cv2.IMREAD_COLOR (or 1)
  cv2.IMREAD_GRAYSCALE (or 0)
  cv2.IMREAD_UNCHANGED (or -1)

続けてFFT実施

###########
# code 2
###########
import cv2
import numpy as np
from PIL import Image

image = cv2.imread("mt_fuji.jpg", cv2.IMREAD_GRAYSCALE)
#cv2.imshow("original",image)
#cv2.waitKey(0)
#cv2.destroyWindow()

fimage = np.fft.fft2(image)
print fimage
print fimage.shape

np.fft.fft2()は2次元FFT。
実行結果が下記。入力が360×240画像だったので、360×240のnumpy arrayで返ってくる。

[[ 1.20523050e+07      +0.        j -3.67019062e+05 +764482.77644721j
   8.97803335e+04 +528353.446206  j ... -8.56635235e+04 -151789.8195801 j
   8.97803335e+04 -528353.446206  j -3.67019062e+05 -764482.77644721j]
 [-5.06881547e+05-1884930.25115523j -4.50139049e+04 -190712.10861819j
  -1.76090294e+05 -185634.30113876j ...  8.13464047e+04  +33421.45807695j
   1.54174557e+05 +151124.32767313j  2.22512389e+05 +112510.91249437j]
 [-2.70716797e+05 +598066.58169905j  2.74010196e+05  +76140.89477773j
   3.81093895e+04 -142669.2043982 j ...  7.45069646e+04  -13227.88422994j
   2.39614427e+03 -107962.49955725j -1.21014694e+05  +16070.44342708j]
 ...
 [-4.93325081e+05+1019497.68318583j  1.10749640e+05 -185659.62071232j
  -2.02180759e+04 -244150.48215119j ... -7.68268395e+03   +7667.31543078j
   1.36815674e+05   -2094.526859  j  4.18478921e+04  -76427.43943856j]
 [-2.70716797e+05 -598066.58169905j -1.21014694e+05  -16070.44342708j
   2.39614427e+03 +107962.49955725j ... -5.75415408e+02  +50912.11759434j
   3.81093895e+04 +142669.2043982 j  2.74010196e+05  -76140.89477773j]
 [-5.06881547e+05+1884930.25115523j  2.22512389e+05 -112510.91249437j
   1.54174557e+05 -151124.32767313j ... -4.22761652e+04  +70475.447572  j
  -1.76090294e+05 +185634.30113877j -4.50139049e+04 +190712.10861819j]]
(240, 360)

変換結果をパワースペクトルで確認してみる。確認に使用したコードが下記。

###########
# code 3
###########
import cv2
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

image = cv2.imread("mt_fuji.jpg", cv2.IMREAD_GRAYSCALE)
#cv2.imshow("original",image)
#cv2.waitKey(0)
#cv2.destroyWindow()

fimage = np.fft.fft2(image)
#print fimage
#print fimage.shape

# Replace quadrant
# 1st <-> 3rd, 2nd <-> 4th
fimg =  np.fft.fftshift(fimage)
# Power spectrum calculation
mag = 20*np.log(np.abs(fimg))
plt.subplot(121)
plt.imshow(image,cmap = 'gray')
plt.subplot(122)
plt.imshow(mag,cmap = 'gray')
plt.show()

実行結果下記
input data to fft

最後に逆変換で元の画像に戻すコード。注意として変換後の結果には複素数成分が含まれているので、実部を取り出す処理が必要。またグレースケールで表示するために0-255階調への値調整が必要になる。

###########
# code 4
###########
import cv2
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

image = cv2.imread("mt_fuji.jpg", cv2.IMREAD_GRAYSCALE)
#cv2.imshow("original",image)
#cv2.waitKey(0)
#cv2.destroyWindow()

fimage = np.fft.fft2(image)
#print fimage
#print fimage.shape

ifimage = np.fft.ifft2(fimage)
# Extract real part
ifimage = ifimage.real
# Convert to 255 tones for gray scale
ifimage = np.uint8(ifimage)

cv2.imshow("fft and ifft",ifimage)
cv2.waitKey(0)
cv2.destroyWindow()

実行結果が下記グレースケールでもとの画像に戻ってきた。
results fft and inv fft

Read images using openCV, convert to frequency data with fft. And then back to the original image with reverse transformation.
Code 1 is reading image by gray scale.
Code 2 is 2D fft by numpy. Frequency distribution is returned.
Code 3 is checking Power spectrum.
Code 4 is invers Fourie by numpy.

numpy/opencv 2次元FFT

離散フーリエ変換(DFT)の高速化版アルゴリズムFFTをnumpyで試す。

import numpy as np

#read imgs 
image = cv2.imread("input.png", 0)

#FFT by numpy
fimage = np.fft.fft2(image)

fimage = np.log(np.abs(fimage) + 1)

fimage = fimage / np.amax(fimage) * 255
cv2.imwrite("result.png", fimage)

■結果
input.png
FFT input img
result.png
FFT results img

python用openCVのインストール@Centos7

python2.7でopenCVのインストールをしてみる。
OSはCentos7

コマンドは下記
%yum install opencv-python

実行してみる。入力データの各画素値をダンプするテスト。
ちなみに入力するデータは→

拡大するとこんな感じ↓の5×5ピクセル画像。

import cv2

img = cv2.imread('./test.bmp')

print(img)

■実行結果
[[[255 255 255]
[255 255 255]
[ 0 0 0]
[255 255 255]
[255 255 255]]

[[255 255 255]
[255 255 255]
[ 0 0 0]
[255 255 255]
[255 255 255]]

[[ 0 0 0]
[ 0 0 0]
[ 0 0 0]
[ 0 0 0]
[ 0 0 0]]

[[255 255 255]
[255 255 255]
[ 0 0 0]
[255 255 255]
[255 255 255]]

[[255 255 255]
[255 255 255]
[ 0 0 0]
[255 255 255]
[255 255 255]]]

255:白、0:黒
横走査を下から上に向かって行っている様子が分かる。