Juhans
article thumbnail

푸리에 변환 (Fourier Transform)

푸리에 변환은 시간이나 공간에 대한 함수시간 또는 공간 주파수 성분으로 분해하는 변환을 말한다. 일반적으로 시간에 의존되는 함수 및 task에서 시간의 제약을 극복하기 위해 사용되는데, 영상처리 분야에서도 푸리에 변환을 통해 영상을 주파수로 변화시키고 그에 따른 전처리 결과를 얻을 수 있다.

 

자세한 푸리에 변환 원리는 아래를 참고하자.

https://ko.wikipedia.org/wiki/%ED%91%B8%EB%A6%AC%EC%97%90_%EB%B3%80%ED%99%98

 

푸리에 변환 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 사인파의 진폭이 다양한 방식으로 표현되어 있다. (1)은 일반적인 첨두치peak 진폭을, (2)는 최대치와 최저치 사이의 차이를, (3)은 제곱평균제곱근을, (4)는 주기

ko.wikipedia.org

 

OpenCV 푸리에 변환

영상처리에서의 푸리에 변환은 크게 두가지로 변환된다고 볼 수 있다. 고주파와 저주파인데 고주파는 픽셀의 밝기 차이가 극명하게 나타나는 위치에서, 저주파는 밝기 차이가 별로 없는 위치에서 변환된다. 즉, 고주파의 경우, 영상 내 객체의 경계면에서 가장 많이 나타나고 저주파는 밝기 차이가 별로 없어야 하므로 주로 배경에서 가장 많이 나타난다.

 

고주파, 저주파 중에서의 통과하는 주파수를 결정하여 필터를 만들기도 한다.

 

실습

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

img = cv2.imread('C:/Users/do/Documents/github/opencv_python/res/home.jpg',0)
f = np.fft.fft2(img)
magnitude_spectrum = 20*np.log(np.abs(f))

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

먼저 일반 이미지를 Fourier Filter Transform(FFT) numpy 함수(np.fft.fft2)를 사용해 주파수 영역으로 변환시킨다.

이 때 fft2함수에서는 흑백 이미지만을 받을 수 있으며, 결과 이미지의 크기를 정해줄 수도 있다. (두 번째 옵션 parameter)

 

위의 결과처럼 이미지가 주파수 영역으로 출력된다. 다만 주파수 영역이 0이 왼쪽 위 커질수록 다른방향으로 퍼지도록 영역이 생성되었기 때문에 이를 이미지의 원점으로 이동시키는 작업이 필요하다.

img = cv2.imread('C:/Users/do/Documents/github/opencv_python/res/home.jpg',0)
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
magnitude_spectrum = 20*np.log(np.abs(fshift))


plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

위와 같이 fft 모듈의 fftshift를 통해 주파수 영역이 원점부터 시작할 수 있도록 배치한다.

 

이후 고주파 필터 연산을 진행하면 아래와 같이 엣지부분이 강조된 이미지를 얻을 수 있다.

또 아래와 같이 저주파 필터를 사용해서 엣지성분이 빠지고 배경이 강조된 이미지를 얻을 수도 있다.

img = cv2.imread('C:/Users/do/Documents/github/opencv_python/res/home.jpg',0)
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]))

rows, cols = img.shape
crow,ccol = int(rows/2) , int(cols/2)

# create a mask first, center square is 1, remaining all zeros
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1

# apply mask and inverse DFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

 

고주파 필터(HPF), 저주파(LPF) 필터 원리

위에서 주파수 영역으로 만든 이미지를 보면 원점부터 가장자리로 퍼지며 점점 주파수가 높아지는 형태인데, 이 영역을 잘라내고 이미지와 조합 + 푸리에 역변환을 통해 필터를 사용하게 된다.

위치 변환한 주파수 영역 이미지

 


 

 

이미지 처리에서 자주 사용되는 레나 이미지를 사용해서 필터를 적용해보자. 

img = cv2.imread('lenna.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
height, width = gray.shape
dft = cv2.dft(np.float32(gray), flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)

먼저 위의 코드처럼 이미지를 불러와 grayscale로 변환하고 주파수 영역으로 변환하기 위해 푸리에 변환을 수행한다. (dft)

이 후 얻은 주파수 영역을 재배치한다. (fftshift). 이 재배치를 통해 주파수 영역이 원점부터 가장자리로 퍼지는 형태로 주파수가 증가하게 된다.

 

저주파 필터

row, col = int(height / 2), int(width / 2)

LPF = np.zeros((height, width, 2), np.uint8)
LPF[row - 50:row + 50, col - 50:col + 50] = 1
LPF_shift = dft_shift * LPF
LPF_ishift = np.fft.ifftshift(LPF_shift)
LPF_img = cv2.idft(LPF_ishift)
LPF_img = cv2.magnitude(LPF_img[:, :, 0], LPF_img[:, :, 1])
out = 20*np.log(cv2.magnitude(LPF_shift[:, :, 0], LPF_shift[:, :, 1]))

주파수 영역 이미지의 원점 부근은 주파수 영역이 낮은 저주파 영역이다. 이 부분을 구분지어주기 위해 row, col이라는 변수로 저주파 영역(window)를 설정하고 주파수 영역에서 이 영역만을 추출하여 역변환을 진행한다. (이 때 역변환 전에 ifftshift를 통해 역변환 이동을 수행해 원점에서 시작하는 주파수영역을 다시 왼쪽 위로 옮긴다.)

 

cv2.magnitude는 2차원 벡터의 크기를 계산해주는 함수이다. log를 취해주는 이유는 벡터의 크기가 매우 큰 값을 갖기 때문에 이미지로 출력해주기 위해서 log scale로 변환해주는 과정이라고 한다.

 

고주파 필터

HPF = np.ones((height, width, 2), np.uint8)
HPF[row - 50:row + 50, col - 50:col + 50] = 0
HPF_shift = dft_shift * HPF
HPF_ishift = np.fft.ifftshift(HPF_shift)
HPF_img = cv2.idft(HPF_ishift)
HPF_img = cv2.magnitude(HPF_img[:, :, 0], HPF_img[:, :, 1])
out2 = 20*np.log(cv2.magnitude(HPF_shift[:, :, 0], HPF_shift[:, :, 1]))

고주파 필터는 저주파와 반대로 중심 부근의 저주파영역을 제거한 주파수 영역 array와 곱해서 고주파 영역만을 살리고 푸리에 역변환(idft)을 통해 고주파 필터가 적용된 이미지를 얻는다.

 

결과적으로 위와 같은 필터를 거친 이미지들을 얻을 수 있다. out1은 역변환이동을 거치기 전의 주파수영역에서 저주파영역을 나타내고 out2는 고주파 영역을 의미한다.

LPF를 자세히 보면 원래 레나 이미지에서 엣지 부분이 모호해진 것을 볼 수 있으며, HPF에서는 레나 이미지에서 엣지 성분들만 추출된 것을 확인할 수 있다.

 

Reference

https://throwexception.tistory.com/823

 

opencv-python 튜토리얼 - 16. 푸리에 변환

푸링에 변환은 여러가지 필터의 주파수 특성을 분석하는데 필요합니다. 영상의 경우 2D 이산 푸리에 필터 (DFT)를 주파수 영역에서 분석하기 위해서 사용하는데요. 고속화된 알고리즘을 Fast Fourier

throwexception.tistory.com

https://cho001.tistory.com/170

 

[OpenCV] 영상처리 푸리에 변환을 이용한 저주파 필터(LPF) 고주파-필터HPF[퍼옴]

0. LPF(Low Pass Filter)/HPF(High Pass Filter)? 원래 HPF와 LPF는 전기회로에서 사용하는 용어입니다. 전기신호는 0과 1로 이루어진 신호입니다. 0이면 전기가 흐르지 않고, 1이면 전기가 흐르는 방식으로 모든

cho001.tistory.com

https://cho001.tistory.com/169?category=899067 

 

영상처리[주파수 관련+푸리에변환]

- 주파수 영역 처리 - * 푸리에 변환을 적용하여 공간 영역에서 주파수 영역으로 변환 * 주파수 영역에서 특정한 주파수 성분을 제거하거나 증폭 * 주파수 영역에서 공간 영역으로 역변환 - 공간

cho001.tistory.com

https://leechamin.tistory.com/266

 

[OpenCV] 04-11. Image Transforms in OpenCV

< Fourier Transform > " style="clear: both; font-size: 2.2em; margin: 0px 0px 1em; color: rgb(34, 34, 34); font-family: "Roboto Condensed", Tauri, "Hiragino Sans GB", "Microsoft YaHei", STHeiti, Sim..

leechamin.tistory.com

https://yuls-with-ai.tistory.com/m/229

 

[OpenCV with Python] 영상의 특징 추출 : 그래디언트와 에지 검출

그래디언트 Gradient 그래디언트는 함수 f(x,y)를 x축과 y축으로 각각 편미분(partial derivative)하여 벡터 형태로 표현한 것이다. x방향 미분과 y방향 미분을 따로 계산하고 벡터라는 것으로 묶은 것이

yuls-with-ai.tistory.com

 

'ML & DL' 카테고리의 다른 글

ANN (Artificial Neural Network) 인공신경망  (0) 2022.09.14