Documentation‎ > ‎

6. Segmentation




Watershed Segmentation

tipl::image<short,2> image_data,label_data;

// ... load image data here

tipl::filter::mean(image_data);
tipl::filter::sobel(image_data);
tipl::filter::mean(image_data);
tipl::segmentation::watershed(image_data,label_data);


   *The same function can be applied to 3d images.

#include "tipl/tipl.hpp"
#include <iostream>
int main()
{
    // 2D watershed
    tipl::grayscale_image image_data;
    tipl::image<short,2> label_data;
    tipl::io::bitmap bitmap_file;

    if(!bitmap_file.load_from_file("watershed2d.bmp"))
    {
        std::cout << "cannot read watershed2d.bmp" << std::endl;
        return 0;
    }
    bitmap_file >> image_data;

    tipl::filter::mean(image_data);
    tipl::filter::sobel(image_data);
    tipl::filter::mean(image_data);
    tipl::segmentation::watershed(image_data,label_data);

    tipl::io::nifti nifti_file;
    nifti_file << label_data;
    nifti_file.save_to_file("result_watershed2d.nii");
    return 0;
}

#include "tipl/tipl.hpp"
#include <iostream>
int main()
{
    tipl::image<short,3> image_data,label_data;
    tipl::io::nifti nifti_file;

    if(!nifti_file.load_from_file("watershed3d.nii"))
    {
        std::cout << "cannot read watershed3d.nii" << std::endl;
        return;
    }

    nifti_file >> image_data;

    tipl::filter::mean(image_data);
    tipl::filter::mean(image_data);
    tipl::filter::sobel(image_data);
    tipl::filter::mean(image_data);
    tipl::filter::mean(image_data);
    tipl::watershed(image_data,label_data);

    nifti_file << label_data;
    nifti_file.save_to_file("result_watershed3d.nii");
    return 0;
}

Fast Marching

The mast marching method follows the original study.


#include "tipl/tipl.hpp"
#include <iostream>
int main()
{
    tipl::image<short,2> image_data,label_data;
    tipl::io::dicom dicom_file;

    if(!dicom_file.load_from_file("dicom_2d.dcm"))
    {
        std::cout << "cannot read dicom_2d.dcm" << std::endl;
        return;
    }
    dicom_file >> image_data;
    tipl::filter::mean(image_data);
    tipl::filter::gradient_magnitude(image_data);

    tipl::image<float,2> time_data;
    tipl::pixel_index<2> t0_point(image_data.width()/2,image_data.height()/2,image_data.geometry());
    tipl::segmentation::fast_marching(image_data,time_data,t0_point);

    tipl::segmentation::otsu(time_data,label_data);
    tipl::io::nifti nifti_file;
    
    nifti_file << image_data;
    nifti_file.save_to_file("result_fast_mag.nii");
    nifti_file << time_data;
    nifti_file.save_to_file("result_fast_marching_time.nii");
    nifti_file << label_data;
    nifti_file.save_to_file("result_fast_marching_label.nii");

    return 0;
}

3D fast marching

#include "tipl/tipl.hpp"
#include <iostream>
int main()
{
    tipl::image<short,3> image_data,label_data;
    tipl::io::nifti nifti_file;
    if(!nifti_file.load_from_file("sample.nii"))
    {
        std::cout << "cannot read sample.nii" << std::endl;
        return 0;
    }
    nifti_file >> image_data;

    tipl::filter::sobel(image_data);
    tipl::image<float,3> time_data;
    tipl::segmentation::fast_marching(image_data,time_data,tipl::pixel_index<3>(83,128,172,image_data.geometry()));

    nifti_file >> image_data;
    for(size_t index = 0;index < image_data.size();++index)
        if(time_data[index] > 10000)
            image_data[index] = 0;
 
    nifti_file << image_data;
    nifti_file.save_to_file("result_fast_marching_3d.nii");
    return 0;
}


Otsu thresholding
#include "tipl/tipl.hpp"
#include <iostream>
int main()
{
    tipl::grayscale_image image_data,label_data;
    tipl::io::bitmap bitmap_file,out_file;
    if(!bitmap_file.load_from_file("otsu_test.bmp"))
    {
        std::cout << "cannot read otsu_test.bmp" << std::endl;
        return 0;
    }
    bitmap_file >> image_data;

    tipl::segmentation::otsu(image_data,label_data);
    tipl::normalize(label_data,255);
    out_file << label_data;
    out_file.save_to_file("result_otsu_method.bmp");
    return 0;
}


Graph Cut

This implementation follows Pedro F. Felzenszwalb and Daniel P. Huttenlocher, "Efficient Graph-Based Image Segmentation", International Journal of Computer Vision, Volume 59, Number 2, September 2004. The algorithm first sorts the weights between each neighboring pixels pair, and merge them using a threshold-based criteria. The performance of the algorithm depends largely on a inner difference parameter k, which affects merging criteria. Larger k results in large clusters, whereas small k the opposite. Another parameter, min_size, determines the minimum allowable cluster size. The clusters smaller than this size will be merged to any connecting neighboring clusters.

Usage

        void graph_cut(const image_type& I,label_type& out,float k,unsigned int min_size)    

Parameters

         I: the input image
         outthe segmentation result
         k: the inner difference parameter 
         min_size: the minimum allowable size of the segmented regions.     

Example


tipl::grayscale_image image_data;
tipl::image<short,2> label_data;
tipl::io::bitmap bitmap_file;
if(!bitmap_file.load_from_file("test.bmp"))
        {
            std::cout << "cannot read test.bmp" << std::endl;
            return 0;
        }
bitmap_file >> image_data;
tipl::segmentation::graph_cut(image_data,label_data,500,50);

tipl::image<unsigned char,2> output;
tipl::normalize(label_data,output,255);
bitmap_file << output;
bitmap_file.save_to_file("graph_cut_result.bmp");


Stochastic region competition

This implementation follows Yeh et al. "Stochastic region competition algorithm for Doppler sonography segmentation", Med. Phys. 39, 2867 (2012). The algorithm requires an initial contour to facilitate segmentation.

Usage

void stochastic_competition(const ImageType& src,LabelImageType& initial_contour,
                            double Zc = 30.0,double Zr = 5.0);

Parameters

    src: the original image
    initial_contour: the initial contour. 1: inside the contour 0:outside contour     
    Zc: The weighting on local edge. higher value => sensitive to edge  
    Zr: The weighting on region prior. higher value => smoother

Example


tipl::image<unsigned int,2> initial_contour;
tipl::image<float,2> image_data;
if(!bitmap_file.load_from_file("test.bmp"))
        {
            std::cout << "cannot read test.bmp" << std::endl;
            return 0;
        }
bitmap_file >> image_data;
tipl::segmentation::stochastic_competition(image_data,initial_contour,30,5);

Results


Initial contours (left) and the corresponding segmentation results (right)
Comments