오늘은 영상(Image)을 구성하는 화소값들을 영상과 함께 도식적으로 표출하는 방법을 하나 소개하려고 합니다. 예를 들면 다음 그림과 같이, 영상을 구성하는 특정 부위의 화소들을 클로즈업하여 표출하면서 각 화소마다의 화소값들도 함께 수치로 나타내는 방식입니다.
물론 이와 같은 그림을 그리는 기능이 IDL에 디폴트로 내장되어 있지는 않습니다. 따로 코딩을 해줘야 하겠죠. 그렇기 때문에 이와 같은 그림을 그리기 위한 코딩의 방법은 여러가지가 있을 수 있겠지만, 오늘은 New Graphics 체계의 기능을 활용해보겠습니다. 물론 전통적인 Direct Graphics 체계에서도 얼마든지 구현이 가능지만, 아마 코드의 줄수가 조금은 더 늘어날 것 같습니다.
이번 예제에서 사용할 영상은 IDL의 설치 폴더에 기본적으로 제공되는 이미지 파일을 사용합니다. 이 파일은 IDL 설치 폴더의 examples/data라는 하위 폴더안에 있는 moon_landing.png라는 파일입니다. 다음과 같은 모습을 하고 있는 8비트 Grayscale 영상입니다.
먼저 다음과 같이 이미지 파일을 읽어서 img라는 2차원 배열로 만들고, 이 배열의 크기 및 화소값의 최소, 최대치를 표시해봅시다. 그러면 300X300의 화소 크기를 갖고, 0~255라는 화소값을 갖는(Byte Scale이 이미 되어 있는) 영상임을 알 수 있습니다.
imfile = FILEPATH('moon_landing.png', SUBDIR=['examples', 'data'])
img = READ_IMAGE(imfile)
HELP, img
PRINT, MIN(img), MAX(img)
그런데 이 영상의 300X300이라는 전체 화소값들 다 표출할 필요는 없겠지요. 영상의 일부 영역만 따로 추출하여 표출을 해야 좀 더 보기가 쉬울겁니다. 그래서 앞서 맨 앞에서 봤던 그림에서처럼 10X10의 크기를 갖는 일부 영역만 따로 뽑아서 작업을 해보겠습니다. 뽑아낼 일부 영역의 좌표는 X방향으로는 200~209, Y방향으로는 180~189로 하겠습니다. 그래서 다음과 같이 일부 영역의 위치에 해당되는 화소좌표값들을 x1, x2, y1, y2라는 변수로 지정하고, 이 영역을 따로 추출하여 sub_img라는 배열로 만듭니다.
x1 = 200
x2 = 209
y1 = 180
y2 = 189
sub_img = img[x1:x2, y1:y2]
sz = SIZE(sub_img, /DIM)
이제 본격적으로 그림을 좀 그려봅시다. WINDOW 함수로 적당한 크기의 그래픽 윈도우를 하나 띄우고, 우선 맛배기로 영상 전체를 표출해봅니다. 당연히 여기서는 IMAGE 함수가 사용됩니다. 그리고 전체 영상에서 우리가 추출하고자 했던 일부 영역의 위치를 나타내기 위하여 POLYGON 함수를 사용해보았습니다. 이렇게 그려진 붉은색 사각형을 보면 어느 부분을 추출하게 될지 한눈에 알 수 있겠지요. 이와 같은 과정을 거치면 다음과 같은 그림을 얻게 됩니다.
win1 = WINDOW(DIMENSIONS=[400, 400])
image = IMAGE(img, /CURRENT)
polygon = POLYGON([x1, x2, x2, x1], [y1, y1, y2, y2], COLOR='red', FILL_BACKGROUND=0, /DATA, /CURRENT)
이번에는 추출된 일부 영역의 영상 및 화소값들을 표출해봅시다. 즉, 맨 앞에서 봤던 것과 같은 그림을 만들어보는 작업입니다. 이를 위한 또 하나의 윈도우를 WINDOW 함수를 이용해서 가로방향으로 긴 형태로 만듭니다. 그리고 IMAGE 함수를 사용하여 일부 영역의 모습을 윈도우의 왼편에 표출합니다. 이왕이면 앞서 전체영상에서 이 일부 영역의 위치를 나타냈던 붉은색 사각형에 해당됨을 강조하기 위하여, POLYGON 함수로 붉은색 사각형을 표시해보았습니다. 여기까지만 작업을 하면 다음과 같이 윈도우의 왼편에만 일부 영역의 모습이 표출됩니다.
win2 = WINDOW(DIMENSIONS=[800, 400])
sub_image1 = IMAGE(sub_img, POSITION=[0.05, 0.05, 0.48, 0.95], /CURRENT)
polygon = POLYGON([0, sz[0], sz[0], 0], [0, 0, sz[1], sz[1]], COLOR='red', FILL_BACKGROUND=0, $
TARGET=sub_image1, /DATA, /CURRENT)
여기서 IMAGE 함수의 내용을 보면 윈도우상에서 영상의 위치를 POSITION 속성을 이용하여 잡고 있습니다. 물론 LAYOUT과 같은 속성을 이용해도 상관은 없습니다. 그리고 표출된 영상을 보면 화소 크기가 10X10밖에 안되기 때문에 화소 하나하나가 깍두기처럼 또렸한 사각형의 형태를 띄는 것이 보입니다. 여기서 다음과 같이 sub_image1의 INTERPOLATE라는 속성에 대하여 1이라는 값을 부여해봅시다. 그러면 다음과 같이 뭔가 좀 뭉개진듯한 느낌의 모습으로 나타납니다.
sub_image1.interpolate = 1
원래 IMAGE 함수가 영상을 표출할 때 Bilinear Interpolation을 하지 않는 것이 기본 설정입니다. 하지만 이와 같이 INTERPOLATE 속성을 활성화시키면 Bilinear Interpolation을 적용하여 영상을 표출한다는 것을 참고적으로 알아두시면 좋겠습니다.
이제는 윈도우의 오른편에도 그림을 좀 그려야겠지요. 먼저 다음과 같이 앞서 했던 것과 똑같은 방법으로 일부 영역을 오른편에 표출합니다. 이번에는 sub_image2라는 이름을 사용하였습니다.
sub_image2 = IMAGE(sub_img, POSITION=[0.52, 0.05, 0.95, 0.95], /CURRENT)
그 다음에는 약간의 트릭을 좀 써본 것인데, 먼저 각 화소 사이사이의 경계선을 그어줍니다. 이를 위하여 다음과 같이 X방향 및 Y방향에 해당되는 반복문을 사용하는데, POLYLINE이라는 함수를 사용하여 선을 그어준 것입니다. 여기서 sz는 앞서 일부 영역에 대하여 SIZE 함수를 사용하여 얻어낸, 일부 영역의 X, Y 방향의 화소 크기를 나타냅니다. 따라서 여기서는 [10, 10]이 됩니다.
FOR i = 0, sz[0] DO pline = POLYLINE([i, i], [0, sz[1]], TARGET=sub_image2, /DATA)
FOR i = 0, sz[1] DO pline = POLYLINE([0, sz[0]], [i, i], TARGET=sub_image2, /DATA)
그리고 마지막 과정으로서, 각 화소마다의 화소값을 숫자로 표출합니다. 이를 위하여 다음과 같이 X, Y 방향의 2중 반복문을 사용합니다. 반복문안에서는 먼저 각 화소값을 정수형태로 얻어서 이를 다시 문자값으로 변환하여 str이란 변수에 넣어줍니다. 바로 이어서 TEXT라는 함수를 사용하여 이 문자값을 해당 화소의 위치에 파란색(Blue)의 문자로 표시하게 됩니다. 이 과정까지 끝나면 다음과 같은 그림을 얻게 됩니다. 사실 맨 앞에서 같은 형태의 그림을 이미 봤으므로, 이번에는 문자들의 색상을 Indigo로 바꿔보았습니다.
FOR j = 0, sz[1]-1 DO BEGIN
FOR i = 0, sz[0]-1 DO BEGIN
str = STRTRIM(STRING(sub_img[i, j], FORMAT='(I5)'), 2)
tt = TEXT(i+0.5, j+0.5, str, TARGET=sub_image2, /DATA, FONT_SIZE=10, ALIGNMENT=0.5, $
VERTICAL_ALIGNMENT=0.5, COLOR='Indigo', /CURRENT)
ENDFOR
ENDFOR
이렇게 해서 영상의 화소값들을 좀 멋지게 표출하는 방법을 설명해보았습니다. 앞서 언급했듯이 코딩에 의한 작업이기 때문에 방법은 여러가지가 있을 수 있습니다. 그러한 여러가지 가능성들 중 하나를 제시한 것으로 생각하시면 되겠습니다. 여러분 각자 갖고 계신 이미지 파일을 이용하여 적용해보시기 바랍니다. 다만, 이 예제에서는 8비트의 Grayscale 영상, 즉 단색 영상을 대상으로 하였습니다. 만약 24비트 RGB 영상의 경우라면 하나의 화소에 대하여 화소값이 Red, Green, Blue 채널별로 존재하므로 이 예제코드를 바로 적용할 수는 없습니다. 약간의 수정이 필요하겠지요. 이 점 염두에 두시길 바랍니다. 어쨌든 오늘 소개된 예제 코드는 아래에 파일로 첨부합니다.
'IDL > New Graphics' 카테고리의 다른 글
NG에서 Erase 메서드의 사용 (0) | 2012.07.16 |
---|---|
플롯상의 각 점들을 서로 다른 색상으로 표출하는 방법 [1] (2) | 2012.07.02 |
SWx Monitor의 플롯 생성 루틴 소개 [2] (0) | 2011.12.19 |
SWx Monitor의 플롯 생성 루틴 소개 [1] (0) | 2011.12.15 |
New Graphics에서 사용 가능한 컬러 목록 보기 (버전 수정) (0) | 2011.11.28 |