IDL/Image Processing

영상 처리에서 ROI의 활용법 [3]

이상우_idl 2013. 2. 27. 17:01
728x90
반응형

지난 2회에 걸쳐서 ROI를 설정하고 그 ROI 영역에 대한 정보들을 알아내는 기본적인 방법들을 살펴보았습니다. 여기서는 ROI를 사용자가 직접 마우스 드래그에 의하여 정하는 방식을 사용했었는데요. 오늘은 특정한 화소값 기준에 의하여 ROI가 결정되도록 하는 방식에 대하여 소개하고자 합니다. 예제로 사용할 2차원 데이터는 지난번과 같습니다. 먼저 다음과 같은 방식으로 이 데이터를 그래픽창에 이미지의 형태로 표출합니다. 여기까지는 지난번에 했던 내용과 같습니다.


IDL> data = HANNING(300, 300)

IDL> PRINT, MIN(data), MAX(data)

0.0000    1.0000

IDL> sz = SIZE(data, /DIM)

IDL> WINDOW, XSIZE=sz[0], YSIZE=sz[1]

IDL> TVSCL, data


단 이번에는 이렇게 표출된 이미지상에 등위선(Contour)을 덧그리게 됩니다. 이 2차원 데이터의 값의 범위는 0~1입니다. 그래서 다음과 같이 CONTOUR 명령을 사용하여 값이 0.5에 해당되는 등위선을 그려볼 수 있습니다. 이와 같이 이미지상에 등위선을 덧그린 모습은 다음과 같습니다.


IDL> CONTOUR, data, LEVEL=0.5, XMARGIN=[0, 0], YMARGIN=[0, 0], /NOERASE



여기서는 LEVEL이라는 키워드를 사용하여 등위선의 값을 0.5로 설정하였습니다. 그리고 XMARGIN, YMARGIN 키워드의 값을 [0, 0]으로 설정하여 그래픽창에서 X축 및 Y축의 여백을 없애서 그림 자체를 화면에 꽉 차도록 그렸습니다. 또한 NOERASE 키워드를 사용하여, 앞서 TVSCL 명령으로 표출한 이미지가 등위선 그림을 그리면서 사라지지 않도록 하였습니다. 이와 같이 그림을 그려보면 값이 0.5에 해당되는 등위선이 어떻게 생겼는지 확인이 가능합니다. 물론 이 값을 다른 값으로 바꾸면 다른 형태의 등위선이 그려지겠지요. 지금 이와 같은 등위선을 그리는 목적은, 등위선이 나타내는 폐곡선 영역을 ROI로 인식시키고자 하는 것입니다. 이런 방식의 ROI 설정을 사용자의 마우스 드래그로 할 수는 없겠지요. 하지만 이렇게 화소값의 정확한 수치에 근거한 ROI를 설정해야 할 경우도 분명히 존재할 것입니다.


이와 같이 특정한 값에 해당되는 등위선으로 되어 있는 영역을 ROI로 인식시키기 위해서는 사실 CONTOUR 명령을 사용해야 합니다. 단 이 경우에는 CONTOUR 명령에 붙어야 하는 키워드들이 좀 더 늘어납니다. 그 사용법은 다음과 같습니다.


IDL> CONTOUR, data, LEVEL=0.5, XMARGIN=[0, 0], YMARGIN=[0, 0], /NOERASE, $

IDL>   PATH_INFO=pathInfo, PATH_XY=pathXY, XSTYLE=5, YSTYLE=5, /PATH_DATA_COORDS

IDL> HELP, pathInfo

IDL> HELP, pathXY


여기서 가장 주목해야 할 부분은 PATH_INFO, PATH_XY라는 키워드들입니다. 이 키워드를 통하여 pathInfo, pathXY라는 결과를 돌려받게 되는데, 이 결과물이 과연 어떤 것들인지 확인하기 위하여 각각에 대하여 HELP 명령을 적용해보았습니다. 먼저 pathInfo에 대하여 HELP를 적용해본 결과는 다음과 같이 나옵니다.


** Structure CONTOUR_PATH_STRUCTURE, 6 tags, length=16, data length=16:

   TYPE            BYTE         1

   HIGH_LOW        BYTE         1

   LEVEL           INT              0

   N               LONG               596

   OFFSET          LONG                 0

   VALUE           FLOAT          0.500000


여기서 pathInfo는 사실 구조체(Structure)라는 자료형으로 얻어집니다. 구조체라는 것은 쉽게 말하면 다양한 자료형(Type)의 정보들을 하나의 묶음으로 하는 통합형 자료형이라고 보면 됩니다. 여기서는 VALUE라는 값이 0.5라는 것과 N이라는 값이 596이라는 것만 일단 주목하면 될 것 같습니다. 0.5는 앞서 CONTOUR 명령에서 LEVEL 키워드에 부여했던 값을 뜻합니다. 그리고 596은 0.5라는 값을 기준으로 그려진 등위선의 윤곽선이 총 596개의 점들로 이루어져 있다는 의미입니다. 그러면 이 596개의 점들을 각각 [X, Y]좌표값을 가질겁니다. 그 좌표값들이 사실 pathXY라는 결과입니다. 실제로 path XY에 대하여 HELP를 적용해본 결과는 다음과 같이 나옵니다.


PATHXY          FLOAT     = Array[2, 596]


이 얘기는 pathXY라는 배열이 596개의 점들에 대한 [X, Y] 좌표값들을 갖고 있다는 의미입니다. 따라서 배열의 구조가 2X596이 된 것입니다. 이제 이렇게 얻어진 pathInfo, pathXY를 갖고 ROI를 정의하면 됩니다. 이 작업은 다음과 같은 방식으로 이루어집니다.


IDL> line = [LINDGEN(pathInfo.N), 0]

IDL> oROI = OBJ_NEW('IDLanROI', (pathXY[*, pathInfo.OFFSET+line])[0, *], (pathXY[*, pathInfo.OFFSET+line])[1, *])


여기서는 IDLanROI라는 클래스에 해당되는 하나의 객체를 정의한 것입니다. 즉, 이 객체 자체가 ROI입니다. 결국은, 앞선 2회의 게시물에서 보면 ROI를 sav 파일의 형태로 저장하고 나중에 RESTORE 명령을 사용하여 IDL에서 인식을 시켰었는데 그 상태와 같다고 보면 됩니다. 그러면 이 ROI에 대한 각종 정보들을 끄집에내는 과정은 동일합니다.


IDL> oROI -> GetProperty, N_VERTS=nvts

IDL> PRINT, nvts

597

IDL> oROI -> GetProperty, ROI_XRANGE=rxr

IDL> PRINT, rxr

75.0000    225.0000

IDL> stats = oROI -> ComputeGeometry(AREA=area, CENTROID=centroid)

IDL> PRINT, area

18187.792

IDL> PRINT, centroid

150.0000    150.0000    0.0000

IDL> roi_mask = oROI -> ComputeMask(DIMENSIONS=sz)

IDL> IMAGE_STATISTICS, data, MASK=roi_mask, COUNT=pixel_area, MEAN=roi_mean, STDDEV=roi_stddev

IDL> PRINT, pixel_area

18497

IDL> PRINT, roi_mean

0.724951

IDL> PRINT, roi_stddev

0.146059


그래서 대략적으로 이와 같은 과정을 밟으면, 특정한 화소값을 기반으로 하는 ROI를 설정하고 이 영역에 관한 여러 정보들을 얻을 수 있습니다. 어떤 경우에는 이렇게 CONTOUR 명령을 사용하여 얻어진 ROI의 갯수가 하나를 넘는 경우도 있습니다. 사용된 2차원 데이터에 형태에 따라서는 그런 경우가 충분히 발생할 수 있겠죠. 그 경우에는 위에서 pathInfo라는 이름으로 얻어지는 정보가 단 한 개의 구조체가 아닌 여러 구조체들로 이루어진 배열이 됩니다. 물론 각 구조체는 각 ROI에 해당되겠죠. 그러면 특정한 ROI의 인덱스를 안다면 그 ROI에 대해서는 다음과 같이 ROI 객체로 만들어주면 됩니다. 만약 i번째 구조체에 해당되는 ROI에 대하여 작업을 한다고 하면 말이죠.


line = [LINDGEN(pathInfo[i].N), 0]

oROI = OBJ_NEW('IDLanROI', (pathXY[*, pathInfo[i].OFFSET+line])[0, *], (pathXY[*, pathInfo[i].OFFSET+line])[1, *])


이렇게 특정 화소값 조건을 만족하는 여러 개의 ROI가 존재할 경우, 그 순서는 면적이 가장 큰 것부터 작은 것의 순서가 됩니다. 예를 들어, 화소값이 0.5라는 조건을 만족하는 등위선이 세 개가 존재한다고 하면, 세 개의 구조체들이 얻어지게 되며, 인덱스상으로 0이 가장 큰 영역에 해당되고 2가 가장 작은 영역에 해당됩니다.


이상 3회에 걸쳐서 이미치 처리에 있어서 ROI의 설정 및 활용법에 대하여 알아보았습니다. 읽어주신 여러분들의 실질적인 작업에 도움이 될만한 내용이었길 바랍니다. 위의 내용을 담은 예제코드도 함께 첨부합니다.


test_roi_20130225.pro


test_roi_20130225.pro
0.0MB
반응형