您好,欢迎访问代理记账网站
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

ITK系列21_ 区域增长(领域连接)算法对脑部PNG图像进行二维分割

邻域连接

接下来的例子阐述了 itk::NeighborhoodConnectedImageFilter 的用法。这个滤波器是itk::ConnectedThresholdImageFilter 的一个相关变量。一方面,如果一个像素的亮度在用户提供的两个门限值之间,那么 ConnectedThresholdImageFilter 就接受这个像素作为区域内的一个像素。另一方面, NeighborhoodConnectedImageFilter 仅仅接受那些所有相邻像素的亮度都在范围内的像素。每个像素的邻域大小是由用户提供的整数范围来定义的。邻域的亮度仅仅替换当前像素的亮度的原因是区域中几乎不接受小的结构。这个滤波器的操作等同于伴随数学形态学的腐蚀运算应用 ConnectedThresholdImageFilter ,腐蚀使用和邻域提供NeighborhoodConnectedImageFilter 的形状相同的结构成员。

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

#include "itkNeighborhoodConnectedImageFilter.h"
#include "itkImage.h"
#include "itkCastImageFilter.h"
//使用 itk::CurvatureFlowImageFilter 在保护边缘时平滑图像
#include "itkCurvatureFlowImageFilter.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

int main( int argc, char *argv[] )
{

  /*if( argc < 7 )
    {
    std::cerr << "Missing Parameters." << std::endl;
    std::cerr << "Usage: " << argv[0]
              << " inputImage outputImage"
              << " seedX seedY"
              << " lowerThreshold upperThreshold" << std::endl;
    return EXIT_FAILURE;
    }*/

  /*现在我们使用一个特殊的像素类型和图像维来定义图像的类型。由于平滑滤波器的需
  要,这种情况下对像素使用浮点型数据类型*/
  typedef   float           InternalPixelType;
  const     unsigned int    Dimension = 2;
  typedef itk::Image< InternalPixelType, Dimension >  InternalImageType;
  //使用图像类型作为一个模板参数来对平滑滤波器类型进行实例化
  typedef unsigned char                            OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;

  typedef itk::CastImageFilter< InternalImageType, OutputImageType >
    CastingFilterType;
  CastingFilterType::Pointer caster = CastingFilterType::New();

  typedef  itk::ImageFileReader< InternalImageType > ReaderType;
  typedef  itk::ImageFileWriter<  OutputImageType  > WriterType;

  ReaderType::Pointer reader = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  reader->SetFileName( "BrainProtonDensitySlice.png" );
  writer->SetFileName( "Neighborhood_huizhi2.png");

  typedef itk::CurvatureFlowImageFilter<InternalImageType, InternalImageType>
    CurvatureFlowImageFilterType;
  //调用 New( ) 方式来定义滤波器并将结果指向一个 itk::SmartPointer 
  CurvatureFlowImageFilterType::Pointer smoothing =
                         CurvatureFlowImageFilterType::New();
  //现在我们声明区域生长滤波器的类型。这种情况下是 NeighborhoodConnectedImageFilter
  typedef itk::NeighborhoodConnectedImageFilter<InternalImageType,
                                    InternalImageType > ConnectedFilterType;
  //使用 New( ) 方式对这个类的一个文件进行结构化
  ConnectedFilterType::Pointer neighborhoodConnected
                                                 = ConnectedFilterType::New();
  /*现在到了连接一个简单的线性管道的时候。在管道的开头添加一个 reader 文件并在末尾
  添加一个 cast filter 和 writer 。由于只有仅仅一小部分图像文件格式支持浮点型数据类型,
  所以使用 cast filter 将浮点型数据类型转换成整型*/
  smoothing->SetInput( reader->GetOutput() );
  neighborhoodConnected->SetInput( smoothing->GetOutput() );
  caster->SetInput( neighborhoodConnected->GetOutput() );
  writer->SetInput( caster->GetOutput() );
  //滤波
  /*CurvatureFlowImageFilter 需要定义两个参数。下面是一个二维图像的常见值。当然它们
  也需要根据输入图像存在的噪声的数量进行适当的调整*/
  smoothing->SetNumberOfIterations( 5 );
  smoothing->SetTimeStep( 0.125 );
  
  const InternalPixelType lowerThreshold = atof( "180" );
  const InternalPixelType upperThreshold = atof( "210" );
  /*NeighborhoodConnectedImageFilter 有两个主要的参数需要设定,它们分别是为了确定是
  否包含在区域中的亮度值而制定的标准的上门限和下门限。这两个值设定得太接近势必会降
  低区域生长的机动性,而设定得太远必将整个图像都卷入区域中*/
  neighborhoodConnected->SetLower( lowerThreshold );
  neighborhoodConnected->SetUpper( upperThreshold );
  /*这里我们增加定义邻域大小的一个至关重要的参数,用来决定一个像素是否在这个区域
  中。邻域越大,这个滤波器在输入图像中滤掉噪声的稳定性就越强,但是计算需要的时间也
  将更长。这里我们选择每个维上两个长度r(2r+1)的一个滤波器,这将产生一个 5×5 像素的邻域*/
  InternalImageType::SizeType radius;

  radius[0] = 2;   // two pixels along X
  radius[1] = 2;   // two pixels along Y

  neighborhoodConnected->SetRadius( radius );
  /*由于在 ConnectedThresholdImageFilter 中,现在我们就必须提供在区域中能被输出像素所
  接受的亮度值而且至少是一个种子点来定义最初的区域*/
  InternalImageType::IndexType index;

  index[0] = atoi( "107" );
  index[1] = atoi( "69");

  neighborhoodConnected->SetSeed( index );
  neighborhoodConnected->SetReplaceValue( 255 );
  /*Writer 上的 Updata() 方法引发了管道的运行。通常在出现错误和抛出异议时, 从一个
  try / catch 模块调用 updata*/
  try
    {
    writer->Update();
    }
  catch( itk::ExceptionObject & excep )
    {
    std::cerr << "Exception caught !" << std::endl;
    std::cerr << excep << std::endl;
    }
  return EXIT_SUCCESS;
}

                     

                       输入图像                         分割出的白质组织                    分割出的脑室组织                     分割出的灰质组织

由于结合 ConnectedThresholdImageFilter ,使用 AddSeed( ) 方式就可以提供一些种子给滤波器。对比下图所示的输出和由 ConnectedThresholdImageFilter 生成的结果,你可能想得到邻域范围的值和查看它是如何影响分割对象边界的平滑度、分割区域的大小和计算所需要的时间。

 

ITK系列目录:

1 ITK图像数据表达之图像

2 ITK图像处理之图像滤波

3 ITK图像处理之图像分割

注:例程配套素材见系列目录


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进