Threshold an Image Using Otsu#

Synopsis#

Threshold an Image using Otsu’s method.

Results#

Input image

Input image#

Output image

Output image#

Code#

Python#

#!/usr/bin/env python

import itk
import argparse

parser = argparse.ArgumentParser(description="Threshold An Image Using Otsu.")
parser.add_argument("input_image")
parser.add_argument("output_image")
parser.add_argument("number_of_histogram_bins", type=int)
parser.add_argument("number_of_thresholds", type=int)
parser.add_argument("label_offset", type=int)
args = parser.parse_args()

PixelType = itk.UC
Dimension = 2

ImageType = itk.Image[PixelType, Dimension]

reader = itk.ImageFileReader[ImageType].New()
reader.SetFileName(args.input_image)

thresholdFilter = itk.OtsuMultipleThresholdsImageFilter[ImageType, ImageType].New()
thresholdFilter.SetInput(reader.GetOutput())

thresholdFilter.SetNumberOfHistogramBins(args.number_of_histogram_bins)
thresholdFilter.SetNumberOfThresholds(args.number_of_thresholds)
thresholdFilter.SetLabelOffset(args.label_offset)

rescaler = itk.RescaleIntensityImageFilter[ImageType, ImageType].New()
rescaler.SetInput(thresholdFilter.GetOutput())
rescaler.SetOutputMinimum(0)
rescaler.SetOutputMaximum(255)

writer = itk.ImageFileWriter[ImageType].New()
writer.SetFileName(args.output_image)
writer.SetInput(rescaler.GetOutput())

writer.Update()

C++#

#include "itkImageFileReader.h"
#include "itkOtsuMultipleThresholdsImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "itkImageFileWriter.h"

int
main(int argc, char * argv[])
{
  if (argc < 6)
  {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << std::endl;
    std::cerr << " <InputImage> <OutputImage> <NumberOfBins>";
    std::cerr << " <NumberOfThresholds> <LabelOffset>" << std::endl;
    return EXIT_FAILURE;
  }

  constexpr unsigned int Dimension = 2;
  using PixelType = unsigned char;
  using SizeType = itk::SizeValueType;

  const char * InputImage = argv[1];
  const char * OutputImage = argv[2];

  const auto NumberOfHistogramBins = static_cast<SizeType>(atoi(argv[3]));
  const auto NumberOfThresholds = static_cast<SizeType>(atoi(argv[4]));
  const auto LabelOffset = static_cast<PixelType>(atoi(argv[5]));

  using ImageType = itk::Image<PixelType, Dimension>;

  const auto input = itk::ReadImage<ImageType>(InputImage);

  using FilterType = itk::OtsuMultipleThresholdsImageFilter<ImageType, ImageType>;
  auto filter = FilterType::New();
  filter->SetInput(input);
  filter->SetNumberOfHistogramBins(NumberOfHistogramBins);
  filter->SetNumberOfThresholds(NumberOfThresholds);
  filter->SetLabelOffset(LabelOffset);

  FilterType::ThresholdVectorType thresholds = filter->GetThresholds();

  std::cout << "Thresholds:" << std::endl;

  for (double threshold : thresholds)
  {
    std::cout << threshold << std::endl;
  }

  std::cout << std::endl;

  using RescaleType = itk::RescaleIntensityImageFilter<ImageType, ImageType>;
  auto rescaler = RescaleType::New();
  rescaler->SetInput(filter->GetOutput());
  rescaler->SetOutputMinimum(0);
  rescaler->SetOutputMaximum(255);

  try
  {
    itk::WriteImage(rescaler->GetOutput(), OutputImage);
  }
  catch (const itk::ExceptionObject & e)
  {
    std::cerr << "Error: " << e << std::endl;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}

Classes demonstrated#

template<typename TInputImage, typename TOutputImage>
class OtsuMultipleThresholdsImageFilter : public itk::ImageToImageFilter<TInputImage, TOutputImage>

Threshold an image using multiple Otsu Thresholds.

This filter creates a labeled image that separates the input image into various classes. The filter computes the thresholds using the OtsuMultipleThresholdsCalculator and applies those thresholds to the input image using the ThresholdLabelerImageFilter. The NumberOfHistogramBins and NumberOfThresholds can be set for the Calculator. The LabelOffset can be set for the ThresholdLabelerImageFilter.

This filter also includes an option to use the valley emphasis algorithm from H.F. Ng, “Automatic thresholding for defect detection”, Pattern Recognition Letters, (27): 1644-1649, 2006. The valley emphasis algorithm is particularly effective when the object to be thresholded is small. See the following tests for examples: itkOtsuMultipleThresholdsImageFilterTest3 and itkOtsuMultipleThresholdsImageFilterTest4 To use this algorithm, simple call the setter: SetValleyEmphasis(true) It is turned off by default.

See

ScalarImageToHistogramGenerator

See

OtsuMultipleThresholdsCalculator

See

ThresholdLabelerImageFilter

ITK Sphinx Examples:

See itk::OtsuMultipleThresholdsImageFilter for additional documentation.