1 #include "itkConfidenceConnectedImageFilter.h"//包含置信连接类
2 //图像中存在的噪声会降低这个滤波器生长大面积区域的能力。当面对噪声图像时,通常
3 //是使用一个边缘保留平滑滤波器
4 #include "itkCastImageFilter.h"//滤波器
5 #include "itkCurvatureFlowImageFilter.h"//边缘保留平滑滤波器
6 #include "itkImageFileReader.h"
7 #include "itkImageFileWriter.h"
8
9 //ConfidenceConnected Image Filter 使用的标准是基于当前区域的简单统计上的。首先,算法计算包含在区域中的所
10 //有像素亮度的平均值和标准差。用户提供一个因子用来乘以标准差并定义一个平均值的范
11 //围。相邻像素中亮度值在这个范围内的将包含到这个区域中。当没有更多的像素符合这个标
12 //准时,算法将结束它的第一次迭代。使用包含在区域内的所有像素再次计算亮度值的平均值
13 //和标准差。这个平均值和标准差定义一个新的亮度范围,用来查看当前区域的邻域并评价它
14 //们的亮度是否落在这个范围内。重复这个迭代过程直到没有新的像素再加进来或者已经达到
15 //了迭代器的最大数目。下面的式子阐述了这个滤波器的使用范围:
16 //I(X) ∈[m− fσ, m + fσ]
17 //其中 m 和 σ 分别是区域亮度的平均值和标准差, f 是用户提供的一个因子, I() 是图像,
18 //X 是区域中特殊相邻像素的位置
19
20 int main( int argc, char *argv[] )
21 {
22 //if( argc < 5 )
23 // {
24 // std::cerr << "Missing Parameters " << std::endl;
25 // std::cerr << "Usage: " << argv[0];
26 // std::cerr << " inputImage outputImage seedX seedY " << std::endl;
27 // return EXIT_FAILURE;
28 // }
29 /*现在我们使用一个像素类型和一个特殊的维来定义图像类型。由于需要使用平滑滤波
30 器,所以这种情况下对像素使用浮点型数据类型*/
31 typedef float InternalPixelType;
32 const unsigned int Dimension = 2;
33 typedef itk::Image< InternalPixelType, Dimension > InternalImageType;
34
35 typedef unsigned char OutputPixelType;
36 typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
37
38 typedef itk::CastImageFilter< InternalImageType, OutputImageType >
39 CastingFilterType;
40 CastingFilterType::Pointer caster = CastingFilterType::New();
41
42 typedef itk::ImageFileReader< InternalImageType > ReaderType;
43 typedef itk::ImageFileWriter< OutputImageType > WriterType;
44
45 ReaderType::Pointer reader = ReaderType::New();
46 WriterType::Pointer writer = WriterType::New();
47
48 reader->SetFileName( "BrainProtonDensitySlice.png" );
49 writer->SetFileName( "BrainProtonDensitySlice_connect2.png" );
50
51 //使用图像类型作为模板参数来对平滑滤波器进行实例化
52 typedef itk::CurvatureFlowImageFilter< InternalImageType, InternalImageType >
53 CurvatureFlowImageFilterType;
54 //调用 New( ) 方式来创建滤波器并将接指向 itk::SmartPointer
55 CurvatureFlowImageFilterType::Pointer smoothing =
56 CurvatureFlowImageFilterType::New();
57
58 /*现在我们声明区域生长滤波器的类型,本例中使用 ConnectedThresholdImageFilter*/
59 typedef itk::ConfidenceConnectedImageFilter<
60 InternalImageType, InternalImageType> ConnectedFilterType;
61 //然后我们使用 New( ) 方式构造这种类的一个滤波器
62 ConnectedFilterType::Pointer confidenceConnected = ConnectedFilterType::New();
63 /*现在到了创建一个简单的线性管道的时候。在管道的开头添加一个 reader 件头并在末尾
64 添加一个 cast filter 和 writer 。由于只有仅仅一小部分图像文件格式支持浮点型数据类型,
65 所以使用 cast filter 将浮点型数据类型转换成整型*/
66 smoothing->SetInput( reader->GetOutput() );//滤波
67 confidenceConnected->SetInput( smoothing->GetOutput() );//区域增长置信连接
68 caster->SetInput( confidenceConnected->GetOutput() );//类型转换,浮点型数据类型转换成整型
69 writer->SetInput( caster->GetOutput() );
70
71 //滤波
72 /*CurvatureFlowImageFilter 需要定义两个参数。下面是一个二维图像的常见值。当然它们
73 也需要根据输入图像存在的噪声的数量进行适当的调整*/
74 smoothing->SetNumberOfIterations( 5 );
75 smoothing->SetTimeStep( 0.125 );
76
77
78 //区域增长-置信连接
79 /*ConfidenceConnectedImageFilter 需要定义两个参数。第一个,定义亮度范围大小的因子
80 f 。乘法因子太小将限制当前区域中很多有相似亮度的像素;乘法因子太大将放松接受条件
81 并导致区域过度生长。值太大就会使得这些区域生长到邻近区域,而这些邻近区域实际上可
82 能属于独立的解剖结构*/
83 confidenceConnected->SetMultiplier( 2.5 );//定义亮度范围大小的因子f
84 /*迭代器的数目是基于被分割的解剖学结构亮度的均匀性之上指定的。均匀性高的区域仅
85 需要一对迭代器。带有 ramp 效果的区域,如带有不同一领域的 MRI 图像,就需要更多的迭代
86 器。实际上,精心选择乘法因子似乎比迭代器的数目更加重要。然而,务必紧记这个算法毫
87 无疑问需要集中于一个稳定的区域。在这个算法上使用过多的迭代器将很有可能使这个区域
88 吞没整个图像*/
89 confidenceConnected->SetNumberOfIterations( 5 );//迭代器数目(迭代次数)
90 /*这个滤波器的输出是一个二值图像,这个二值图像除了分割出的区域外到处都是零值像
91 素。区域中的亮度值是由 SetReplaceValue() 方式来选择的*/
92 confidenceConnected->SetReplaceValue( 255 );
93
94 /*这个算法的实例化需要用户提供一个种子点。将这个点选在被分割的解剖学结构的典型
95 区域是很便捷的。种子区域周围的一个小的邻域将用来计算包含在标准里的最初的平均值和
96 标准差。种子是以一种 itk::Index 的形式传递给 SetSeed() 方式的*/
97 InternalImageType::IndexType index;
98 //设置种子点坐标位置
99 index[0] = atoi( "107" );
100 index[1] = atoi( "69" );
101 confidenceConnected->SetSeed( index );
102 /*种子区域周围邻域最初的大小是使用 SetInitialNeighborhoodRadius() 方式来定义的。这
103 个邻域将定义成一个拥有 2r + 1 个像素的 N(二维图像为2,三维为3) 维矩形区域,其中 r 是作为最初邻域范围的传递值*/
104 confidenceConnected->SetInitialNeighborhoodRadius( 2 );//设置最初邻域范围的传递值r 即5像素矩阵
105 /*writer 上的 Updata() 方法引发了管道的运行。通常在出现错误和抛出异议时, 从一个
106 try / catch 模块调用 updata*/
107 try
108 {
109 writer->Update();
110 }
111 catch( itk::ExceptionObject & excep )
112 {
113 std::cerr << "Exception caught !" << std::endl;
114 std::cerr << excep << std::endl;
115 }
116
117 return EXIT_SUCCESS;
118 }