본문 바로가기
프로그래밍/ITK

원점과 공간 정의

by 이재만박사 2016. 7. 2.

- 이 부분에 대한 소스 코드는 다음 파일에서 찾을 수 있다

- Examples/DataRepresentation/Image/Image4.cxx

 

- ITK가 일반적인 이미지 처리 일을 수행하는데 사용될 수 있을지라도, 그 툴킷의 주 목적은 의료 이미지 데이터 처리이다

- 그런 측면에서, 이미지에 관한 추가적인 정보는 의무적으로 고려된다

- 특히 픽셀 사이에 물리적인 공간과 연관된 정보와 어떤 월드 좌표 시스템에 대하여 공간에서 이미지의 위치는 극도로 중요하다

 

- 이미지 원점과 공간은 많은 응용 프로그램에 근본적이다

- 예를 들어, 정합(Registration)은 물리 좌표계에서 수행된다

- 적절하지 않게 정의된 공간과 원점은 그런 과정에서 일치하지 않는 결과를 출력한다

- 공간 정보가 없는 의료 이미지는 의료 진단, 의료 분석, 특징 추출, 지원형 방사 치료 또는 이미지 안내 수술에 대해 사용되어서는 안 된다

- 다르게 말하면, 공간 정보가 부족한 의료 이미지는 쓸모도 없고 위험하다

 

- 그림 4.1은 itk::Image와 연관된 주요 지형 컨셉을 보여준다

- 이 그림에서, 원은 픽셀의 중심을 나타내는데 사용된다

- 픽셀의 값은 픽셀의 중심에 위치한 Dirac Delta 함수와 같이 존재하는 것을 가정한다

- 픽셀 공간은 픽셀 중심 사이에 측정되고 각 차원에 따라 다를 수 있다

- 이미지 원점은 이미지에서 첫 번째 픽셀의 좌표와 연관되어 있다

- 픽셀은 데이터 값을 유지하는 픽셀 중심 주변으로 직사각형 영역으로 고려된다

- 이것은 그림의 오른쪽에서 보여지는 것과 같이, 이미지 그리드의 Voronoi 영역처럼 보여진다

- 이미지 값의 선형 보간은 Dealunay 영역 내부에서 수행되고 그것의 모시리는 픽셀 중심이다

 

 

- 이미지 공간은 FixedArray로 나타내고 그것의 크기는 이미지의 차원을 매칭한다

- 이미지의 공간을 수동적으로 설정하기 위해, 대응되는 타입의 배열은 생성되어야 한다

- 배열의 원소는 주변 픽셀의 중심 사이에 공간을 초기화해야 한다

- 다음 코드는 공간과 원점을 처리하는 Image 클래스에서 사용 가능한 메서드들의 예를 보여준다

 

ImageType::SpacingType spacing;


// Units (e.g., mm, inches, etc.) are defined by the application.
spacing[0] = 0.33; // spacing along X
spacing[1] = 0.33; // spacing along Y
spacing[2] = 1.20; // spacing along Z

 

- 배열은 SetSpacing() 메서드를 사용하여 이미지에 할당될 수 있다

 

image ->SetSpacing( spacing );

 

- 공간 정보는 GetSpacing() 메서드를 사용함으로써 이미지로부터 얻을 수 있다

- 이 메서드는 FixedArray에 대한 참조를 리턴한다

- 리턴된 객체는 배열의 내용을 읽기 위해 사용될 수 있다

- 배열을 변경하지 않는다는 것을 지시하기 위해 const 키워드를 사용하는 것에 주목하라

 

const ImageType::SpacingType& spacing = image->GetSpacing();

 

std::cout << "Spacing = "

std::cout << spacing[0] << ", " << spacing[1] << ", " << spacing[2] << std::endl;

 

- 이미지의 원점은 공간과 유사한 방법으로 관리된다

- 적당한 차원의 Point가 첫 번째로 할당되어야 한다

- 그리고 나서 원점의 좌표는 모든 컴포넌트에 할당될 수 있다

- 이 좌표는 물리 공간에서 임의의 참조 시스템에 대하여 이미지의 첫 번째 픽셀의 위치에 대응한다

- 같은 응용 프로그램에서 사용되는 여러 개의 이미지들이 일치하는 참조 시스템을 사용하는 것이 확실하게 하는 것은 사용자의 책임이다

- 이것은 이미지 정합 응용 프로그램에서 굉장히 중요하다

 

- 다음의 코드는 이미지 원점을 초기하하기 위한 알맞은 변수의 생성과 할당을 보여준다

 

ImageType::PointType origin;

 

origin[0] = 0.0f;

origin[1] = 0.0f;

origin[2] = 0.0f;

 

image->SetOrigin(origin);

 

- 원점은 또한 GetOrigin() 메서드를 사용하여 이미지로부터 또한 얻을 수 있다

- 이것은 Point에 대한 참조를 리턴한다

- 이 참조는 배열의 내용을 읽기 위해 사용될 수 있다

- 배열의 내용이 변경되지 않기 위해 지시하는 const 키워드의 사용을 다시 주목하라

 

const ImageType::PointType& origin = image->GetOrigin();

 

std::cout << "Origin = "

std::cout << origin[0] << ", " << origin[1] << ", " << origin[2] << std::endl;

 

- 일단 이미지의 공간과 원점이 초기화되면, 이미지는 바르게 물리 공간 좌표계로부터 픽셀 인덱스에 매핑될 것이다

- 다음의 코드는 물리 공간에서 point가 가장 가까운 픽셀의 내용을 읽는 목적을 위해 어떻게 이미지 인덱스로 매핑될 수 있는지에 대해 보여준다

 

- 첫째로, itk::Point 타입을 선언해야 한다

- point 타입은 좌표를 나타내기 위해 사용되는 타입 위에 그리고 공간의 차원 위에 템플릿된다

- 이 특별한 경우에, point의 차원은 이미지의 차원과 매칭되어야 한다

 

typedef itk:Point< double, ImageType::ImageDimension > PointType;

 

- itk::Index와 같은 Point 클래스는 상대적으로 작고 간단한 객체이다

- 이러한 이유로, ITK에서 큰 데이터 객체와 같은 참조-카운트가 아니다

- 결과적으로, 또한 itk::SmartPoint 로 조작되지 않는다

- Point 객체는 어떤 다른 C++ 클래스의 인스턴스처럼 간단히 선언된다

- 일단 point가 선언되면, 그것의 컴포넌트는 전통적인 배열 표기법을 사용하여 접근할 수 있다

- 특히, [ ] 연산자는 가능하다

- 효율 이유로, 특별한 점의 컴포넌트를 접근하기 위해 사용되는 인덱스에 대해 경계 체크도 하지 않는다

- 인덱스가 범위 안에 {0, Dimension - 1} 있는 것을 보증하기 위한 것은 사용자의 책임이다

 

PointType point;

 

point[0] = 1.45;

point[1] = 7.21;

point[2] = 9.28;

 

- 이미지는 현재의 공간과 원점의 값을 사용하여 점을 인덱스에 매핑할 것이다

- 인덱스 객체는 Image 타입에 정의된 IndexType을 사용하여 초기화될 수 있다

 

ImageType::IndexType pixelIndex;

 

- 이미지 클래스의 TransformPhysicalPointToIndex() 메서드는 제공된 점에 가장 가까운 픽셀 인덱스를 계산할 것이다

- 그 메서드는 현재 버퍼에 있는 픽셀 데이터 내부에 포함되는 이 인덱스에 대해 체크한다

- 그 메서드는 결과 인덱스가 버퍼 영역 안에 있는지 아닌지를 가리키는 부울 변수를 리턴한다

- 결과 인덱스는 그 메서드의 결과 값이 false 일 때 사용되지 말아야 한다

 

- 다음 줄은 point를 인덱스로 매핑하는 것을 보여주고 이미지로부터 픽셀 데이터에 접근하기 위한 픽셀 인덱스의 연속적인 사용을 보여준다

 

bool isInside = image->TransformPhysicalPointToIndex( point, pixelIndex );

 

if ( isInside )

{

    ImageType::PixelType pixelValue = image->GetPixel( pixelIndex );

    pixelValue += 5;

 

    image->SetPixel( pixelIndex, pixelValue );

}

 

- 픽셀 데이터에 접근하기 위한 GetPixel() 과 SetPixel()는 매우 비효율적인 메서드임을 기억하라

- 픽셀 데이터에 대한 거대한 접근이 요구될 때 이미지 반복자가 사용되어야 한다

댓글