ITK 实例5 领域连接算法对脑部PNG图像进行二维分割

发布时间 2023-08-16 14:55:55作者: 一杯清酒邀明月
  1 #include "itkNeighborhoodConnectedImageFilter.h"
  2 #include "itkImage.h"
  3 #include "itkCastImageFilter.h"
  4 //使用 itk::CurvatureFlowImageFilter 在保护边缘时平滑图像
  5 #include "itkCurvatureFlowImageFilter.h"
  6 #include "itkImageFileReader.h"
  7 #include "itkImageFileWriter.h"
  8  
  9 int main( int argc, char *argv[] )
 10 {
 11  
 12   /*if( argc < 7 )
 13     {
 14     std::cerr << "Missing Parameters." << std::endl;
 15     std::cerr << "Usage: " << argv[0]
 16               << " inputImage outputImage"
 17               << " seedX seedY"
 18               << " lowerThreshold upperThreshold" << std::endl;
 19     return EXIT_FAILURE;
 20     }*/
 21  
 22   /*现在我们使用一个特殊的像素类型和图像维来定义图像的类型。由于平滑滤波器的需
 23   要,这种情况下对像素使用浮点型数据类型*/
 24   typedef   float           InternalPixelType;
 25   const     unsigned int    Dimension = 2;
 26   typedef itk::Image< InternalPixelType, Dimension >  InternalImageType;
 27   //使用图像类型作为一个模板参数来对平滑滤波器类型进行实例化
 28   typedef unsigned char                            OutputPixelType;
 29   typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
 30  
 31   typedef itk::CastImageFilter< InternalImageType, OutputImageType >
 32     CastingFilterType;
 33   CastingFilterType::Pointer caster = CastingFilterType::New();
 34  
 35   typedef  itk::ImageFileReader< InternalImageType > ReaderType;
 36   typedef  itk::ImageFileWriter<  OutputImageType  > WriterType;
 37  
 38   ReaderType::Pointer reader = ReaderType::New();
 39   WriterType::Pointer writer = WriterType::New();
 40  
 41   reader->SetFileName( "BrainProtonDensitySlice.png" );
 42   writer->SetFileName( "Neighborhood_huizhi2.png");
 43  
 44   typedef itk::CurvatureFlowImageFilter<InternalImageType, InternalImageType>
 45     CurvatureFlowImageFilterType;
 46   //调用 New( ) 方式来定义滤波器并将结果指向一个 itk::SmartPointer 
 47   CurvatureFlowImageFilterType::Pointer smoothing =
 48                          CurvatureFlowImageFilterType::New();
 49   //现在我们声明区域生长滤波器的类型。这种情况下是 NeighborhoodConnectedImageFilter
 50   typedef itk::NeighborhoodConnectedImageFilter<InternalImageType,
 51                                     InternalImageType > ConnectedFilterType;
 52   //使用 New( ) 方式对这个类的一个文件进行结构化
 53   ConnectedFilterType::Pointer neighborhoodConnected
 54                                                  = ConnectedFilterType::New();
 55   /*现在到了连接一个简单的线性管道的时候。在管道的开头添加一个 reader 文件并在末尾
 56   添加一个 cast filter 和 writer 。由于只有仅仅一小部分图像文件格式支持浮点型数据类型,
 57   所以使用 cast filter 将浮点型数据类型转换成整型*/
 58   smoothing->SetInput( reader->GetOutput() );
 59   neighborhoodConnected->SetInput( smoothing->GetOutput() );
 60   caster->SetInput( neighborhoodConnected->GetOutput() );
 61   writer->SetInput( caster->GetOutput() );
 62   //滤波
 63   /*CurvatureFlowImageFilter 需要定义两个参数。下面是一个二维图像的常见值。当然它们
 64   也需要根据输入图像存在的噪声的数量进行适当的调整*/
 65   smoothing->SetNumberOfIterations( 5 );
 66   smoothing->SetTimeStep( 0.125 );
 67   
 68   const InternalPixelType lowerThreshold = atof( "180" );
 69   const InternalPixelType upperThreshold = atof( "210" );
 70   /*NeighborhoodConnectedImageFilter 有两个主要的参数需要设定,它们分别是为了确定是
 71   否包含在区域中的亮度值而制定的标准的上门限和下门限。这两个值设定得太接近势必会降
 72   低区域生长的机动性,而设定得太远必将整个图像都卷入区域中*/
 73   neighborhoodConnected->SetLower( lowerThreshold );
 74   neighborhoodConnected->SetUpper( upperThreshold );
 75   /*这里我们增加定义邻域大小的一个至关重要的参数,用来决定一个像素是否在这个区域
 76   中。邻域越大,这个滤波器在输入图像中滤掉噪声的稳定性就越强,但是计算需要的时间也
 77   将更长。这里我们选择每个维上两个长度r(2r+1)的一个滤波器,这将产生一个 5×5 像素的邻域*/
 78   InternalImageType::SizeType radius;
 79  
 80   radius[0] = 2;   // two pixels along X
 81   radius[1] = 2;   // two pixels along Y
 82  
 83   neighborhoodConnected->SetRadius( radius );
 84   /*由于在 ConnectedThresholdImageFilter 中,现在我们就必须提供在区域中能被输出像素所
 85   接受的亮度值而且至少是一个种子点来定义最初的区域*/
 86   InternalImageType::IndexType index;
 87  
 88   index[0] = atoi( "107" );
 89   index[1] = atoi( "69");
 90  
 91   neighborhoodConnected->SetSeed( index );
 92   neighborhoodConnected->SetReplaceValue( 255 );
 93   /*Writer 上的 Updata() 方法引发了管道的运行。通常在出现错误和抛出异议时, 从一个
 94   try / catch 模块调用 updata*/
 95   try
 96     {
 97     writer->Update();
 98     }
 99   catch( itk::ExceptionObject & excep )
100     {
101     std::cerr << "Exception caught !" << std::endl;
102     std::cerr << excep << std::endl;
103     }
104   return EXIT_SUCCESS;
105 }