1、代码
1 #include "itkConnectedComponentImageFilter.h"
2 #include "itkImage.h"
3 #include "itkImageFileReader.h"
4 #include "itkImageFileWriter.h"
5 #include "itkImageRegionIterator.h"
6 #include "itkLabelShapeKeepNObjectsImageFilter.h"
7
8 using namespace std;
9
10 void print(const std::string& file, itk::Image<unsigned char, 2>* image)
11 {
12 ofstream fout(file);
13 auto size = image->GetBufferedRegion().GetSize();
14 for (auto i = 0; i < size[0]; i++)
15 {
16 for (auto j = 0; j < size[1]; j++)
17 {
18 itk::Image<unsigned char, 2>::IndexType index{ {i,j} };
19 auto c = image->GetPixel(index);
20 fout << (int)c;
21 }
22 fout << std::endl;
23 }
24 }
25
26
27 int main(int argc, char *argv[])
28 {
29 // 1、获取二值化的分割结果mask
30 const char* input_path = "D:/documents/vs2019/itk_tutorial/largestcompent/build/RelWithDebInfo/left_femur.nrrd";// 图像保存的路径
31 using ImageType = itk::Image<unsigned char, 3>;
32 using ReaderFilter = itk::ImageFileReader<ImageType>;
33 auto reader = ReaderFilter::New();
34 reader->SetFileName(input_path);
35 reader->Update();
36 ImageType::Pointer image = reader->GetOutput();
37
38 // 2, 调用ITK的itkConnectedComponentImageFilter
39 using ConnectedComponentFilter = itk::ConnectedComponentImageFilter<ImageType, ImageType>;
40 auto connnectedComponentFilter = ConnectedComponentFilter::New();
41 connnectedComponentFilter->SetInput(image);
42 connnectedComponentFilter->Update();
43
44 // 3,调用ITK的itkLabelShapeKeepNObjectsImageFilter
45 using LabelShapeKeepNObjectsFilter = itk::LabelShapeKeepNObjectsImageFilter<ImageType>;
46 auto labelShapeKeepNObjectsFilter = LabelShapeKeepNObjectsFilter::New();
47 labelShapeKeepNObjectsFilter->SetInput(connnectedComponentFilter->GetOutput());
48 labelShapeKeepNObjectsFilter->SetBackgroundValue(0);
49 labelShapeKeepNObjectsFilter->SetNumberOfObjects(1);
50 labelShapeKeepNObjectsFilter->SetAttribute(
51 LabelShapeKeepNObjectsFilter::LabelObjectType::NUMBER_OF_PIXELS);
52 labelShapeKeepNObjectsFilter->Update();
53 // 4、将Label便签转换为1
54 typedef itk::RescaleIntensityImageFilter<ImageType, ImageType> RescaleFilterType;
55 RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New();
56 rescaleFilter->SetOutputMinimum(0);
57 rescaleFilter->SetOutputMaximum(1);
58 rescaleFilter->SetInput(labelShapeKeepNObjectsFilter->GetOutput());
59 rescaleFilter->Update();
60 //ImageType::Pointer largestccimage = rescaleFilter->GetOutput();
61
62 // 5,保存最大连通区域图像
63
64 const char* out_path = "D:/documents/vs2019/itk_tutorial/largestcompent/build/RelWithDebInfo/output.nii.gz"; // 保存输出结果的路径
65 using WriterFilter = itk::ImageFileWriter<ImageType>;
66 auto writer = WriterFilter::New();
67 writer->SetFileName(out_path);
68 writer->SetInput(rescaleFilter->GetOutput());
69 writer->Update();
70
71 return EXIT_SUCCESS;
72 }
2、效果
原始图像:
去除小连通域之后
3、主要函数介绍
itk::ConnectedComponentImageFilter<ImageType, OutputImageType>;
该filter值检测连通区域,不编号,不排序。
itk::LabelShapeKeepNObjectsImageFilter;
该filter对连通区域进行排序,然后只保留最大的几个连通区域。
itk::LabelImageToShapeLabelMapFilter< OutputImageType, LabelMapType> ;
为保留的每个连通区域打上标签(标号),编号顺序为找到不同区域的顺序.
虽然LabelShapeKeepNObjectsImageFilter调用SetAttribute 之后,按照attribute对连通区域大小进行了排序,但该排序并不反映在label上。即大的label并不一定对应大的size。反映在 SetNumberOfObjects(n) 设定保留区域之后,只保留排序后前n个区域的label。
itk::RescaleIntensityImageFilter<OutputImageType, ImageType>;
上一步图像只有标签,图像上没有直接的区别,本步对保留下来的不同连通区域进行不同的染色,以示区分。