连通域
一个区域D中,任一闭曲线所围区域,都属于区域D,称为“单连通区域”。
连通域形状分析
- 创建二值图像
1 using ImageType = itk::Image<unsigned char, 2>;
2
3 ImageType::Pointer CreateMaskImage()
4 {
5 ImageType::Pointer image = ImageType::New();
6 ImageType::IndexType start;
7 start.Fill(0);
8
9 ImageType::SizeType size;
10 size.Fill(128);
11
12 ImageType::RegionType region;
13 region.SetSize(size);
14 region.SetIndex(start);
15
16 image->SetRegions(region);
17 image->Allocate();
18
19 using IteratorType = itk::ImageRegionIteratorWithIndex< ImageType >;
20 IteratorType it(image, image->GetRequestedRegion());
21
22 for (it.GoToBegin(); !it.IsAtEnd(); ++it)
23 {
24 ImageType::IndexType idx = it.GetIndex();
25
26 // 创建空心圆 C=(50,50),R=15,r=5
27 if ((idx[0] - 50)*(idx[0] - 50) + (idx[1] - 50)*(idx[1] - 50) < 225 &&
28 (idx[0] - 50)*(idx[0] - 50) + (idx[1] - 50)*(idx[1] - 50) > 25)
29 it.Set(1);
30
31 // 创建圆 C=(70,80),r=7
32 else if ((idx[0] - 70)*(idx[0] - 70) + (idx[1] - 80)*(idx[1] - 80) < 49)
33 it.Set(1);
34
35 // 创建矩形 C=(100,100),W(120,110)
36 else if (idx[0] >= 100 && idx[0] <= 120 &&
37 idx[1] >= 100 && idx[1] <= 110)
38 it.Set(1);
39
40 else
41 it.Set(0);
42 }
43
44 return image;
45 }
生成图像如下
- 打印所有连通区域信息
1 typedef unsigned long LabelType;
2 typedef itk::ShapeLabelObject< LabelType, 2 > LabelObjectType;
3 typedef itk::LabelMap< LabelObjectType > LabelMapType;
4 typedef itk::BinaryImageToShapeLabelMapFilter< ImageType, LabelMapType > I2LType;
5 I2LType::Pointer i2l = I2LType::New();
6 i2l->SetInput(mask);
7 i2l->SetFullyConnected(false);
8 i2l->SetInputForegroundValue(1);
9 i2l->SetOutputBackgroundValue(0);
10 i2l->Update();
11
12 LabelMapType::Pointer labelMap = i2l->GetOutput();
13 for (unsigned int label = 1; label <= labelMap->GetNumberOfLabelObjects(); label++)
14 {
15 const LabelObjectType * labelObject = labelMap->GetLabelObject(label);
16 labelObject->Print(std::cout);
17 std::cout << "----------------------------------------" << std::endl;
18 }
打印信息如下:
1 ShapeLabelObject (000002469EAA6CE0)
2 RTTI typeinfo: class itk::ShapeLabelObject<unsigned long,2>
3 Reference Count: 1
4 LineContainer: 000002469EAA6CF0
5 Label: 1
6 NumberOfPixels: 616
7 PhysicalSize: 616
8 Perimeter: 127.254
9 NumberOfPixelsOnBorder: 0
10 PerimeterOnBorder: 0
11 PerimeterOnBorderRatio: 0
12 Elongation: 1
13 Flatness: 1
14 Roundness: 0.691393
15 Centroid: [50, 50]
16 BoundingBox: ImageRegion (000002469EAA6D20)
17 Dimension: 2
18 Index: [36, 36]
19 Size: [29, 29]
20 EquivalentSphericalRadius: 14.0028
21 EquivalentSphericalPerimeter: 87.9823
22 EquivalentEllipsoidDiameter: [28.0056, 28.0056]
23 PrincipalMoments: [61.9156, 61.9156]
24 PrincipalAxes:
25 1 0
26 0 1
27 FeretDiameter: 0
28 m_OrientedBoundingBoxSize: [0, 0]
29 m_OrientedBoundingBoxOrigin: [0, 0]
30 ----------------------------------------
31 ShapeLabelObject (000002469EAA7030)
32 RTTI typeinfo: class itk::ShapeLabelObject<unsigned long,2>
33 Reference Count: 1
34 LineContainer: 000002469EAA7040
35 Label: 2
36 NumberOfPixels: 145
37 PhysicalSize: 145
38 Perimeter: 41.524
39 NumberOfPixelsOnBorder: 0
40 PerimeterOnBorder: 0
41 PerimeterOnBorderRatio: 0
42 Elongation: 1
43 Flatness: 1
44 Roundness: 1.02799
45 Centroid: [70, 80]
46 BoundingBox: ImageRegion (000002469EAA7070)
47 Dimension: 2
48 Index: [64, 74]
49 Size: [13, 13]
50 EquivalentSphericalRadius: 6.79374
51 EquivalentSphericalPerimeter: 42.6863
52 EquivalentEllipsoidDiameter: [13.5875, 13.5875]
53 PrincipalMoments: [11.5172, 11.5172]
54 PrincipalAxes:
55 1 0
56 0 1
57 FeretDiameter: 0
58 m_OrientedBoundingBoxSize: [0, 0]
59 m_OrientedBoundingBoxOrigin: [0, 0]
60 ----------------------------------------
61 ShapeLabelObject (000002469EAA7170)
62 RTTI typeinfo: class itk::ShapeLabelObject<unsigned long,2>
63 Reference Count: 1
64 LineContainer: 000002469EAA7180
65 Label: 3
66 NumberOfPixels: 231
67 PhysicalSize: 231
68 Perimeter: 59.5651
69 NumberOfPixelsOnBorder: 0
70 PerimeterOnBorder: 0
71 PerimeterOnBorderRatio: 0
72 Elongation: 1.91485
73 Flatness: 1.91485
74 Roundness: 0.904522
75 Centroid: [110, 105]
76 BoundingBox: ImageRegion (000002469EAA71B0)
77 Dimension: 2
78 Index: [100, 100]
79 Size: [21, 11]
80 EquivalentSphericalRadius: 8.57494
81 EquivalentSphericalPerimeter: 53.8779
82 EquivalentEllipsoidDiameter: [12.3935, 23.7317]
83 PrincipalMoments: [10, 36.6667]
84 PrincipalAxes:
85 0 1
86 -1 -0
87 FeretDiameter: 0
88 m_OrientedBoundingBoxSize: [0, 0]
89 m_OrientedBoundingBoxOrigin: [0, 0]
90 ----------------------------------------
- 统计灰度信息
1 typedef itk::BinaryImageToStatisticsLabelMapFilter< ImageType, ImageType > ConverterType;
2 ConverterType::Pointer converter = ConverterType::New();
3 converter->SetInput(reader->GetOutput());
4 converter->SetFeatureImage(reader2->GetOutput());
5 converter->SetInputForegroundValue(1);
6 converter->SetFullyConnected(false);
7 converter->Update();
8 converter->GetOutput()->PrintLabelObjects();
- 过滤连通区域
1 typedef unsigned long LabelType;
2 typedef itk::ShapeLabelObject< LabelType, 2 > LabelObjectType;
3 typedef itk::LabelMap< LabelObjectType > LabelMapType;
4 typedef itk::BinaryImageToShapeLabelMapFilter< ImageType, LabelMapType > I2LType;
5 I2LType::Pointer i2l = I2LType::New();
6 i2l->SetInput(mask);
7 i2l->SetFullyConnected(false);
8 i2l->SetInputForegroundValue(1);
9 i2l->SetOutputBackgroundValue(0);
10 i2l->Update();
11
12 LabelMapType::Pointer labelMap = i2l->GetOutput();
13 for (unsigned int label = 1; label <= labelMap->GetNumberOfLabelObjects(); label++)
14 {
15 const LabelObjectType * labelObject = labelMap->GetLabelObject(label);
16 labelObject->Print(std::cout);
17 std::cout << "----------------------------------------" << std::endl;
18 }
19
20 std::vector< LabelObjectType::Pointer > filtered_label_objects;
21 for (LabelMapType::Iterator it(labelMap); !it.IsAtEnd(); ++it)
22 {
23 // 过滤条件
24 if (it.GetLabelObject()->GetRoundness() < 0.95)
25 filtered_label_objects.push_back(it.GetLabelObject());
26 }
27
28 for (int i = 0; i < filtered_label_objects.size(); i++)
29 {
30 labelMap->RemoveLabelObject(filtered_label_objects[i]);
31 }
32
33 typedef itk::LabelMapToBinaryImageFilter< LabelMapType, ImageType> L2IType;
34 L2IType::Pointer l2i = L2IType::New();
35 l2i->SetInput(labelMap);
36 l2i->Update();
37
38 using WriterType = itk::ImageFileWriter<ImageType>;
39 WriterType::Pointer writer = WriterType::New();
40 writer->SetFileName("mask.mha");
41 writer->SetInput(l2i->GetOutput());
42 writer->SetImageIO(itk::MetaImageIO::New());
43 writer->Update();
效果如下:
总结
通过连通域形状分析可以过滤到阈值分割中的错误部分,另外ITK还提供了itk::BinaryImageToStatisticsLabelMapFilter类,可以提供原图区域的统计信息。
itk::ShapeLabelObject提供的形状信息包括:
- NumberOfPixels 像素数
- PhysicalSize 物理尺寸
- Perimeter 周长
- NumberOfPixelsOnBorder 边界像素数
- PerimeterOnBorder 边界周长
- PerimeterOnBorderRatio 边界周长比
- Elongation 伸长率
- Flatness 平整度
- Roundness 圆度
- Centroid 质心
- BoundingBox 包围盒
- EquivalentSphericalRadius 等效球面半径
- EquivalentSphericalPerimeter 等效球面周长
- EquivalentEllipsoidDiameter 等效椭球直径
- PrincipalMoments 主力矩
- PrincipalAxes 主轴
- FeretDiameter
itk::StatisticsLabelObject提供的统计信息包括:
- Minimum
- Maximum
- Mean
- Sum
- StandardDeviation 标准差
- Variance 方差
- Median
- Skewness 偏态
- Kurtosis 峰度
- WeightedElongation 加权伸长率
- WeightedFlatness 加权平面度
- MaximumIndex
- MinimumIndex
- CenterOfGravity 重心
- WeightedPrincipalMoments 加权主力矩
- WeightedPrincipalAxes 加权主轴