오늘은 이미지를 처리 및 표출하는 예제로서, 사이즈가 큰 이미지 데이터가 주어졌을 때 원본 이미지와 그 중 일부에 해당되는 영역만 확대된 부분 이미지를 나란히 배치하고 그 대상이 되는 영역의 위치를 순차적으로 변화시키는 예제를 살펴보고자 합니다. 예제로 사용할 이미지 데이터는 IDL의 설치 폴더에서 제공되는 boulder.tif라는 파일을 읽어서 배열로 가져오기로 합니다. 이 파일은 TIFF 형식이며 다음과 같이 READ_IMAGE 함수를 사용하여 읽으면 됩니다.
file = FILEPATH('boulder.tif', SUBDIRECTORY=['examples', 'data'])
data = READ_IMAGE(file)
HELP, data
이와 같이 데이터를 읽으면 1071x1390의 크기를 갖는 바이트형 배열인 data를 얻게 됩니다. 이제 그래픽 창을 띄우고 표출을 해야 하는데, 이번 작업에서는 가로 방향으로 긴 그래픽 창을 띄우고 왼쪽에는 원본 이미지를 그리고 오른쪽에는 부분 영역을 확대한 이미지를 표시하기로 합니다. 그 과정은 다음과 같이 시작합니다.
sx = 1000
sy = 500
win = WINDOW(DIMENSIONS=[sx, sy], /NO_TOOLBAR)
i0 = IMAGE(data, MARGIN=0.02, /CURRENT, LAYOUT=[2, 1, 1])
bszx = 200
bszy = 200
bpx = 100
bpy = 1100
box = POLYGON([bpx, bpx+bszx, bpx+bszx, bpx], [bpy, bpy, bpy+bszy, bpy+bszy], $
FILL_BACKGROUND=0, COLOR='yellow', THICK=2, /DATA)
여기서는 1000x500 크기의 그래픽 창을 띄우고 왼쪽 섹션에 원본 이미지 데이터인 data를 표출하였습니다. 그리고 POLYGON 함수를 사용하여 노란색 윤곽선의 박스를 삽입하였는데, 이것은 나중에 확대하게 될 부분 영역의 위치를 표시하기 위해서입니다. 여기서는 X 방향으로 100~299 그리고 Y 방향으로 1100~1299의 좌표 범위에 해당되는 200x200 크기의 부분 영역을 정의하였습니다. 그 다음에는 이 부분 영역에 해당되는 부분 배열을 추출하여 부분 이미지를 그래픽 창의 오른쪽에 표시하기 위하여 다음과 같은 과정을 추가합니다.
img = data[bpx:bpx+bszx, bpy:bpy+bszy]
i1 = IMAGE(img, MARGIN=0.02, /CURRENT, LAYOUT=[2, 1, 2])
이와 같이 부분 이미지에 해당되는 배열 img를 얻고 이를 이미지의 형태로 오른쪽에 표출하는 과정까지 실행하면 표출 결과는 다음그림과 같습니다.

일단 여기서는 부분 이미지의 크기가 200x200인데 표출될 그래픽 창은 더 크기 때문에 자연스럽게 확대된 모습으로 보이게 됩니다. 다만 확대된 이미지를 보면 픽셀들이 계단처럼 보이는데 이것은 이미지가 확대될 때 적용되는 디폴트 기법이 샘플링(Nearest Neighbor Sampling)이기 때문입니다. 만약 좀 더 부드러운 확대 이미지가 되도록 하려면 IMAGE 함수에서 INTERPOLATE 속성을 1로 설정하여 2차원 선형 내삽(Bilinear Interpolation) 기법이 적용되도록 하면 됩니다. 즉 바로 위에서 IMAGE 함수가 사용되었던 내용을 다음과 같이 변경하면 됩니다.
i1 = IMAGE(img, INTERPOLATE=1, MARGIN=0.02, /CURRENT, LAYOUT=[2, 1, 2])
이렇게 하면 표출 결과는 다음과 같습니다. 이제는 확대 이미지에서 픽셀들이 거칠게 보이지 않고 부드럽게 보이게 됩니다.

그러면 원본 이미지 및 확대 이미지는 이렇게 표시되도록 하고 다음 단계로 가서 부분 영역의 위치를 순차적으로 변경해봅시다. 즉 부분 영역의 위치가 순차적으로 변화하면서 왼쪽의 영역 박스 및 오른쪽의 확대 이미지도 함께 연동되어 변화하도록 해보려는 것입니다. 이를 위해서는 반복형 구문을 사용해야 합니다. 그러면서 박스 및 확대 이미지의 속성을 변화시키기 위하여 각 개체에 대하여 SetData 메서드를 사용하면 됩니다. 그 과정은 다음과 같습니다.
FOR j = 0, 360 DO BEGIN
box.SetData, [bpx, bpx+bszx, bpx+bszx, bpx]+j, [bpy, bpy, bpy+bszy, bpy+bszy]
i1.SetData, data[bpx+j:bpx+bszx+j, bpy:bpy+bszy]
ENDFOR
여기서는 부분 영역을 X축 방향으로 처음 위치로부터 1 픽셀씩 360회에 걸쳐 이동시켜본 것입니다. 그러면서 박스의 위치 좌표를 변화시키는 작업 및 부분 영역의 범위를 변화시키는 작업을 위하여 각각의 그래픽 개체인 box, i1에 대하여 SetData 메서드를 사용한 것을 주목하면 됩니다. 이러한 내용을 실행하면 그래픽 창이 뜬 상태에서 박스의 위치 및 확대 이미지가 순차적으로 변화하는 모습을 볼 수 있게 됩니다. 그 모습은 여러분이 IDL에서 직접 보셔야 합니다. 물론 각 회차마다 변화하는 모습을 캡쳐한 이미지들을 모아서 동영상 파일을 제작하는 것도 가능합니다. 참고로 IDL에서 동영상 파일을 만드는 방법에 관해서는 예전에 올렸던 관련 게시물들(링크 1, 링크 2)의 내용을 참조하시면 됩니다. 이 내용을 바탕으로 동영상 파일을 만들기 위하여 바로 위의 반복형 구문의 내용을 다음과 같이 수정해봅시다.
vfile = 'image_zoom.mp4'
fps = 60
oVid = IDLffVideoWrite(vfile)
vidStream = oVid.AddVideoStream(sx, sy, fps)
FOR j = 0, 720 DO BEGIN
box.SetData, [bpx, bpx+bszx, bpx+bszx, bpx]+j, [bpy, bpy, bpy+bszy, bpy+bszy]
i1.SetData, data[bpx+j:bpx+bszx+j, bpy:bpy+bszy]
cap = win.CopyWindow(WIDTH=sx)
time = oVid.Put(vidStream, cap)
ENDFOR
oVid.CleanUp
여기서는 IDLffVideoWrite 클래스를 사용하는 방식으로 처리하였습니다. 이와 같은 내용으로 변경하고 전체 과정을 다시 실행하면 image_zoom.mp4라는 동영상 파일을 얻을 수 있습니다. 다만 여기서는 반복의 회차가 720까지 가도록 하였고, 변수 fps를 60으로 정의함으로써 생성되는 동영상이 1초당 60프레임으로 돌아가도록 해보았습니다. 이와 같이 생성된 동영상은 아래 링크를 통하여 보실 수 있습니다.
앞서 제시된 예제에서는 단색광 이미지 즉 배열 구조가 2차원인 이미지 데이터를 대상으로 하였는데, RGB 이미지에 대해서도 동일한 방법론을 적용할 수 있습니다. 다만 RGB 이미지의 경우는 배열 구조가 3차원이라는 것을 감안하여 배열 인덱싱을 해야한다는 것만 유의하면 됩니다. 이러한 예제를 보기 위하여 이번에는 다음과 같이 새로운 이미지 파일을 대상으로 해봅시다. 즉 앞서 제시된 전체 과정에서 맨 처음 이미지 데이터를 가져오는 부분을 다음 내용을 대체합니다.
file = FILEPATH('ohare.jpg', subdir=['examples', 'data'])
READ_JPEG, file, data
HELP, data
여기서는 역시 IDL의 설치 폴더에서 제공되는 ohare.jpg라는 파일을 읽게 되는데, 이 이미지는 5000x5000의 크기를 갖는 RGB 이미지입니다. 그래서 위와 같이 읽으면 얻게 되는 data는 3x5000x5000의 구조를 갖는 바이트형 배열이 됩니다. 이제 이후의 과정은 앞서 제시되었던 내용과 거의 동일합니다. 다만 배열 구조가 3차원이 되었기 때문에 인덱싱하는 부분들만 그에 맞게 변경해줘야 합니다. 일단 그래픽 창을 띄우고 표출하는 과정은 다음과 같습니다.
sx = 1000
sy = 500
win = WINDOW(DIMENSIONS=[sx, sy], /NO_TOOLBAR)
i0 = IMAGE(data, MARGIN=0.02, /CURRENT, LAYOUT=[2, 1, 1])
bszx = 400
bszy = 400
bpx = 3200
bpy = 4100
box = POLYGON([bpx, bpx+bszx, bpx+bszx, bpx], [bpy, bpy, bpy+bszy, bpy+bszy], $
FILL_BACKGROUND=0, COLOR='yellow', THICK=2, /DATA)
img = data[*, bpx:bpx+bszx, bpy:bpy+bszy]
i1 = IMAGE(img, INTERPOLATE=1, MARGIN=0.02, /CURRENT, LAYOUT=[2, 1, 2])
여기서는 원본 이미지 배열인 data로부터 부분 영역에 해당되는 이미지 배열 img를 추출하는데 있어서 3차원 배열이라는 특성에 맞게 인덱싱된 것을 유의하면 됩니다. 일단 여기까지의 과정에 의하여 표출된 모습은 다음 그림과 같습니다.

그리고 바로 뒤에 이어지는 반복형 구문에 의한 변화 및 동영상 캡쳐의 과정에서도 이러한 부분만 유의하여 변경해주면 됩니다.
vfile = 'image_zoom.mp4'
fps = 60
oVid = IDLffVideoWrite(vfile)
vidStream = oVid.AddVideoStream(sx, sy, fps)
FOR j = 0, 1080 DO BEGIN
box.SetData, [bpx, bpx+bszx, bpx+bszx, bpx]+j, [bpy, bpy, bpy+bszy, bpy+bszy]
i1.SetData, data[*, bpx+j:bpx+bszx+j, bpy:bpy+bszy]
cap = win.CopyWindow(WIDTH=sx)
time = oVid.Put(vidStream, cap)
ENDFOR
oVid.CleanUp
이러한 전체 과정을 실행하면 앞선 예제에서와 마찬가지로 mp4 형식의 동영상 파일을 얻게 됩니다. 다만 여기서는 반복의 회차가 1080까지 가도록 하였고, 변수 fps를 60으로 정의함으로써 생성되는 동영상이 1초당 60프레임으로 돌아가도록 해보았습니다. 이와 같이 생성된 동영상은 아래 링크를 통하여 보실 수 있습니다.
* 이 글이 도움이 되었다면 게시물에 대하여 공감 버튼(하트 모양) 클릭 및 블로그 구독도 해주시면 더 큰 힘이 됩니다. 감사합니다.
'IDL > Image Processing' 카테고리의 다른 글
| 감마 보정 (Gamma Correction) [2] (1) | 2026.01.15 |
|---|---|
| 감마 보정(Gamma Correction) [1] (1) | 2026.01.14 |
| COLORTABLE 함수를 이용한 컬러테이블의 생성 [3] (0) | 2024.09.12 |
| COLORTABLE 함수를 이용한 컬러테이블의 생성 [2] (0) | 2024.09.03 |
| MORPH_OPEN 및 MORPH_CLOSE 함수 소개 (0) | 2024.08.08 |