K-Means Clustering#
Warning
Fix Problem Contains problems not fixed from original wiki.
Synopsis#
KMeans clustering.
Results#
Note
Help Wanted Implementation of Results for sphinx examples containing this message. Reconfiguration of CMakeList.txt may be necessary. Write An Example <https://itk.org/ITKExamples/Documentation/Contribute/WriteANewExample.html>
Code#
C++#
#include <itkImage.h>
#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>
#include <itkScalarImageKmeansImageFilter.h>
int
main(int argc, char * argv[])
{
// sample usage
//./kMeansClustering input.jpg output.jpg 1 3 0 100 200
// verify command line arguments
if (argc < 5)
{
std::cerr << "Usage: " << std::endl;
std::cerr << argv[0];
std::cerr << " inputScalarImage outputLabeledImage contiguousLabels";
std::cerr << " numberOfClasses mean1 mean2... meanN " << std::endl;
return EXIT_FAILURE;
}
// parse command line arguments
const char * inputImageFileName = argv[1];
const char * outputImageFileName = argv[2];
const unsigned int useNonContiguousLabels = std::stoi(argv[3]);
const unsigned int numberOfInitialClasses = std::stoi(argv[4]);
constexpr unsigned int argoffset = 5;
if (static_cast<unsigned int>(argc) < numberOfInitialClasses + argoffset)
{
std::cerr << "Error: " << std::endl;
std::cerr << numberOfInitialClasses << " classes has been specified ";
std::cerr << "but no enough means have been provided in the command ";
std::cerr << "line arguments " << std::endl;
return EXIT_FAILURE;
}
std::vector<double> userMeans;
for (unsigned k = 0; k < numberOfInitialClasses; ++k)
{
const double userProvidedInitialMean = std::stod(argv[k + argoffset]);
userMeans.push_back(userProvidedInitialMean);
}
// Define the pixel type and dimension of the image that we intend to
// classify.
using PixelType = signed short;
constexpr unsigned int Dimension = 2;
using ImageType = itk::Image<PixelType, Dimension>;
const auto input = itk::ReadImage<ImageType>(inputImageFileName);
// Instantiate the ScalarImageKmeansImageFilter
using KMeansFilterType = itk::ScalarImageKmeansImageFilter<ImageType>;
auto kmeansFilter = KMeansFilterType::New();
kmeansFilter->SetInput(input);
// Make the output image intellegable by expanding the range of output image values, if desired
kmeansFilter->SetUseNonContiguousLabels(useNonContiguousLabels);
// initialize using the user input means
for (unsigned k = 0; k < numberOfInitialClasses; ++k)
{
kmeansFilter->AddClassWithInitialMean(userMeans[k]);
}
try
{
itk::WriteImage(kmeansFilter->GetOutput(), outputImageFileName);
}
catch (const itk::ExceptionObject & excp)
{
std::cerr << "Problem encountered while writing ";
std::cerr << " image file : " << outputImageFileName << std::endl;
std::cerr << excp << std::endl;
return EXIT_FAILURE;
}
// inspect the means
KMeansFilterType::ParametersType estimatedMeans = kmeansFilter->GetFinalMeans();
const unsigned int numberOfClasses = estimatedMeans.Size();
for (unsigned int i = 0; i < numberOfClasses; ++i)
{
std::cout << "cluster[" << i << "] ";
std::cout << " estimated mean : " << estimatedMeans[i] << std::endl;
}
return EXIT_SUCCESS;
}
Classes demonstrated#
-
template<typename TInputImage, typename TOutputImage = Image<unsigned char, TInputImage::ImageDimension>>
class ScalarImageKmeansImageFilter : public itk::ImageToImageFilter<TInputImage, TOutputImage> Classifies the intensity values of a scalar image using the K-Means algorithm.
Given an input image with scalar values, it uses the K-Means statistical classifier in order to define labels for every pixel in the image. The filter is templated over the type of the input image. The output image is predefined as having the same dimension of the input image and pixel type unsigned char, under the assumption that the classifier will generate less than 256 classes.
You may want to look also at the RelabelImageFilter that may be used as a postprocessing stage, in particular if you are interested in ordering the labels by their relative size in number of pixels.
- See
Image
- See
ImageKmeansModelEstimator
- See
KdTreeBasedKmeansEstimator, WeightedCentroidKdTreeGenerator, KdTree
- See
RelabelImageFilter
- ITK Sphinx Examples: