IDL/Image Processing

불규칙 격자 2차원 데이터의 이미지 표출에 관하여 [2]

이상우_idl 2018. 12. 4. 15:56
728x90
반응형

* 지난 회 게시물에서 계속 이어집니다.


지난 회에는 격자점들 사이의 간격이 일정하지 않은 2차원 데이터를 NG 체계에서 IMAGE 함수를 사용하여 이미지의 형태로 표출하는 과정을 살펴보았습니다. 이 예제에서 원본 데이터는 10x16의 형태인데 IMAGE 함수에 의한 표출 과정에서 내부적으로 100x100의 형태로 변환되어 표출되는 것을 확인하였습니다. 그런데 내부적으로 변환된 데이터의 크기는 항상 일정하진 않습니다. 지금의 예제에서는 100x100이지만 원본 데이터의 크기가 다를 경우에는 변환된 데이터의 크기도 달라질 수 있습니다. 중요한 것은 변환 데이터의 크기를 내가 직접 설정하지는 못합니다. IMAGE 함수가 내부적으로 알아서 적당한(?) 크기로 설정한 채로 진행됩니다. 따라서 내부적으로 내정된 크기가 아닌 내가 원하는 크기로 변환되어 표출되도록 하는 것이 필요할 수 있습니다. 즉 100x100이 아니라 예를 들어 300x600 또는 500x450 등 내가 직접 지정한 크기로 변환되어 표출되도록 하려면 어떻게 해야 할까요? 사실 안타깝게도 이러한 처리 방식을 IMAGE 함수가 직접적으로 지원하지는 않습니다. 따라서 이를 위해서는 별도의 데이터 변환 과정을 따로 추가해야 합니다. 즉 원본 데이터인 2차원 배열을 내가 직접 지정하는 격자 체계 기반으로 변환하는 과정이 따로 더 필요하다는 얘기가 됩니다. 따라서 이제 핵심은 이러한 변환 과정을 어떻게 처리할 것이냐의 문제가 됩니다.


사실 이것이 생각만큼 간단한 일은 아니긴 합니다. 물론 간단하게 생각해보면 배열의 차원은 유지한 채 각 차원별 크기를 바꾸는 문제라고 볼 수도 있습니다. 예를 들어 10x16의 형태인 2차원 배열을 500x450의 형태로 변환하는 경우를 한번 가정해보면, 당장 떠오를만한 관련 기능으로는 아마 CONGRID 또는 REBIN 등의 내장함수들을 고려해볼 수도 있습니다. 그런데 지금의 상황은 CONGRID, REBIN 등과 같은 함수들로는 해결하기가 매우 어렵습니다. 왜냐하면 원본 데이터를 구성하는 10x16 형태의 2차원 배열의 격자점들의 분포 간격이 일정하지 않기 때문입니다. CONGRID 또는 REBIN 등의 함수는 격자점 간격이 일정한 경우에만 제 역할을 합니다. 따라서 불규칙한 간격으로 격자점들이 분포할 경우에 대해서도 적용이 가능한 기능을 사용해야 하는데, 제가 이 블로그에서 소개한 바 있는 GRIDDATA라는 함수가 나름 적절한 선택일 것 같습니다(관련 게시물 1, 게시물 2). 물론 관련 게시물들에서 언급이 되어있듯이 이 함수는 불규칙한 격자 분포를 하는 데이터를 규칙 격자화하는 역할을 합니다. 이 과정에서 다양한 내삽 기법들의 적용이 가능한데, 이러한 내삽 과정에 있어서 어떤 알고리즘을 사용하느냐에 따라 여러가지 사용 방법들이 존재합니다. 따라서 일괄적으로 간단하게 얘기하긴 좀 어렵지만, 일단 이 예제에서는 Delaunay 삼각법 기반의 선형(Linear) 내삽 기법을 사용하는 경우로 한정짓도록 하겠습니다. 그러면 어차피 중복이긴 하지만 온전한 설명을 위하여 예제 데이터를 생성하는 부분부터 다시 보겠습니다. 그 내용은 다음과 같습니다.


xg = [100, 103, 108, 110, 114, 122, 128, 135, 144, 150]*1.0

yg = [25:70:3.0]

xn = N_ELEMENTS(xg)

yn = N_ELEMENTS(yg)

data = HANNING(xn, yn)*100

HELP, data, xg, yg


그런데 GRIDDATA 함수를 사용하기 위해서는 별도의 처리 과정이 추가로 필요합니다. 왜냐하면 위의 예제 데이터의 경우 data는 10x16의 형태를 갖는 2차원 배열이고, xg와 yg는 각각 10개 및 16개의 값들로 구성된 1차원 배열입니다. 그런데 이 상태로 GRIDDATA 함수에 바로 투입하면 안됩니다. GRIDDATA에 투입되는 필수 인수들은 배열 구조 및 원소 갯수 등이 모두 동일해야 합니다. 즉 data라는 배열이 2차원이라면 xg와 yg도 그에 대응하여 동일한 형태의 2차원 배열이 되어야 하는데, 실제로는 아직은 그렇지가 않은 상황입니다. 따라서 이를 위하여 다음과 같은 과정이 추가적으로 필요합니다.


xg_2d = xg#REPLICATE(1., N_ELEMENTS(yg))

yg_2d = REPLICATE(1., N_ELEMENTS(xg))#yg

HELP, xg_2d, yg_2d


여기서는 xg_2d, yg_2d라는 새로운 배열들을 따로 생성했는데, HELP 명령으로 출력된 내용을 보면 다음과 같습니다.


XG_2D           FLOAT     = Array[10, 16]

YG_2D           FLOAT     = Array[10, 16]


이와 같이 data 배열과 동일한 10x16의 형태로 X축 격자점 좌표 및 Y축 격자점 좌표 값들을 담고 있는 xg_2d 및 yg_2d라는 배열을 생성하였습니다. 따라서 GRIDDATA 함수에 필수적으로 투입할 인수들은 xg_2d, yg_2d, data 등 세 개가 됩니다. 그 다음 단계는 GRIDDATA 함수가 결과로 산출할 규칙 격자 배열의 구조를 설정하는 것인데요. 이를 위하여 다음과 같이 xg_new, yg_new라는 두 개의 1차원 배열들을 새롭게 정의하였습니다.


xg_new = [100:150:0.1]

yg_new = [25:70:0.1]


이 두 배열은 X 및 Y 방향에 대하여 격자점들의 분포 범위는 원본 데이터와 동일하지만, 간격이 더 촘촘하고 일정하도록 정의된 것입니다. 실제로 xg_new는 501개의 값들로 구성되고 yg_new는 451개의 값들로 구성됩니다. 그래서 GRIDDATA 함수를 사용하여 얻은 결과가 이러한 새로운 규칙 격자 체계를 기반으로 한 501x451의 형태를 갖는 2차원 배열이 되도록 하고자 하는 것입니다. 이제 GRIDDATA 함수를 사용하여 구체적인 결과를 얻는 과정은 다음과 같습니다.


TRIANGULATE, xg_2d, yg_2d, tr

data_new = GRIDDATA(xg_2d, yg_2d, data, XOUT=xg_new, YOUT=yg_new, $

  /GRID, TRIANGLES=tr, /LINEAR)

HELP, data_new


여기서는 GRIDDATA 함수의 사용에 앞서서 TRIANGULATE 명령이 사용되었는데, 앞서 언급했던 Delaunay 삼각법 기반의 선형 내삽을 위하여 필요한 과정이기 때문입니다. 그리고 GRIDDATA 함수 내에서는 xg_2d, yg_2d, data 등의 형태가 서로 동일한 세 개의 배열들이 필수 인수로 사용되었고 xg_new, yg_new는 각각 XOUT, YOUT 키워드에 부여되었음을 볼 수 있습니다. 이렇게 얻은 data_new에 대하여 HELP 명령으로 출력된 세부 내용은 다음과 같습니다.


DATA_NEW        FLOAT     = Array[501, 451]


따라서 내가 지정한 규칙 격자 체계 기반으로 새롭게 산출된 데이터는 501x451의 형태를 갖는 2차원 배열임을 알 수 있습니다. 이제는 표출만 남았습니다. 표출 과정은 IMAGE 함수를 사용하여 다음과 같이 해주면 됩니다.


win = WINDOW(DIMENSIONS=[600, 600], /NO_TOOLBAR)

im_new = IMAGE(data_new, xg_new, yg_new, RGB_TABLE=ct, $

  AXIS_STYLE=2, XRANGE=[100, 150], YRANGE=[25, 70], $

  MARGIN=0.1, ASPECT_RATIO=0, /CURRENT)


이렇게 하여 표출된 최종 그림은 다음과 같습니다.



이렇게 하면 10x16의 형태를 갖는 불규칙 분포의 2차원 격자 데이터를 내가 원하는 크기의 규칙 격자 체계를 갖는 2차원 데이터로 변환하여 이미지의 형태로 표출할 수 있습니다. 이 과정에서 GRIDDATA 함수를 사용하였습니다. 참고로 GRIDDATA 함수가 사용된 위의 내용은 다음과 같이 다른 키워드들이 사용되는 방식으로 대체해도 됩니다.


data_new = GRIDDATA(xg_2d, yg_2d, data, DIMENSION=[501, 451], $

  START=[100, 25], DELTA=[0.1, 0.1], TRIANGLES=tr, /LINEAR)


즉 앞선 내용에서는 XOUT, YOUT, /GRID 등의 키워드들이 사용된 반면 위 내용에서는 DIMENSION, START, DELTA 등의 키워드들이 사용되었습니다. 이것은 GRIDDATA 함수를 사용하여 결과로 얻게 될 데이터의 격자 체계를 정의하는 방식상의 차이입니다. 결과는 어떻게 하든 거의 같다고 보면 됩니다.


그래서 2회에 걸쳐 소개한 이 내용은 이 정도로 마무리할까 합니다. 불규칙한 분포를 하는 2차원 데이터를 규칙적인 격자 기반의 데이터로 변환하는 것은 저도 업무적으로 종종 마주치는 일이어서 이 블로그에서도 심심치않게 다뤄오고 있습니다. 따라서 아마도 유사한 성격의 내용을 나중에 또 소개하게 될 수도 있을 것 같습니다.

반응형