IDL/New Graphics

VOLUME 함수를 이용한 3차원 큐브 데이터의 가시화 [2]

이상우_idl 2020. 1. 20. 23:33
728x90
반응형

* 지난 회 게시물에서 내용이 이어집니다.

 

지난 1회차 게시물의 내용에서는 NG 체계에서 VOLUME 함수를 이용하여 3차원 큐브(또는 볼륨) 형태의 데이터를 가시화하는데 있어서 불투명도(Opacity)라는 개념을 이해하고 활용하는 방법을 살펴보았습니다. 오늘은 이 불투명도의 개념을 적절히 활용하는 예제를 좀더 살펴보고자 합니다. 먼저 지난 회에서 사용했던 유사한 방식으로 3차원 데이터를 볼륨 형태로 가시화하는 기본적인 과정부터 다시 시작해보겠습니다. 이 과정은 다음과 같습니다.

 

file = FILEPATH('jet.dat', SUBDIR=['examples', 'data'])

data = READ_BINARY(file, DATA_DIMS=[81, 40, 101])

data = data/2B

HELP, data

PRINT, MIN(data), MAX(data)

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

v = VOLUME(data, ASPECT_RATIO=1, RGB_TABLE0=34, /CURRENT)

 

이와 같은 방식으로 VOLUME 함수를 사용하여 볼륨 데이터를 가시화할 때 기본적으로 적용되는 불투명도 테이블(Opacity Table)은 세부적으로는 256개의 바이트형 값들로 구성되며 0, 1, 2, ...., 253, 254, 255와 같이 순차적으로 1씩 증가하는 값들로 구성됩니다. 그러면 가시화의 대상이 되는 3차원 볼륨 데이터 내의 각 복셀을 표출하는데 있어서, 복셀값이 데이터의 최소값에 가까울수록 점점 투명하게 그리고 복셀값이 데이터의 최대값에 가까울수록 점점 불투명하게 표시됩니다.  물론 이것은 불투명도 테이블이 디폴트로 적용될 경우의 얘기입니다. 불투명도 테이블은 내가 직접 구성하여 활용할 수도 있음을 몇가지 예제들을 통하여 지난 회에서 소개하였습니다.

 

자 이제 오늘은 약간 다른 예제를 소개해 보고자 하는데요. 거두절미하고 우선 다음과 같은 내용을 실행하여 data_new라는 새로운 배열을 생성해 봅시다.

 

sz = SIZE(data, /DIM)

data_new = MAKE_ARRAY(sz, VALUE=MIN(data))

yp = 20

data_new[*, yp, *] = data[*, yp, *]

HELP, data_new

 

여기서 생성된 data_new는 그 배열구조는 원본 데이터 배열인 data와 동일합니다. 먼저 SIZE 함수를 사용하여 data 배열의 크기 정보를 가져오고 이를 MAKE_ARRAY 함수에 적용하여 동일한 구조의 data_new라는 배열을 생성하였습니다. 다만 data_new 배열의 초기 원소값들은 모두 원본 데이터인 data 배열의 최소값으로 통일하였습니다. 하지만 바로 뒤에서는 data_new 배열의 일부분에 대해서만 원본 data 배열의 값들로 대체하였습니다. 이 작업을 통해서 얻어진 data_new는 81x40x101의 구조를 갖는 바이트형 배열이라는 점에 있어서는 원본 data 배열과 동일하지만, 그 구성값들은 원본과는 다릅니다. 그러면 이 data_new 배열을 가시화해보면 어떻게 보이게 될까요? 이를 위하여 다음과 같이 별도의 새로운 그래픽창에서 볼륨 가시화를 해봅시다.

 

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

v = VOLUME(data_new, ASPECT_RATIO=1, RGB_TABLE0=34, /CURRENT)

 

그 모습은 다음 그림과 같습니다.

 

 

 

이 모습은 마치 3차원 볼륨 데이터의 단면도를 보는 것 같습니다. 사실은 어느 정도 그런 의도를 갖고 처리한 것이 맞습니다. 바로 XZ 평면의 형태로 볼륨 데이터의 단면도를 나타낸 것입니다. XZ 평면의 Y축 위치 인덱스를 위에서 20으로 설정하여 변수 yp에 담아서 사용한 것입니다. 만약 yp의 값을 바꾸면 당연히 Y축상에서 해당 위치에 대한 단면의 모습을 볼 수 있게 됩니다. 변수 yp의 값을 10으로 정의할 경우의 모습은 다음 그림과 같습니다.

 

 

 

그리고 변수 yp의 값을 30으로 정의할 경우의 모습은 다음 그림과 같습니다.

 

 

 

비슷한 방식으로 응용을 해본다면, 특정한 X축 좌표에 대한 YZ 평면을 표시하는 것도 가능합니다. 이를 위해서는 다음과 같은 방식으로 data_new를 생성하면 됩니다.

 

xp = 40

data_new[xp, *, *] = data[xp, *, *]

 

이렇게 생성된 data_new를 가시화한 모습은 다음 그림과 같습니다.

 

 

 

그리고 특정한 Z축 좌표에 대한 XY 평면을 표출하고자 한다면 다음과 같은 방식으로 처리하면 될 것입니다.

 

zp = 50

data_new[*, *, zp] = data[*, *, zp]

 

이 경우의 모습은 다음 그림과 같습니다.

 

 

 

그래서 이와 같은 방식으로 나름 그럴듯한 모습의 평면형 단면도와 같은 가시화를 해볼 수가 있습니다. 물론 엄밀하게 따진다면, 여기서 표출된 그림들은 마치 단면(Cross-section Plane)처럼 보이긴 하지만 그 실체는 2차원적인 평면은 전혀 아닙니다. 여전히 3차원 볼륨 데이터를 가시화한 모습일 뿐입니다. 다만 새로운 3차원 볼륨 데이터를 구성하는데 있어서 내가 보고자 하는 단면에 해당되는 복셀들만 눈에 보이도록 처리하고, 나머지 복셀들은 눈에 안보이도록 처리한 것일 뿐입니다. 그래서 표출된 그림에서는 마치 평면처럼 보이긴 하지만 그 '평면'을 구성하는 요소들은 여전히 '복셀(Voxel)'들입니다. 하지만 그냥 3차원 볼륨의 형태로 가시화했을 때에는 잘 보이지 않던 내부의 모습을 볼 수 있다는 점에 있어서는 이러한 표출 방식은 나름의 의미를 갖는다고 볼 수 있습니다.

 

다만 이와 같이 마치 '평면'처럼 보이는 표출 방식에 있어서 유의해야 할 것은, 불투명도 테이블에 대한 고려가 필요하다는 것입니다. 여기서는 불투명도 테이블을 커스터마이즈하지 않고 그냥 디폴트로 적용한 상태이기 때문에, 낮은 값의 복셀들은 투명도가 높고, 높은 값의 복셀들은 불투명도가 높습니다. 그러한 특성이 '평면'에서도 여전히 존재함을 유의해야 합니다. 그래서 앞서 표출했던 XZ, YZ, XY 평면 형태의 그림들에서 허옇게 보이는 부분은 실제로는 거의 투명하게 처리된 부분이고, 원본 데이터에서도 복셀값이 낮은 부분에 속하기때문에 그렇게 보인다는 것을 유의해야 합니다.

 

그런데 3차원 볼륨 데이터에 대한 단면도를 표출하는데 있어서 이와 같은 방식이 나름 그럴듯해 보이긴 하면서도 뭔가 좀 작위적이고 부자연스러운 느낌이 들 수 있습니다. '단면'이라는 것은 기하학적으로 2차원 평면입니다. 그래서 원론적으로 생각해보면 XYZ 3차원 공간상에서 존재하는 평면을 폴리곤의 형태로 생성하고 그 폴리곤에 단면 이미지를 텍스쳐(Texture)의 형태로 입힌다면 더 완벽한 작업이 될 수 있을텐데, 굳이 위와 같이 다소 꼼수처럼 보이는 방식을 통해서 '단면'을 표출했을까요? 사실은 NG 체계에서는 평면 형태의 폴리곤을 구현하는 것 자체는 POLYGON 함수를 이용하면 가능하지만, 문제는 이렇게 구현된 평면 폴리곤에 이미지 텍스쳐를 입히는 기능이 아직 지원되지 않기 때문입니다. 즉 NG 체계의 POLYGON 함수에서는 이미지 텍스쳐 기능이 지원되지 않는다는 것입니다. 그래서 NG 체계에서 3차원 공간상에서 2차원적인 평면을 구현하는 것까지는 가능하지만, 그 위에 이미지를 텍스쳐로 입혀서 표출하는 것은 현 시점에서는 불가능합니다(IDL 8.7 기준).

 

물론 3차원 큐브 데이터에 대하여 단면 이미지를 3차원 공간상에서 바로 표출하는 것이 IDL에서 아예 불가능한 것은 아닙니다. 하지만 이러한 작업을 제대로 하려면 OG(Object Graphics)에서 작업을 해야 합니다. OG 체계에서 사용되는 IDLgrPolygon 클래스에서는 이미지 텍스쳐 기능이 완벽하게 지원됩니다. 다만 OG 체계에서 그래픽 표출을 하는 것은 과정이 상당히 복잡해서 관련 내용을 이 블로그에서 다루기도 제 입장에서는 좀 버거운 측면이 있습니다. 그래서 일단 거기까지는 가지는 않겠습니다. 물론 나중에 혹시라도 기회가 된다면(?) 모르겠습니다.

 

그러면 이번 시리즈 게시물은 일단 여기서 마감하겠습니다. 물론 나중에라도 NG 체계에서의 볼륨 가시화와 관련하여 새로운 내용이 있다면 다시 여기를 통해서 소개하도록 하겠습니다.

반응형