이미 많이들 아시겠지만 IDL에서는 여러가지 다양한 이미지 처리 기능들을 지원하며, 제가 이 블로그를 통해서 이미 여러 차례 소개해드린 바 있습니다. 그런데 이러한 이미지 처리 기능들 중 상당수는(100%는 아니지만) 단색광 이미지 즉 배열 구조가 2차원인 경우에만 지원되는 경우가 꽤 많습니다. 예를 들어 어떤 이미지의 가로 및 세로 방향의 화소(Pixel) 크기가 각각 816 및 612일 경우, 그 이미지 데이터의 배열은 816x612의 2차원 구조를 갖는다고 볼 수 있습니다. 즉 이러한 배열은 각 화소마다 단일한 색상값을 갖는 단색광 이미지에 해당됩니다. 그런데 우리가 얻게 되는 여러가지 이미지 데이터들 중에서는 하나의 화소가 Red, Green, Blue 3종의 화소값들을 동시에 갖는 RGB 이미지인 경우도 꽤 많습니다. 우리가 스마트폰으로 촬영한 사진을 PC에서 파일로 받으면 그 안에 담긴 이미지 데이터도 이러한 형태인 경우가 대부분입니다. 이러한 이미지 데이터는 배열 구조상으로는 3차원 배열(예를 들면 3x816x612)이 됩니다. 왜냐하면 이미지를 구성하는 각각의 화소마다 3종의 색상값들(Red, Green, Blue)을 동시에 갖기 때문입니다. 그런데 IDL에서 지원되는 각종 이미지 처리 기능 및 함수들은 대부분 단색광 이미지 배열을 인수로 받아서 처리를 하도록 설계된 경우가 많습니다. 관련 예제를 살펴보기 위하여 다음과 같이 JPG 이미지 파일을 하나 열어서 간단한 처리를 해봅시다.
READ_JPEG, 'Boulder_2016.jpg', img
HELP, img
여기서는 사용된 Boulder_2016.jpg라는 JPG 파일은 아래에 첨부하였으므로 여러분들도 다운로드받아서 사용하시면 됩니다.
이 JPG 파일은 내부적으로 RGB 이미지 데이터를 포함하고 있습니다. 따라서 위와 같이 READ_JPEG 명령을 사용하여 이미지 데이터를 img라는 배열로 가져오고 HELP 명령을 사용하여 관련 정보를 출력해보면 그 내용은 다음과 같습니다.
IMG BYTE = Array[3, 816, 612]
이와 같이 3x816x612의 3차원 구조를 갖는 바이트형 값들로 구성된 배열임을 확인할 수 있으며 이는 RGB 이미지에 해당됩니다. 일단 이 원본 이미지 데이터를 표출만 먼저 해보면 그 과정 및 표출 결과는 다음과 같습니다.
sz = SIZE(img, /DIM)
win0 = WINDOW(DIMENSIONS=[sz[1], sz[2]], /NO_TOOLBAR)
i0 = IMAGE(img, MARGIN=0, /CURRENT)
이제 IDL에서 지원되는 이미지 처리 함수들 중 SMOOTH 함수를 img에 대하여 적용해보겠습니다. 참고로 SMOOTH 함수는 이미지에 대하여 저주파 필터(Low Pass Filter)를 적용하여 화소값들 사이의 차이를 감소시키는 역할, 즉 이미지 내의 형체들을 부드럽게 뭉개는(?) 역할을 합니다. 다음과 같이 대상 배열인 img에 대하여 필터링 커널의 크기를 9로 설정하여 비교적 많이 뭉개지도록 처리하고 그 결과를 img_f라는 배열로 얻고자 합니다.
img_f = SMOOTH(img, 9)
HELP, img_f
다만 안타깝게도 이렇게 처리하면 에러가 발생하면서 실행이 중단됩니다. 에러 메시지는 대략 다음과 같습니다.
% SMOOTH: Width must be nonnegative and smaller than array dimensions: <INT ( 9)>
장황하게 적혀있지만 이러한 에러가 발생한 근본적인 원인은, SMOOTH 함수에 인수로 부여된 배열 img의 구조가 3x816x612인데 3이라는 크기의 첫번째 차원에 대해서는 9라는 크기의 커널이 적용될 수 없기 때문입니다. 원래의 의도는 이미지 자체에 대하여 가로 및 세로 방향(두번째 및 세번째 차원)에 대하여 9라는 크기의 커널을 적용하고자 하는 것인데, 위와 같이 처리하면 크기가 3인 첫번째 차원에 대해서까지 커널링을 하라는 의미가 되므로 에러가 발생한 것입니다. 결국 이 작업이 우리의 의도대로 진행되려면 Red, Green, Blue 각 채널별 이미지에 해당되는 2차원 배열을 따로 추출하여 SMOOTH 함수에 의한 개별 처리를 한 다음 다시 RGB로 합성하는 과정이 필요합니다. 이 과정이 좀 번거로울 수는 있겠지만 순차적으로 소개해보면 먼저 다음과 같이 각 채널별 이미지 데이터를 2차원으로 추출합니다.
img_r = REFORM(img[0, *, *]); red channel
img_g = REFORM(img[1, *, *]); green channel
img_b = REFORM(img[2, *, *]); blue channel
HELP, img_r, img_g, img_b
이렇게 추출된 img_r, img_g, img_b는 각각 816x612의 2차원 구조를 갖는 배열이 됩니다. 여기서는 REFORM 함수도 사용하였는데, 그 이유는 REFORM 함수를 사용하지 않을 경우에는 크기가 1인 첫번째 차원이 찌꺼기처럼 남기 때문에 이를 제거하기 위한 것임을 유의해야 합니다. 그리고 다음 단계에서는 이렇게 추출된 각 채널별 이미지에 대하여 SMOOTH 함수에 의한 처리를 다음과 같이 해줍니다.
img_r_f = SMOOTH(img_r, 9)
img_g_f = SMOOTH(img_g, 9)
img_b_f = SMOOTH(img_b, 9)
이제 다음 단계에서는 각 채널별 처리 결과 배열들을 다시 RGB 3차원 배열로 합성합니다. 즉 SMOOTH 함수에 의한 처리가 완료된 RGB 이미지 배열을 최종적으로 얻기 위한 것인데 그 과정은 다음과 같습니다.
img_f = TRANSPOSE([[[img_r_f]], [[img_g_f]], [[img_b_f]]], [2, 0, 1])
HELP, img_f
이 과정은 다소 복잡하게 보일 수도 있습니다. 세부적으로 보면 먼저 각 채널별 처리 결과 2차원 배열들인 img_r_f, img_g_f, img_b_f를 3차원 배열로 합성합니다. 여기서는 꺽쇠 괄호가 사용된 방식에 유의해야 합니다. 그러면 여기까지의 결과 자체는 816x612x3의 구조를 갖게 됩니다. 다만 원본 RGB 이미지 배열이 3x816x612의 구조였기 때문에, 결과 배열도 동일한 구조를 갖도록 하기 위하여 TRANSPOSE 함수를 추가적으로 사용한 것이라고 보면 됩니다. 여기서는 TRANSPOSE 함수의 피벗(Pivot) 기능도 함께 사용되었습니다. 최종적인 결과는 img_f라는 배열로 얻어졌으며 HELP에 의하여 출력된 관련 정보를 보면 다음과 같습니다.
IMG_F BYTE = Array[3, 816, 612]
이와 같이 최종 결과인 img_f는 원본 데이터인 img와 동일한 배열 구조를 갖게 됩니다. 이제 img_f를 표출해서 결과를 확인하면 됩니다. 그 과정은 및 표출 결과는 다음과 같습니다.
win1 = WINDOW(DIMENSIONS=[sz[1], sz[2]], /NO_TOOLBAR)
i1 = IMAGE(img_f, MARGIN=0, /CURRENT)
이와 같이 우리가 의도했던대로 부드럽게 뭉개진 RGB 이미지를 결과로 얻었음을 확인할 수 있습니다. 정리를 해보면, 2차원 이미지에 대한 각종 처리 기법들을 3차원 RGB 이미지에 대하여 적용하고자 할 경우에는, 위의 예제에서와 같이 각 채널별 이미지 배열을 추출하여 개별적으로 처리를 한 다음 다시 합성하는 방식으로 결과를 얻으면 됩니다. 물론 이미지 처리 기능들 중 어떤 것들(예를 들면 UNSHARP_MASK 함수)은 위와 같은 복잡한 과정을 거칠 필요없이 RGB 이미지 배열을 그대로 받아서 처리할 수 있는 경우도 있긴 합니다. 그런 경우에는 그 기능을 바로 활용하시면 됩니다. 다만 RGB 3채널이 아니고 더 많은 채널들이 공존하는 다파장 또는 Hyperspectral 이미지 데이터를 다룰 경우에는 각 채널별 이미지를 분리하여 개별 처리하는 방식으로 작업을 하는 것이 필요할 수도 있음을 염두에 두는 것이 좋겠습니다.
'IDL > Image Processing' 카테고리의 다른 글
제임스웹 우주망원경(JWST) 데이터의 입수 및 표출 (0) | 2022.07.29 |
---|---|
COLOR_QUAN 함수의 사용법 (0) | 2022.04.22 |
ROT 함수 소개 (0) | 2022.03.16 |
이미지에서 노이즈(Noise) 제거하기 [2] (0) | 2021.07.01 |
이미지에서 노이즈(Noise) 제거하기 [1] (0) | 2021.06.15 |