OTSU 分割(最大类间方差阈值分割)

实例19 OTSU算法对PNG图像进行单阈值二维分割

#include "itkOtsuThresholdImageFilter.h"//Otsu分割头文件
#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

int main( int argc, char * argv[] )
{
  /*if( argc < 5 )
    {
    std::cerr << "Usage: " << argv[0];
    std::cerr << " inputImageFile outputImageFile ";
    std::cerr << " insideValue    outsideValue   "  << std::endl;
    return EXIT_FAILURE;
    }*/

  //确定作为输入和输出图像的像素类型
  typedef  unsigned char  InputPixelType;
  typedef  unsigned char  OutputPixelType;
  const unsigned int      Dimension = 2;
 //使用输入输出图像的像素类型和维来定义它们的图像类型
  typedef itk::Image< InputPixelType,  Dimension >   InputImageType;
  typedef itk::Image< OutputPixelType, Dimension >   OutputImageType;
  //使用上面定义的输入输出图像的类型对滤波器类型进行实例化
  typedef itk::OtsuThresholdImageFilter<InputImageType, OutputImageType >  FilterType;
  //对一个 itk::ImageFileReader 类也进行实例化以便从文件中读取图像数据
  typedef itk::ImageFileReader< InputImageType >  ReaderType;
  
  typedef itk::ImageFileWriter< OutputImageType >  WriterType;
  //调用 New( ) 方式创建滤波器和 reader 并将结果指向 itk::Smartpointers 
  ReaderType::Pointer reader = ReaderType::New();
  FilterType::Pointer filter = FilterType::New();
  WriterType::Pointer writer = WriterType::New();

  //由 reader 得到的图像作为输入传递给 OtsuThresholdImageFilter
  reader->SetFileName("BrainProtonDensitySlice.png");
  filter->SetInput(reader->GetOutput());
  writer->SetInput( filter->GetOutput() );
 
  //outsideValue:给定阈值的上下限范围之外的像素的亮度值
  //insideValue:给定阈值的上下限范围之内的像素的亮度值
  const OutputPixelType outsideValue = atoi( "0" );//范围之外设置为纯黑
  const OutputPixelType insideValue  = atoi( "255" );//范围之内设置为纯白

  /*用 SetOutsideValue() 方式定义指向那些亮度值在给定阈值的上下限范围之外的像素的
  亮度值,用 SetInsideValue() 方式定义指向那些亮度值在给定阈值的上下限范围之内的像素的
  亮度值*/
  filter->SetOutsideValue( outsideValue );
  filter->SetInsideValue(  insideValue  );
  
  try
    {
    filter->Update();
    }
  catch( itk::ExceptionObject & excp )
    {
    std::cerr << "Exception thrown " << excp << std::endl;
    }
  
  //由滤波器内部计算得到的阈值。为了做到这些我们调用 GetThreshold 方式
  int threshold = filter->GetThreshold();
  std::cout << "Threshold = " << threshold << std::endl;
  
  writer->SetFileName( "BrainProtonDensitySlice_OTSU2.png" );
  try
    {
    writer->Update();
    }
  catch( itk::ExceptionObject & excp )
    {
    std::cerr << "Exception thrown " << excp << std::endl;
    }

  return EXIT_SUCCESS;
}

得到分割阈值为98:

ITK系列19_ 区域增长(OTSU算法)对PNG图像进行单阈值二维分割_图像分割

当给定阈值的上下限范围之内、之外的像素的亮度值分别给定为255(纯白显示)、0(纯黑显示)时:

 

                                    ITK系列19_ 区域增长(OTSU算法)对PNG图像进行单阈值二维分割_OTSU_02                                                        ITK系列19_ 区域增长(OTSU算法)对PNG图像进行单阈值二维分割_区域增长算法_03

                                                    输入图像                                                                           OTSU分割图

当给定阈值的上下限范围之内、之外的像素的亮度值分别给定为0(纯黑显示)、255(纯白显示)时:

                                     ITK系列19_ 区域增长(OTSU算法)对PNG图像进行单阈值二维分割_OTSU_02                                                       ITK系列19_ 区域增长(OTSU算法)对PNG图像进行单阈值二维分割_ITK_05         

                                                    输入图像                                                                           OTSU分割图

 

另外一个对像素进行分类的方法就是把错分类率降到最小。这样就要寻找一个阈值这个阈值将图像分为两部分,并且使得其中一部分落在另一部分那侧的直方图降到最小。这等同于将类中的差异最小化或者说将类之间的差异最大化。这个图展示了这种滤波器在进行分割时的自身局限性,这些局限性在处理含噪声的图像和由于领域偏见而缺乏空间均匀性的MRI图像时表现得尤为突出。

 

ITK系列目录:

1 ITK图像数据表达之图像

2 ITK图像处理之图像滤波

3 ITK图像处理之图像分割

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