지난 회차 게시물에서는 IDL에서 이미지의 노이즈를 제거하는 기법들 중 컨볼루션(Convolution) 기반의 기법들을 예제와 함께 소개해보았습니다. 오늘은 FFT(Fast Fourier Transform) 기반의 노이즈 제거 기법들을 소개해보도록 하겠습니다. 일단 두 종류의 예제 이미지 데이터는 지난 회에서 사용했던 것을 똑같이 사용할 것입니다. 인위적으로 노이즈를 추가하여 예제 데이터를 생성하고 이를 표출하는 과정은 지난 회와 동일하지만 여기서도 다시 적어봅니다.
file = FILEPATH('moon_landing.png', SUBDIRECTORY=['examples', 'data'])
img0 = FLOAT(READ_PNG(file))
sz = SIZE(img0, /DIM)
noise = RANDOMN(-1, sz[0], sz[1], /UNIFORM)
img_a = img0
img_a[WHERE(noise GT .98)] = 255
xCoords = LINDGEN(sz[0], sz[1]) MOD sz[0]
yCoords = TRANSPOSE(xCoords)
noise = -SIN(xCoords*2)-SIN(yCoords*2)
img_b = img0+50*noise+100
HELP, img_a
PRINT, MIN(img_a), MAX(img_a)
HELP, img_b
PRINT, MIN(img_b), MAX(img_b)
win1 = WINDOW(DIMENSIONS=[sz[0]*2, sz[1]], /NO_TOOLBAR)
im1_a = IMAGE(img_a, MARGIN=0, /CURRENT, LAYOUT=[2, 1, 1])
im1_b = IMAGE(img_b, MARGIN=0, /CURRENT, LAYOUT=[2, 1, 2])
표출된 원본 이미지들의 모습은 다음 그림과 같습니다.
이와 같이 img_a는 마치 점과 같은 형체들이 이미지 전반에 걸쳐 노이즈처럼 퍼져있는 모습이고, img_b의 경우는 줄무늬와 같은 패턴의 노이즈가 이미지 전반에 걸쳐있는 모습입니다. 이제 이러한 두 종류의 이미지에 대하여 오늘은 FFT(Fast Fourier Transform)를 기반으로 한 기법들을 적용해봅시다.
첫번째로 먼저 밴드패스(Band Pass) 알고리즘을 기반으로 한 기법부터 보겠습니다. 이를 위해서는 IDL에서는 BANDPASS _FILTER 함수를 사용하면 되는데요. 사실 이 기법에 대하여 이해하려면 FFT에 관한 이해가 어느 정도는 필요합니다만 제가 여기서 FFT에 관한 원론적인 설명을 세세하게 하기는 힘들 것 같습니다. 다만 그냥 최대한 단순하게 얘기를 해보겠습니다. 우리가 보는 이미지는 공간 도메인(Spatial Domain) 상에 존재하는 데이터인데, 이미지 내에서는 전반적인 큰 규모의 패턴도 있고 작은 규모의 자잘한 패턴도 있습니다. 우리가 제거하고자 하는 노이즈(Noise)는 작은 규모의 자잘한 패턴에 속합니다. 그런데 FFT 기법을 이용하면 공간 도메인(Spatial Domain)의 이미지를 주파수 도메인(Frequency Domain)으로 옮기는 것이 가능합니다. 그러면 원래 이미지 내에서 큰 규모의 패턴은 저주파(Low Frequency)에 해당되고 작은 규모의 노이즈와 같은 패턴은 고주파(High Frequency)에 해당됩니다. 즉 주파수 도메인에서 저주파와 고주파 파트로 나눌 수가 있고, 이러한 주파수 도메인 상에서 고주파 파트에 대하여 제거 또는 감쇄와 같은 처리를 한 다음 다시 공간 도메인으로 역변환(Inverse Transform)을 시키는 것이 바로 FFT 기반의 노이즈 제거 기법의 전형적인 처리 방식입니다.
그러한 기법들 중 하나인 밴드패스(Band Pass) 알고리즘에서는 주파수 도메인 상에서 특정한 주파수 범위를 통과(Pass)시키고 나머지는 통과시키지 않습니다. 즉 특정 주파수 범위만 살리고 나머지는 제거한 상태에서 역변환 처리를 하는 기법이라고 보면 됩니다. 이러한 기법을 사용하려면 BANDPASS_FILTER 함수를 사용하면 되는데, IDL 도움말에서 이 함수에 관한 내용을 보면 밴드패스의 방식에 대한 도식적인 그림도 볼 수 있습니다. 여기서도 첨부해봅니다.
BANDPASS_FILTER 함수에서는 위 그림에 명시된 세 종류의 기법들이 각각 IDEAL, BUTTERWORTH, GAUSSIAN 키워드로 지원됩니다. 이것은 결국 통과(Pass)의 대상이 될 주파수 범위를 프로파일의 형태로 정의하는데 있어서 사용 가능한 유형들이라고 보면 됩니다. 디폴트 설정은 BUTTERWORTH=1입니다. 그리고 함수를 사용하는데 있어서는 통과(Pass)시킬 주파수 범위를 지정해주는 것도 당연히 필요합니다. 실제 처리 과정의 예제는 다음과 같습니다.
img_f_a = BANDPASS_FILTER(img_a, 0, 0.4, BUTTERWORTH=20)
img_f_b = BANDPASS_FILTER(img_b, 0, 0.4, BUTTERWORTH=20)
이와 같이 주파수 범위의 시작과 끝에 해당되는 주파수 값들을 인수로 부여해야 하는데 0~1로 normalize된 값을 사용해야 합니다. 여기서는 0~0.4의 범위가 되도록 하였는데, 저주파에 해당되는 형체는 그대로 살리고 중고주파에 해당되는 형체 즉 노이즈를 제거하기 위함입니다. 그리고 BUTTERWORTH 키워드의 값을 20으로 설정하였는데요. 이 값이 높으면 불연속성이 큰 Ideal 형태에 가깝고, 값이 낮으면 불연속성이 약한 Gaussian 형태에 가까와집니다. 물론 적정 주파수 범위 및 키워드 값의 설정 등을 위해서는 몇번의 시행착오가 필요하며, 위에 제시된 값들보다 더 나은 조합이 있을 수도 있습니다. 어쨌든 위와 같은 내용을 실행한 결과는 다음 그림과 같습니다.
이 그림을 보면 우측의 결과가 좀 더 나아보이고 좌측의 경우는 별다른 효과가 없는 것 같습니다. 만약 Ideal 방식으로 처리하려면 다음과 같이 /IDEAL 키워드를 사용하면 됩니다.
img_f_a = BANDPASS_FILTER(img_a, 0, 0.15, /IDEAL)
img_f_b = BANDPASS_FILTER(img_b, 0, 0.15, /IDEAL)
다만 이 경우에도 결과가 큰 차이는 나지 않는 것 같아서 결과 그림은 생략합니다. 그리고 만약 Gaussian 방식으로 처리하려면 다음과 같이 /GAUSSIAN 키워드를 사용하면 됩니다.
img_f_a = BANDPASS_FILTER(img_a, 0, 0.15, /GAUSSIAN)
img_f_b = BANDPASS_FILTER(img_b, 0, 0.15, /GAUSSIAN)
그리고 이 결과는 다음 그림과 같습니다.
앞서 BUTTERWORTH 키워드를 사용했을 때와 비교해보면 좌측의 결과가 좀 나아진 것 같긴 합니다만 그만큼 뭉개짐도 더 심해진 것 같습니다. 물론 세부 기법의 선택 및 값 설정에 의하여 다른 결과를 얻을 수도 있을 것입니다. 이 부분은 여러분이 직접 테스트해보시기 바랍니다.
그리고 방금 소개한 밴드패스(Band Pass) 알고리즘 대신 밴드제외(Band Reject) 알고리즘을 사용할 수도 있습니다. 밴드패스 알고리즘이 통과(Pass)시킬 주파수 범위를 지정하는 기법인 반면, 밴드제외 알고리즘은 말그대로 제외(Reject)시킬 주파수 범위를 지정하는 기법입니다. 따라서 서로 정반대의 방식이라고 보면 됩니다. 여기서 자연스럽게 두번째 기법을 소개하게 되었는데요. 이 밴드제외 기법을 사용하기 위해서는 BANDREJECT_FILTER 함수를 사용하면 됩니다. 만약 방금 전에 했던 Gaussian 방식의 처리를 BANDREJECT_FILTER 함수를 사용하여 밴드제외 기법으로 실행하려면 다음과 같이 하면 됩니다.
img_f_a = BANDREJECT_FILTER(img_a, 0.15, 1, /GAUSSIAN)
img_f_b = BANDREJECT_FILTER(img_b, 0.15, 1, /GAUSSIAN)
이것은 0.15~1의 주파수 범위를 제외(Reject)시키라는 의미입니다. 앞서 BANDPASS_FILTER 함수에서는 0~0.15의 주파수 범위를 통과(Pass)시키라고 했었는데, 결국 서로 똑같은 얘기입니다. 그래서 실제로 두 결과는 서로 똑같습니다. 따라서 BANDREJECT_FILTER 함수에 의한 결과 그림은 생략하겠습니다. 여러분이 한번 직접 비교해보시기 바랍니다.
세번째로 소개할 기법은 Butterworth 필터링 알고리즘을 사용하는 BUTTERWORTH 함수를 사용하는 방법입니다. 사실 Butterworth라는 용어 자체는 앞서 이미 밴드패스 및 밴드제외 기법에서도 언급을 하였는데요. 물론 전용함수인 BUTTERWORTH 함수는 밴드패스 또는 밴드제외와 같은 방식이 아니라 그냥 원론적인 방식으로 Butterworth 커널을 정의하고 이를 적용하여 처리합니다. 실제 처리 과정의 예제는 다음과 같습니다.
filter = BUTTERWORTH(sz[0], sz[1], CUTOFF=10)
img_f_a = FFT(FFT(img_a)*filter, /INVERSE)
img_f_b = FFT(FFT(img_b)*filter, /INVERSE)
결과를 얻기 위해서는 이와 같이 BUTTERWORTH 함수를 사용하여 원본 데이터와 동일한 크기의 커널을 생성하고, 이를 원본 이미지의 FFT 결과에 곱한 다음 역변환을 하는 일련의 과정이 필요합니다. 따라서 위와 같이 약간 복잡해 보일 수도 있는 내용이 되었습니다. 그리고 BUTTERWORTH 함수에서 사용 가능한 세부 키워드들이 더 있는데, 그 중 CUTOFF는 Butterworth 필터를 정의하는 수식에 등장하는 cutoff frequency에 해당됩니다. 다만 이 값의 절대 기준이 무엇인지는 저도 잘 모르겠는데, 일단 디폴트 값은 9입니다. 따라서 이를 기준으로 더 크거나 작게 조정하면서 최적의 값을 결정해야 할 것 같습니다. 여기서는 제가 10을 사용해보았는데, 결과는 다음 그림과 같습니다.
이 모습을 보면 양쪽 다 노이즈의 제거 효과는 어느 정도 있는 것 같지만 전반적인 뭉개짐 현상도 무시못할 수준인 것 같습니다. 물론 함수 내에서 지원되는 CUTOFF, ORDER 등의 키워드의 값들을 조정하여 좀 더 나은 결과를 얻을 수 있는 가능성도 있을 것입니다.
네번째이자 마지막으로 소개할 기법은 Hanning 필터링 알고리즘을 사용하는 HANNING 함수를 사용하는 방법입니다. HANNING 함수는 아마 이 블로그를 보시는 분들에게는 나름 익숙할 것 같은데, 제가 이미지 처리와 관련된 게시물을 작성할 때 가상의 예제 이미지 데이터를 생성하는데 있어서 자주 사용했던 함수이기도 합니다. 일단 실제 처리 과정의 예제는 다음과 같습니다.
filter = HANNING(sz[0], sz[1])
img_f_a = FFT(FFT(img_a, /CENTER)*filter, /INVERSE, /CENTER)
img_f_b = FFT(FFT(img_b, /CENTER)*filter, /INVERSE, /CENTER)
이 내용은 앞서 소개했던 BUTTERWORTH 함수를 사용하는 방식과 비슷하게 보이기도 합니다. HANNING 함수를 사용하여 원본 데이터와 동일한 크기의 커널을 생성하고, 이를 원본 이미지의 FFT 결과에 곱한 다음 역변환을 하는 일련의 과정이 필요하다는 점도 비슷합니다. 다만 최종 결과를 얻기 위한 FFT 변환 및 역변환의 과정에서 /CENTER 키워드가 사용되었는데, 이것은 Hanning 필터의 모양이 가운데가 높이 솟은 형태이기 때문에, 주파수 범위의 원점을 가운데로 이동시키는 것이 필요하기 때문입니다. 어쨌든 결과를 보면 다음 그림과 같습니다.
사실 결과가 양쪽 다 그리 만족스럽지는 않습니다. Hanning 필터에 의한 효과가 고주파 영역의 잡음을 제대로 제거하지는 못하고 그냥 어느 정도 완화시키는 정도에 불과했기 때문인 것으로 보입니다. 물론 노이즈의 형태에 따라서는 이러한 처리 방식이 효과적인 경우도 있지만, 지금과 같이 효과가 별로인 경우도 있습니다.
지금까지 FFT 기반의 노이즈 제거 방법들을 몇가지 소개해보았습니다. 이미 앞서 여러번 언급을 했듯이 노이즈의 형태에 따른 최적의 기법이 무엇이냐 그리고 특정 기법 내에서도 세부적인 인자값들을 어떻게 설정할 것이냐에 따라서 결과는 천차만별로 달라질 수 있습니다. 따라서 제거하고자 하는 노이즈의 형태에 맞는 기법들 찾고 만족스러운 결과를 얻기 위해서는 여러가지 방식으로 시행착오를 여러번 거쳐야 할 수도 있다는 것을 유념해야 할 것 같습니다.
IDL에서 이미지의 노이즈를 제거하는 기법들에 관한 내용은 이 정도로 소개를 마치겠습니다. 물론 나중에 또 적절한 관련 이슈가 또 생긴다면 여길 통해서 다시 소개해보도록 하겠습니다.
'IDL > Image Processing' 카테고리의 다른 글
RGB 이미지에 대한 처리 방법 (0) | 2022.03.21 |
---|---|
ROT 함수 소개 (0) | 2022.03.16 |
이미지에서 노이즈(Noise) 제거하기 [1] (0) | 2021.06.15 |
클리핑(Clipping) 기법의 이해와 응용 (0) | 2021.05.26 |
마스킹(Masking) 기법의 이해와 응용 (0) | 2021.05.17 |