IDL/Image Processing

부분 이미지에 별도의 컬러테이블을 적용하는 방법

이상우_idl 2013. 7. 29. 08:30
728x90
반응형

얼마전에 IDL/ENVI 유저그룹에 이런 질문이 올라왔었습니다. 이미지를 하나 그려놓고 그 일부영역에 해당되는 부분만 다른 컬러테이블을 적용하여 중첩 표출하는 것을 어떤 식으로 구현하는게 좋은가에 대한 질문이었는데요. 저도 처음에는 좋은 방법이 안떠오르다가 약간 요령을 사용하면 가능하다는 것을 알아냈습니다. 오늘은 그 방법을 소개해볼까 합니다.


해결방법은 그 '일부영역'의 형태에 따라 간단할 수도 있고, 약간의 트릭이 필요할 수도 있습니다. 기본적으로는 Direct Graphics 체계에서 TV명령을 잘 사용하면 됩니다. '일부영역'의 형태가 사각형이라면 상당히 쉽습니다. 먼저 설명을 위한 예제 이미지를 띄울텐데, 흑백 컬러테이블을 사용하면 다음 그림과 같습니다. 다만, 400X400의 크기를 갖는 원본 이미지상에서 '일부영역'은 크기가 200X200이고 그 위치는 화소단위로 (140, 90)이란 좌표에 있다고 가정해봅시다. 그러면 그 '일부영역'의 위치 및 크기는 그림상의 검은 사각형과 같습니다.


data = BYTSCL(HANNING(400, 400))

sz = SIZE(data, /DIM)

DEVICE, DECOMPOSED=0

WINDOW, 0, XSIZE=sz[0], YSIZE=sz[1], RETAIN=2

LOADCT, 0

TV, data

vtx = [140, 329, 329, 140, 140]

vty = [90, 90, 289, 289, 90]

PLOTS, vtx, vty, COLOR=0, /DEVICE



여기서는 이미지를 TV로 표출한 다음, '일부영역'의 사각형을 구성하는 꼭지점의 X, Y 좌표 정보들을 vtx, vty라는 배열로 만들고 PLOTS를 사용하여 윤곽선을 그려보았습니다. 그러면 이 '일부영역'을 다른 컬러테이블을 사용하여 표출하려면 어떻게 해야 할까요? 물론 원하는 컬러테이블을 먼저 불러와야겠죠. 그런 다음에는 TV 명령의 몇몇 인자값들을 명시해줌으로써 내가 원하는 위치에 원하는 이미지를 중첩하여 표출하면 됩니다. 그 방법은 아래와 같고, 그 결과는 아래 그림과 같습니다.


LOADCT, 70

TV, data[140:329, 90:289], 140, 90



우리가 TV나 TVSCL을 사용할 때 대개는 이미지 배열 자체만 인자로 사용을 하지만, 이와 같이 이미지 배열에 해당되는 인자들 뒤에 추가적으로 X, Y 좌표를 명시할 수 있습니다. 이미지를 표출할 때 그 위치를 명시해야 할 경우의 사용법입니다. 여기서는 원본 이미지 배열은 data상에서 '일부영역'에 해당되는 부분을 인덱싱을 한 다음, 위치를 지정하여 표출한 것입니다. 이와 같이 '일부영역'의 형태가 사각형일 경우에는 비교적 쉽게 처리가 가능합니다.


그런데 '일부영역'의 형태가 사각형이 아닌 다른 형태를 띄는 경우라면 어떻게 해야 할까요? 예를 들면, 평행사변형, 육각형, 타원형, 원형, 무정형(Free Hand) 등의 경우라면 위와 같은 방법으로는 해결이 안됩니다. TV, TVSCL은 오직 사각형으로 된 2차원 배열만을 인자로 받을 수 있기 때문입니다. 이 경우에는 먼저 그 '일부영역'의 형태에 해당되는 도형의 꼭지점 정보를 알고 있어야 합니다. 여기서는 비교적 간단한 예로서 육각형인 경우를 보겠습니다. 400X400의 크기를 갖는 원본 이미지상에서 이 육각형을 이루는 6개의 꼭지점들의 X, Y 좌표는 다음과 같다고 가정하면, 그 영역의 위치 및 모습은 아래 그림과 같습니다.


vtx = [100, 180, 260, 260, 180, 100, 100]

vty = [100, 80, 100, 260, 280, 260, 100]

PLOTS, vtx, vty, COLOR=0, /DEVICE



그러면 이 육각형의 내부를 어떻게 앞에서와 같이 내가 원하는 컬러테이블로 채워넣느냐가 관건인데요. 사실 여기서도 TV가 또 등장합니다. 바로 위에서 TV, TVSCL은 사각형으로 된 2차원 배열만을 인자로 받을 수 있다고 했는데, 그렇다면 TV는 무용지물 아닐까요? 그렇지는 않습니다. 사실 여기서 TV에 사용될 수 있는 2차원 배열의 경우는 그 크기에 별다른 제한은 없습니다. 따라서 여기서는 육각형인 '일부영역'을 1X1의 크기를 갖는 더 작은 '일부영역'들로 쪼개어서 작업을 하면 됩니다. 다만 이와 같은 작업을 모든 화소들에 대하여 반복적으로 수행해야 하므로, 반복문에 의한 반복작업이 필요하다는 점만 염두에 두면 됩니다.


그런데 한가지 걸림돌이 있습니다. 원본 이미지상의 모든 화소들에 대하여 각각의 화소가 이 육각형의 안에 있는지 바깥에 있는지를 체크를 하고, 안에 있는 경우에는 위와 같이 1X1 배열에 대한 TV 명령이 수행되어야 한다는 점입니다. 그래서 어떤 화소가 특정한 다각형의 안에 있느냐 바깥에 있느냐를 판단하는 루틴이 하나 필요합니다. 사실 이런 루틴이 IDL에 내장되어 있으면 좋은데, 제가 알기로는 기본 라이브러리에는 내장된 것이 없더군요. 그래서 이 작업을 위한 외부 라이브러리 프로그램을 하나 사용을 할까 합니다. 바로 그 유명한 David Fanning의 라이브러리에 있는 INSIDE라는 함수를 사용하면 됩니다. 이 함수에는 판단하고자 하는 화소의 X, Y 좌표, 그리고 다각형을 이루는 꼭지점들의 X, Y 좌표들이 차례로 인자로 사용됩니다. 따라서 이 함수를 사용하는 적절한 반복문을 만들면 다음과 같은 내용이 됩니다. TV가 어떻게 사용되었는지를 잘 눈여겨 보시기 바랍니다.


LOADCT, 70

FOR j = 0, sz[1]-1 DO BEGIN

  FOR i = 0, sz[0]-1 DO BEGIN

    result = INSIDE(i, j, vtx, vty)

    IF result THEN TV, data[i:i, j:j], i, j

  ENDFOR

ENDFOR


그리고 이 결과로 얻어지는 그림은 다음과 같습니다. 보시는 것처럼 원본 이미지상에서 육각형안에 해당되는 부분만 다른 컬러테이블로 표출이 된 상태입니다. 단, 바로 앞서 육각형의 윤곽선을 나타내기 위해서 사용했던 PLOTS 명령은 여기서는 사용을 안하는 것이 좋습니다. 기울어진 직선의 윤곽선을 따라 그 검은선의 흔적이 불필요하게 보일 수 있기 때문입니다.


사실 이 작업의 경우는 화소 하나하나마다의 반복문으로 수행이 될 수 밖에 없기 때문에, 다각형이 크고 그 안에 포함된 화소들의 갯수가 많을 경우에는 처리시간이 다소 걸릴 수 밖에 없다는 점을 유념할 필요가 있습니다. 어쨌든 이런 방법을 사용하면, '일부영역'에 해당되는 어떤 형태의 다각형이든지 그 꼭지점 정보들만 알면 얼마든지 작업이 가능합니다. 설명을 제가 DG 체계에서의 방법으로 소개를 했는데, 이 기법의 경우는 NG나 OG보다는 오히려 DG가 더 효율적인 것 같습니다. 물론 만약에 캡션이나 다른 작업들때문에 NG나 OG에서의 작업도 필요하다고 한다면, 위와 같은 결과를 이미지 파일로 저장해놓고 사용하는 것도 좋은 방법일 것으로 생각됩니다.


* 여기서 사용된 INSIDE라는 함수의 소스코드는 여기에 첨부하겠습니다. 이렇게 파일 하나만 제가 따로 첨부해서 올려도 별다른 문제는 없겠지요? 만약 원래 David Fanning의 Coyote 라이브러리를 사용중이신 분들의 경우는 굳이 이 파일을 받지 않으셔도 됩니다.


inside.pro


inside.pro
0.01MB
반응형