空間周波数フィルタリング

# 空間周波数フィルタリング


# 基本関数

## min max scaler

```Python
import cv2
import numpy as np
import math

def _min_max(x):
    return (x - x.min()) / (x.max() - x.min())

```

## FFT
```Python
def make_FFT(img):
    # FFT
    dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
    # ゼロ周波数の成分を中心に移動
    dft_shift = np.fft.fftshift(dft)
    # パワースペクトル
    magnitude_spectrum = 20 * np.log((cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1])) + 1)

    return dft_shift, magnitude_spectrum

```

## Innverse FFT
```Python
def make_IFFT(fshift):
    #fshift is not magnitude
    # Inverse FFT
    f_ishift = np.fft.ifftshift(fshift)
    img_back = cv2.idft(f_ishift)
    img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])

    return img_back
```

## Masking parts
```Python
def make_mask(img, dft_shift, freq, LowPass=False):

    #円形のマスク画像を作ります
    rows, cols = img.shape
    crow, ccol = int(rows / 2), int(cols / 2)

    # mask radius r
    if rows >= cols:
        r = int(0.5 * freq * cols)
    else:
        r = int(0.5 * freq * rows)

    center = [crow, ccol]
    x, y = np.ogrid[:rows, :cols]

    #direct
    mask_area = np.sqrt((x - center[0]) ** 2 + (y - center[1]) ** 2) <= r

    if LowPass == False:
        # 内側 0, 外側 1
        mask = np.ones((rows, cols, 2), np.uint8)
        mask[mask_area] = 0
    elif LowPass == True:
        # 内側 1, 外側 0
        mask = np.zeros((rows, cols, 2), np.uint8)
        mask[mask_area] = 1

    #マスク処理

    fshift = dft_shift * mask
    mag = 20 * np.log((cv2.magnitude(fshift[:, :, 0], fshift[:, :, 1])) + 1)

    return fshift, mag


```

## テストコード
```Python
img = cv2.imread('./image/messi.jpg', 0)
print(img.max())
print(img.min())

#input image -> fft
dft_shift, img_mag = make_FFT(img=img)


#low pass filter
f_shift1, fshift_mask_mag1 = make_mask(img = img,dft_shift=dft_shift, freq=0.3, LowPass=True)
f_shift2, fshift_mask_mag2 = make_mask(img = img,dft_shift=dft_shift, freq=0.5, LowPass=True)

#band pass filter
f_shift3 = f_shift2 - f_shift1
fshift_mask_mag3 = fshift_mask_mag2 - fshift_mask_mag1

#IFFT
img_back1 = make_IFFT(fshift=f_shift1)
img_back2 = make_IFFT(fshift=f_shift2)
img_back3 = make_IFFT(fshift=f_shift3)


#Plot
cv2.imshow('original image', img)
cv2.imshow('fft image', (255*_min_max(img_mag)).astype(np.uint8))

cv2.imshow('masked image1', (255*_min_max(fshift_mask_mag1)).astype(np.uint8))
cv2.imshow('masked image2', (255*_min_max(fshift_mask_mag2)).astype(np.uint8))
cv2.imshow('masked image3', (255*_min_max(fshift_mask_mag3)).astype(np.uint8))

cv2.imshow('ifft masked_image1', (255*_min_max(img_back1)).astype(np.uint8))
cv2.imshow('ifft masked_image2', (255*_min_max(img_back2)).astype(np.uint8))
cv2.imshow('ifft masked_image3', (255*_min_max(img_back3)).astype(np.uint8))

cv2.waitKey(0)

```

# 結果

## Original Image
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/96f81195-dc89-af1b-3517-1b08b86ab95b.png)

## Frequency Domain
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/7f71d4e3-63a5-d48f-4bac-093fcf8e842e.png)

## BandPassFiltering
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/6c4c9d33-fd2f-6495-a871-8ccd17e04cec.png)

## BandPassFiltered Image
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/328b1fa9-4137-1e23-caa3-7beaf1562364.png)