Insight Toolkit (ITK)는 의료영상처리를 위한 오픈소스 라이브러리입니다. 본 글에서는 itk에서 영상을 나타내기 위한 기본 클래스 itk::Image를 소개합니다.
itk::Image 객체 사용하기
itk::Image는 다양한 자료형으로 Pixel을 표현하기 위해 Generic Programming을 따릅니다. 2개의 파라미터를 입력하는데, 첫 번째 파라미터는 픽셀의 자료형, 두 번째 파라미터는 차원(Dimension)을 의미합니다.
#include "itkImage.h"
// itk::Image<PixelType, Dimension>
using ImageType = itk::Image<unsigned char, 3>;
itk::Image<unsigned char, 3>은 그레이 영상의 3차원 데이터를 의미합니다. 템플릿 클래스로부터 객체를 만들다보면 코드가 길어지므로 using 키워드를 사용해서 alias를 선언하여 줍니다.
아래와 같이 PixelType과 Dimension을 선언해 놓고 사용하기도 합니다.
using PixelType = unsigned char;
constexpr unsigned int Dims = 3;
using ImageType = itk::Image<PixelType, Dims>;
스마트포인터를 사용하여 객체를 사용합니다. New() 를 호출하여 객체를 생성하고,스마트포인터에 이를 할당합니다.
//itk::SmartPointer
ImageType::Pointer image = ImageType::New();
itk::Image 영상 표현 정보
영상을 표현하기 위해 Region, Origin, Spacing과 Direction정보가 필요합니다. 아래 이미지를 잘 들여다 보시고 아래 설명을 읽는 것을 권장합니다.
http://insightsoftwareconsortium.github.io
Region
영상의 영역에 대한 정보로 index와 size 정보의 조합으로 이루어집니다. index는 시작점, size는 3차원 기준으로 가로x세로x높이라고 이해하시면 쉬울 것 같습니다.
itk::Image에서 다루는 Region은 3가지 입니다. 문서 상으로는 itk는 RAM 용량을 초과하는 이미지도 다룰 수 있다고 쓰여 있습니다.
- BufferedRegion: 물리 메모리 상에 있는 이미지 영역
- RequestedRegion: 처리되고 있는 이미지 영역
- LargestPossibleRegion: 전체 데이터 영역
※ 일반적으로 size를 이야기할 때는 LargestPossibleRegion을 기준으로 합니다.
Image Region 객체를 불러오는 간단한 예제입니다.
#include <iostream>
#include <itkImage.h>
using PixelType = unsigned char;
constexpr unsigned int Dims = 3;
using ImageType = itk::Image<PixelType, Dims>;
using namespace std;
int main()
{
ImageType::Pointer image = ImageType::New();
ImageType::RegionType region1 = image->GetBufferedRegion();
ImageType::RegionType region2 = image->GetRequestedRegion();
ImageType::RegionType region3 = image->GetLargestPossibleRegion();
cout << "Buffered: " << region1.GetIndex() << "," << region1.GetSize() << endl;
cout << "Requested: " << region2.GetIndex() << "," << region2.GetSize() << endl;
cout << "Largest: " << region3.GetIndex() << "," << region3.GetSize() << endl;
ImageType::IndexType index;
index.Fill(0);
ImageType::SizeType size;
size[0] = 448;
size[1] = 448;
size[2] = 30;
ImageType::RegionType region;
region.SetIndex(index);
region.SetSize(size);
// 영역 할당
image->SetRegions(region);
image->Allocate();
cout << image->GetLargestPossibleRegion() << endl;
return 0;
}
실행 결과Region 데이터를 활용하여, image 객체에 Region을 할당하여 주는 예제입니다.
Origin & Spacing
Origin은 Physical Space를 기준으로 하는, 영상의 원점을 의미합니다.
Spacing은 Physical Space 상에서 픽셀 간 간격을 의미합니다. 영상을 다룰 때, 메모리 공간에는 픽셀 별로 데이터만 저장할 뿐, 픽셀의 실제 간격은 알 수 없습니다. 예를 들어 설명을 해 보겠습니다. 1차원 데이터에 5개의 픽셀이 있고 spacing값이 0.1이라면, 물리적 공간에서는 5pixel * 0.1 = 0.5 mm (일반적으로 mm단위를 씀)을 의미합니다. 반면 spacing값이 1.0이라면 5pixel * 1 = 5mm가 되겠지요.
3DSlicer라는 프로그램을 사용하면 Dicom 데이터 또는 의료영상 데이터를 로드할 수 있는데, 영상의 Origin과 Spacing(왼쪽 빨간 박스 영역)을 확인할 수 있습니다.
※ Direction Matrix는 영상과 물리적 공간 좌표계 간의 관계를 의미합니다. 관련 내용이 방대하여 따로 다루도록 하겠습니다. 해당 글 작성이 되면 본 포스팅에 링크할 예정입니다.