본문 바로가기

Programming/VTK

[VTK] dicom 데이터(CT image)에서 뼈 영역만 남기기 (MFC, vs2019)

CT 데이터는 3D 픽셀(=Voxel)로 이루어져 있으며, 각 Voxel에는Hounsfield Unit (HU) 값이 있습니다.

 

Hounsfield Unit 이란?

HU는 물질이 X-ray를 얼마나 흡수하느냐(=조직의 밀도)를 숫자로 나타낸 값입니다.
주로 사람의 몸에 대한 X-ray 영상을 취득할 때, 각 조직(tissue)의 밀도(density)를 표현하는 단위로 사용됩니다.
X-ray가 많이 흡수될수록 (즉, density가 높을수록) HU값이 크고, 적게 흡수될수록 (즉, density가 낮을수록) HU값이 작습니다.

 

조직   HU
공기 Air 약 -1000 HU
폐 영역 Lung area 약 -500 HU
지방 조직 Fats 약 -100 ~ -50 HU
Water 0 HU
근육 Muscle 약 50 ~ 100 HU
뼈(해면골) Cancellous bone 약 150 ~ 300 HU
뼈(치면골) Compact bone 약 700 ~ 3000 HU

 

위 값을 사용하였을 때, 뼈 영역을 추출하기 위해서는 약 200 HU  이상을 선택하면 됩니다. 

 

 

dicom 데이터(CT image)에서 뼈 영역만 남기기

vtkFlyingEdges3D  알고리즘은 3D 스칼라 필드에서 등표면(isosurface) 을 추출하는 알고리즘입니다. 

vtkMarchingCubes 보다 빠른 고속 등표면 추출 알고리즘으로, 본 예제에서는 vtkFlyingEdges3D  알고리즘을 사용하겠습니다. 

 

우선 vtkDICOMImageReader를 사용하여 dicom 이미지를 불러와 줍니다. 

vtkSmartPointer<vtkActor> CvtkMFCDlgEXDlg::initImageActor(CString cstrImagePath)
// cstrImagePath: .dcm이 들어있는 폴더 directory 
{
	vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
	const char* charPath = (char*)(LPCTSTR)cstrImagePath;
	reader->SetDirectoryName(charPath);
	reader->Update();

 

dicom 이미지를 불러온 후, 해당 3d 볼륨데이터를 가져와서 vtkFlyingEdges3D 에 입력으로 연결합니다. 

 


	vtkNew<vtkFlyingEdges3D> flyingEdges3D_bone;
	flyingEdges3D_bone->SetInputConnection(reader->GetOutputPort());
	flyingEdges3D_bone->SetValue(0, 250);
    
	vtkNew<vtkPolyDataMapper> mapper_bone;
	mapper_bone->SetInputConnection(flyingEdges3D_bone->GetOutputPort());
	mapper_bone->ScalarVisibilityOff();	//스칼라 값을 무시하고, 지정한 색상이나 재질을 그대로 사용하기 위해
    
	vtkNew<vtkActor> actor;
	actor->SetMapper(mapper_skin);
	actor->GetProperty()->SetDiffuseColor(colors->GetColor3d("BoneColor").GetData()); // 뼈색상(흰색)으로 객체 설정
	actor->GetProperty()->SetSpecular(0.3);	// 광택 반사계수 (0.0: 매트, 1.0: 매우 강한 광택)
	actor->GetProperty()->SetSpecularPower(20);	//광택 집중도 설정 (1~5: 광택 넓고 퍼짐, 플라스틱 같이, 10~100: 광택 좁고 선명, 금속 같이)

	return actor;
}

 

  • SetValue(index, value)는 특정 등치값(iso-value) 에 해당하는 표면을 추출하겠다는 뜻입니다.
  • 여기서 index = 0은 첫 번째 등표면 설정이라는 뜻이고,
  • value = 250은 HU(Hounsfield Unit) 기준으로 200이라는 밀도를 가진 등표면을 생성하겠다는 의미입니다.

쉽게 말하면: 👉 "HU 값이 250인 영역에서 등표면을 만들어줘! (예: 뼈의 시작 부분)"

 

이렇게 진행하면 다음과 같은 결과를 얻을 수 있습니다. 

그런데 그림을 보시면 뼈 영역 뿐만 아니라 지저분한 배경 이 같이 나온 것을 확인할 수 있습니다. 

 

이것은 뼈영역 분할을 위해, 단지 밀도의 범위 (사실 따지고 보면 색상 영역)으로만 분할을 진행하였기 때문에

뼈 영역과 비슷한 밀도값을 가지게 되면 모두 분할되기 때문입니다. 

 

그렇다면 여기서 뼈만 예쁘게 뽑고 싶다면 어떻게 하면 될까요 ??

 

TO BE CONTINUE 😏