IDL/Image Processing

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

이상우_idl 2013. 2. 20. 15:01
728x90
반응형

지난 1회 포스팅에서는 XROI에서 수동으로 ROI를 설정하고 이 정보를 sav파일로 저장한 다음, XROI 인터페이스는 닫고 sav파일의 내용을 RESTORE 명령으로 복원해서 IDL에서 인식시킨 후 그 안의 정보를 끄집어낼 준비까지 마쳤습니다. 편의상 이 과정을 다시 요약하면 다음과 같습니다.


IDL> data = HANNING(300, 300)

IDL> sz = SIZE(data, /DIM)

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

IDL> TVSCL, data

IDL> XROI, BYTSCL(data)

여기서 마우스 드래그로 ROI를 선택하고, 저장 버튼을 눌러 'regions.sav'라는 이름의 sav파일로 저장

IDL> RESTORE, 'regions.sav'

IDL> DRAW_ROI, oROIs, COLOR=0, /LINE_FILL, /DEVICE



염두에 둬야 할 점은, 'regions.sav'라는 파일을 RESTORE 명령으로 IDL에서 복원하면 oROIs라는 이름의 객체가 IDL상에서 인식된다는 것입니다. 일단 먼저 DRAW_ROI 명령을 사용하여 ROI의 위치 및 형태가 앞서 XROI 인터페이스상에서 마우스 드래그로 정의했던 것과 같다는 것을 확인할 수 있습니다. 이 객체는 엄밀히 말하면 IDLanROI라는 클래스에 속하는데요. 이에 대해서 자세히 언급하지는 않겠습니다. 그냥 원하는 정보들을 끄집어내는 방법 위주로만 소개를 하겠습니다. 먼저 다음과 같은 명령을 실행해봅시다.


IDL> oROIs -> GetProperty, N_VERTS=nvts


이것은 oROIs라는 객체로부터 N_VERTS라는 속성(Property)을 끄집어내어 nvts라는 변수에 넣어서 전달해달라는 의미입니다. IDL의 객체로부터 특정한 속성 정보를 끄집어내는 전형적인 방법이라는 정도로만 얘기해두겠습니다. 이 상태에서 nvts라는 변수의 값을 출력해보면 다음과 같이 어떤 값이 나옵니다.


IDL> PRINT, nvts

143


이것은 ROI의 경계선을 이루는 화소(pixel)들의 갯수가 143개라는 뜻입니다. ROI가 더 크면 이 갯수는 더 많을 것이고, 작으면 더 적겠지요. 이번엔 다음과 같이 ROI_XRANGE라는 속성의 정보를 끄집어내어 그 결과를 출력해봅시다.


IDL> oROIs -> GetProperty, ROI_XRANGE=rxr

IDL> PRINT, rxr

93.0000    171.0000


여기서 출력된 값은 전체 이미지상에서 ROI가 차지하는 공간범위가 X축 방향으로 어디서부터 어디까지냐를 나타냅니다. 이와 유사한 ROI_YRANGE라는 속성도 당연히 존재합니다. 이번에는 또 다른 정보들을 끄집어내기 위하여 다음과 같은 명령을 실행해봅시다.


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

IDL> PRINT, centroid

130.52779    156.27914    0.00000


여기서 ComputeGeometry라는 것은 객체에 대한 메서드(Method)라고 부르는데, 그냥 쉽게 생각하면 이러한 종류의 객체에만 고유하게 존재하는 명령같은 것으로 이해하면 됩니다. 그래서 세부적으로는 CENTROID, AREA 등과 같은 키워드가 존재하여 이 키워드를 통하여 해당 정보를 끄집어내기도 합니다. 여기서 CENTROID는 ROI 영역의 중심의 좌표에 해당됩니다. 일종의 무게중심(Center of Mass)과 같은 개념이라고 보면 됩니다. 이 값을 출력하면 위와 같이 3개의 값들이 나오는데, 각각 X, Y, Z 좌표값에 해당됩니다. 어차피 이 상황에서는 Z좌표라는게 아무 의미가 없으므로 앞의 두 값만 의미가 있겠죠. 즉, ROI의 중심좌표가 [130, 156]이라고 보면 된다는 의미입니다. 그리고 AREA는 말 그대로 면적입니다. ROI가 차지하는 영역의 면적에 해당되는데 출력해보면 다음과 같이 면적값을 보여줍니다.


IDL> PRINT, area

4717.50000


단 여기서 유의할 점은 이 면적인 기하학적(Geometric) 면적입니다. 화소(Pixel) 기반의 면적은 아닙니다. 기하학적 면적이라는 의미는 ROI를 이루는 윤곽선의 좌표를 실수로 인식해서 실제 수학적인 도형처럼 계산한다는 의미입니다. 예를 들어 간단하게 사각형으로 생각해보면, 어떤 사각형의 좌표가 가로 방향으로 0~10이고 세로 방향으로 0~20이라고 합시다. 그러면 "기하학적인" 면적은 당연히 (10-0)*(20-0)=200이 될겁니다. 그런데 이걸 화소 기반으로 생각하면, 가로 방향의 화소 갯수는 0부터 10까지이니까 11개이고 세로 방향으로는 0부터 20까지니까 21개입니다. 그러면 화소 기반의 면적인 11*21=241이 됩니다. 분명히 차이가 있죠. 이러한 차이를 다음 그림에서 도식적으로 나타내보았습니다. 왼쪽이 기하학적 면적이고 오른쪽이 화소 단위 면적입니다.



그래서 내가 원하는 면적이 기하학적 면적인지 아니면 화소 단위의 면적인지를 구분해야 합니다. 기하학적 면적을 원한다면 위의 방법으로 해결되지만, 만약 화소 단위의 면적을 원한다면 다음과 같은 과정을 밟아주면 됩니다.


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

IDL> IMAGE_STATISTICS, data, MASK=roi_mask, COUNT=pixel_area

IDL> PRINT, pixel_area

4857


여기서는 ComputeMask라는 메서드를 사용하여 ROI 영역을 나타내는 마스크 영역을 설정하고, 이를 기반으로 IMAGE_STATISTICS라는 명령을 사용하여 COUNT라는 키워드로 얻어진 값을 화소 단위의 면적으로 간주합니다. 여기서 COUNT의 의미는 ROI 영역이 커버하는 화소들의 총 갯수를 의미합니다. 즉 화소 단위의 면적이 됩니다. 여기서 사용된 IMAGE_STATISTICS라는 명령에는 몇몇 유용한 키워드들이 있습니다. 예를 들어 다음과 같이 사용해봅시다.


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

IDL> PRINT, roi_mean, roi_stddev

0.877726     0.0940309


여기서는 ROI 영역내 화소값들의 평균 및 표준편차값을 구한 것입니다. 이와 같이 MEAN, STDDEV라는 키워드를 사용하여 이러한 간단한 통계값들도 얻을 수 있습니다. 그 외에도 ROI에 관한 다양한 정보들을 끄집어낼 수 있는데요. 좀 더 자세한 내용은 IDL 도움말에서 IDLanROI, IMAGE_STATISTICS로 검색해보면 찾을 수 있습니다.


이제 다음 회에서는 ROI를 마우스 드래그와 같은 수동적인 방법이 아닌, CONTOUR 기반으로 정의하는 방법을 소개할 예정입니다. 사실 수동으로 ROI를 설정하는 것보다는 이 방법이 더 유용한 경우가 많을겁니다. 기대해주시길~


반응형