ContributedCode:ITKShapeGuidedSegmentation

From Wiki
Jump to: navigation, search

Comments about itkGeodesicActiveContourLevelSetImageFilter

For the last two weeks I've been trying to use this filter and I've not been able to make a simple example work. I'll describe my procedure in the following and provide the images and examples. I think there are many black holes in the documentation of this filter, so I intend to turn this into a small tutorial covering the obscure parts. All the images provided in this example can be found at: http://iie.fing.edu.uy/~juanc/files/itk/basic_example_center_prior/

My goal is to detect a simple shape in a binary image: image_center.png In the following I will describe all the steps I've made. If you want to see the results only, please jump to the results section. If you are interested in reproducing the examples, you can get the code in the code section.

training sample

In the first place I've constructed the training sample with the following conditions: all the images are registered between each other, centered, and the principal axis of the shape is parallel to the x-axis. See images here:

mm_00.png mm_01.png mm_02.png mm_03.png mm_04.png mm_05.png mm_06.png

After that I've modified the example in SignedDanielssonDistanceMapImageFilter.cxx, and made my own SignedDanielssonDistanceMapImageFilter2.cxx which computes the distance maps.

  1. compute distance maps from training samples (do this for the seven images)

SignedDanielssonDistanceMapImageFilter2 mm_00.png map_00.mha SignedDanielssonDistanceMapImageFilter2 m_01.png map_01.mha ... SignedDanielssonDistanceMapImageFilter2 m_06.png map_06.mha

Example result:

PCA decomposition

With that training sample I've written a piece of code EstimatePCAModel.cxx that uses itkImagePCAShapeModelEstimator class to compute the PCA decomposition of the training sample

  • all the modes are normalized by multiplying by its corresponding singular value (sqrt of eigenvalue).
  • when I do so, the values of the resulting modes are too big (mean shape has a maximum value of 10e5)
  • as an alternative, I first normalize the eigenvalues dividing all of the by the maximum. This was the best alternative so far.

  1. compute some (3) modes from the (7) training samples:

EstimatePCAModel 7 map_0%d.mha 3 mode_0%d.mha

Segmentation

After this I run the segmentation, for that purpose I've modified the example GeodesicActiveContourLevelSetImageFilter.cxx to be able to do various things:

  • receive an initial level set, rather than
  • receive an initial angle for the transformation parameters
  • save the final distance map, and not only a mask representing it
  • save a debug image with the intermediate results, once each 10 iterations
  • save all the debug images to a debug directory
  • the program receives the same arguments as the original, plus some arguments I've added to comply with the previous items.

cd /tmp

  1. create a debug directory

mkdir debug

  1. run the algorithm

GeodesicActiveContourShapePriorLevelSetImageFilter image_center.png output_0500.png 142 100 170 80 200 100 30 1 0 0.01 mode_00.mha 1 mode_0%d.mha 150 150 500 ini_08.mha 0 ls_0500.mha 1 > a_0500.log here is a short description of the parameters that I've added

  • 500: is the max. number of iterations
  • ini_08.mha is the initial level set (in ini_08.png you can see the curve)
  • 0: is the initial angle for the shape
  • ls_0500.mha: is the final level set
  • 1: is just a trick to make the code read the modes from 1 instead of 0.

results

example 05

Parameters:

  • translation: (150,150)
  • rotation: 0
  • weights (propagation, shape): 0 0.01
  • nb. modes: 1

Results:


See that the initial shape and the object to segment are the same, meaning that the algorithm should not have any problems to find it. In addition I've tried with several initializations and the results are the same. As you can see, the result is correct in shape and position but it is rotated.

example 06 (under construction)

This time I've put a very small weight on the shape term, and it seemed to work.

Parameters:

  • translation: (150,150)
  • rotation: 0
  • weights (propagation, shape): 0 1e-6
  • nb. modes: 1

Results:

comments

Here are the things I'm asumming about this filter.

  • The parameters of the transformation given as output have the following meaning: is the transformation required to apply to a pixel in the input image space to bring it to the shape space.
  • Using this interpretation, the transformation in this case should be composed of only a rotation.

Problems:

  • If I provide a null translation (0,0), the shape term doesn't work, presumably because the initial level set doesn't overlap the shape prior (after transformation of course). My way of check that it doesn't work is that the model computes a zero coefficient for the PCA decomposition.
  • The translation I'm using then is (150,150), which is the center of the image, this makes no sense to me, however is the only thing that works (partially).
  • In example05 the final level set gets the position of the shape model, and not the position of the object to detect. this could be because the shape term gets too much weight. Tried in example06 and seemed to work, I think there is some issue with the scaling of the PCA modes.

Ideas:

  • As suggested in the list, there is a possible bug in the GeodesicActiveContour segmentation

with Shape Prior framework, however, I've tried the fix provided and didn't help my case.

code

to make it work:

  1. untar the directory where desired

cd /tmp tar -zxvf shape.tar.gz cd shape

  1. configure

cmake .

  1. compile

make

references