Watershed control


(Pierre Cettour Janet) #1

Hello.
I am trying using itk::WatershedImageFilter (https://itk.org/Doxygen/html/classitk_1_1WatershedImageFilter.html), and I have some question about the parameter. I would like to control precisely the number of regions that return the filter. Is it possible with this filter? So if it is possible, how can I do that?
I did not precisely understand the Threshold parameter, is it possible to have more information about it.
To control the number of the region, we can use a seed watershed, so I also try the itk::MorphologicalWatershedFromMarkersImageFilter (https://itk.org/Doxygen/html/classitk_1_1MorphologicalWatershedFromMarkersImageFilter.html), but it connects some region whose have tall border. So it does not give me the result i want.
Thanks a lot for your help.
Best regards


(Dženan Zukić) #2

The Level parameter can be used to create a hierarchy of output images in constant time once an initial segmentation is done. A typical scenario might go like this: For the initial execution of the filter, set the Level to the maximum saliency value that you anticipate might be of interest. Once the initial Update() of this process object has finished, the Level can be manipulated anywhere below the initial setting without triggering a full update of the segmentation mini-pipeline. All that is now be required to produce the new output is a simple relabeling of the output image.

The above paragraph is from the Watershed filter’s documentation. There is no direct way to control the number of segments, but you can use the described trick to iteratively narrow down segments to the number you want. Just increase/decrease level and call Update() again.


(Pierre Cettour Janet) #3

Hello
thanks for your answer but dosn’t solve my problem.
I’d like to have some more infirmation about the both parameter : threshold and level. I’don’t understand how they work.
I’d like to know also why MorphologicalWatershedFromMarkersImageFilter does not find the tall border, even the one created.


(Dženan Zukić) #4

I did not understand threshold and level just from description either. So pick an image, pass it through the watershed filter with different parameters and then you will understand the effect they have. Here is an ad-hoc example I used:

#include "itkWatershedImageFilter.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkGradientMagnitudeRecursiveGaussianImageFilter.h"

//C:\Dev\itk-snap-src\Testing\TestData\WB.nrrd wb-seg.nrrd 0.01 0.4
int main(int argc, char *argv[])
{
    if (argc < 5)
    {
        std::cerr << "Missing Parameters " << std::endl;
        std::cerr << "Usage: " << argv[0];
        std::cerr << " inputImage  outputImage lowerThreshold  outputScaleLevel" << std::endl;
        return 1;
    }

    typedef short                             InPixelType;
    typedef float                             InternalPixelType;
    const   unsigned int                      Dimension = 3;


    typedef itk::Image< InternalPixelType, Dimension >  InternalImageType;
    typedef itk::Image< InPixelType, Dimension >  InImageType;

    typedef  itk::ImageFileReader< InImageType   >  ReaderType;

    ReaderType::Pointer reader = ReaderType::New();
    reader->SetFileName(argv[1]);
    reader->ReleaseDataFlagOn();
    reader->Update();

    typedef   itk::GradientMagnitudeRecursiveGaussianImageFilter<
        InImageType,
        InternalImageType
    > GradientMagnitudeFilterType;

    GradientMagnitudeFilterType::Pointer gradientMagnitudeFilter = GradientMagnitudeFilterType::New();

    gradientMagnitudeFilter->SetInput(reader->GetOutput());
    gradientMagnitudeFilter->SetSigma(1.0);
    gradientMagnitudeFilter->ReleaseDataFlagOn();
    gradientMagnitudeFilter->Update();

    typedef  itk::WatershedImageFilter<InternalImageType> WatershedFilterType;

    WatershedFilterType::Pointer watershedFilter = WatershedFilterType::New();

    watershedFilter->SetInput(gradientMagnitudeFilter->GetOutput());

    watershedFilter->SetThreshold(atof(argv[3]));
    watershedFilter->SetLevel(atof(argv[4]));
    watershedFilter->Update();

    typedef WatershedFilterType::OutputImageType  LabeledImageType;
    typedef  itk::ImageFileWriter< LabeledImageType  >        WriterType;
    WriterType::Pointer writer = WriterType::New();
    writer->SetFileName(argv[2]);
    writer->SetInput(watershedFilter->GetOutput());

    try
    {
        writer->Update();
    }
    catch (itk::ExceptionObject & excep)
    {
        std::cerr << "Exception caught !" << std::endl;
        std::cerr << excep << std::endl;
    }
    
    return 0;
}

(Matt McCormick) #5

In general the morphological watershed filters result in a much better segmentation.

For more information on the morphological watersheds and their parameters, see this Insight Journal article:

http://www.insight-journal.org/browse/publication/92