Hello,<br><br>I have segmented the ventricles from an image using a connected threshold image filter.<br>I then tried to convert my outputted segmentation to a label map filter and then to get the label's attributes.<br>
<br>I am using parts of the example code attribute_values.cxx that is described in section 9.4 of<br>Gaetan Lehmann's paper: "Label object representation and manipulation with ITK"<br> <br>My problem is that my code is telling me that the number of labels is 0.<br>
How do I apply a label to my segmented ventricles?<br><br>Below is my code:<br><br>/*<br>to run type:<br>./ConnectedThresholdImageFilter correctedsubject5.dcm outsubject5.dcm 103 142 95 17100 17300<br>*/<br><br>#if defined(_MSC_VER)<br>
#pragma warning ( disable : 4786 )<br>#endif<br><br>#ifdef __BORLANDC__<br>#define ITK_LEAN_AND_MEAN<br>#endif<br><br><br>#include "itkConnectedThresholdImageFilter.h"<br><br>#include "itkImage.h"<br>#include "itkCastImageFilter.h"<br>
<br>#include "itkCurvatureFlowImageFilter.h"<br><br>#include "itkImageFileReader.h"<br>#include "itkImageFileWriter.h"<br><br>#include "itkGDCMImageIO.h"<br><br>#include "itkVersion.h"<br>
<br>#include "itkOrientedImage.h"<br>#include "itkMinimumMaximumImageFilter.h"<br><br>#include "itkGDCMImageIO.h"<br>#include "itkGDCMSeriesFileNames.h"<br>#include "itkNumericSeriesFileNames.h"<br>
<br>#include "itkImageSeriesReader.h"<br>#include "itkImageSeriesWriter.h"<br><br>#include "itkResampleImageFilter.h"<br>#include "itkShiftScaleImageFilter.h"<br><br>#include "itkIdentityTransform.h"<br>
#include "itkLinearInterpolateImageFunction.h"<br><br>#include <itksys/SystemTools.hxx><br><br>#include "gdcm/src/gdcmFile.h"<br>#include "gdcm/src/gdcmUtil.h"<br><br>#include <string><br>
<br>//added per attribute_values.cxx<br>#include "itkImageFileReader.h"<br><br>#include "itkShapeLabelObject.h"<br>//#include "itkStatisticsLabelObject.h"<br><br>#include "itkLabelMap.h"<br>
<br>#include "itkBinaryImageToShapeLabelMapFilter.h"<br>//#include "itkBinaryImageToStatisticsLabelMapFilter.h"<br><br>//end of added code<br><br>int main( int argc, char *argv[])<br>{<br> if( argc < 7 )<br>
{<br> std::cerr << "Missing Parameters " << std::endl;<br> std::cerr << "Usage: " << argv[0];<br> std::cerr << " inputImage outputImage seedX seedY seedZ lowerThreshold upperThreshold" << std::endl;<br>
<br> return 1;<br> }<br><br> typedef float InternalPixelType;<br> <br> const unsigned int Dimension = 3;<br><br> typedef itk::Image< InternalPixelType, Dimension > InternalImageType;<br>
<br> typedef signed short OutputPixelType;<br><br> typedef itk::Image< OutputPixelType, Dimension > OutputImageType;<br> typedef itk::Image< float, Dimension > OutputImageType2;<br> typedef itk::CastImageFilter< InternalImageType, OutputImageType ><br>
CastingFilterType;<br> CastingFilterType::Pointer caster = CastingFilterType::New();<br> <br> const unsigned int ImageDimension = 3;<br> typedef signed short PixelType;<br><br> typedef itk::Image< PixelType, ImageDimension > FixedImageType;<br>
typedef itk::Image< float, ImageDimension > FloatImageType;<br><br> typedef itk::ImageFileReader< FixedImageType > ReaderType;<br> typedef itk::ImageFileWriter< OutputImageType > WriterType;<br>
typedef itk::ImageFileWriter< FloatImageType > WriterType2;<br><br> ReaderType::Pointer reader = ReaderType::New();<br> WriterType::Pointer writer = WriterType::New();<br> WriterType2::Pointer writer2 = WriterType2::New();<br>
<br> typedef itk::GDCMImageIO ImageIOTypefixed;<br> ImageIOTypefixed::Pointer gdcmImageIOfixed = ImageIOTypefixed::New();<br> reader->SetImageIO( gdcmImageIOfixed );<br><br> typedef itk::GDCMImageIO ImageIOTypefixed2;<br>
ImageIOTypefixed2::Pointer gdcmImageIOfixed2 = ImageIOTypefixed2::New();<br><br> reader->SetFileName( argv[1] );<br> <br> reader->Update();<br><br> typedef itk::CurvatureFlowImageFilter< InternalImageType, InternalImageType ><br>
CurvatureFlowImageFilterType;<br> <br> CurvatureFlowImageFilterType::Pointer smoothing =<br> CurvatureFlowImageFilterType::New();<br><br> typedef itk::ConnectedThresholdImageFilter< InternalImageType,<br>
InternalImageType > ConnectedFilterType;<br><br> ConnectedFilterType::Pointer connectedThreshold = ConnectedFilterType::New();<br><br> typedef signed short InputAPixelType;<br> typedef float OutputBPixelType;<br>
<br> typedef itk::Image< InputAPixelType, 3 > InputAImageType;<br> typedef itk::Image< OutputBPixelType, 3 > OutputBImageType;<br><br> typedef itk::CastImageFilter< InputAImageType, OutputBImageType > CastFilterType;<br>
<br> CastFilterType::Pointer castFilter = CastFilterType::New();<br><br><br> castFilter->SetInput( reader->GetOutput() );<br> <br><br> connectedThreshold->SetInput( castFilter->GetOutput() );<br><br> caster->SetInput( connectedThreshold->GetOutput() );<br>
<br><br> smoothing->SetNumberOfIterations( 20 ); //was 5<br> smoothing->SetTimeStep( 0.125 );<br> <br> const InternalPixelType lowerThreshold = atof( argv[6] );<br> const InternalPixelType upperThreshold = atof( argv[7] );<br>
<br> connectedThreshold->SetLower( lowerThreshold );<br> connectedThreshold->SetUpper( upperThreshold );<br> <br> connectedThreshold->SetReplaceValue( 255 );<br><br> InternalImageType::IndexType index;<br>
<br> index[0] = atoi( argv[3] );<br> index[1] = atoi( argv[4] );<br> <br> //added<br> index[2] = atoi( argv[5] );<br><br> std::cout << index << std::endl;<br><br> // Software Guide : BeginCodeSnippet<br>
connectedThreshold->SetSeed( index );<br> <br> //obtain a 5 x 5 bounding region of seeds<br> int ii, jj, kk;<br><br> ii = index[0];<br> jj = index[1];<br> kk = index[2];<br><br> for (int i = ii; i < ii + 5; i++)<br>
for (int j = jj; j < jj + 5; j++)<br> for (int k = kk; k < kk + 5; k++)<br> {<br> <br> index[0] = i;<br> index[1] = j;<br> index[2] = k;<br> connectedThreshold->AddSeed( index );<br>
}<br><br> for (int i = ii; i > ii - 5; i--)<br> for (int j = jj; j > jj - 5; j--)<br> for (int k = kk; k > kk - 5; k--)<br> {<br> <br> index[0] = i;<br> index[1] = j;<br> index[2] = k;<br>
connectedThreshold->AddSeed( index );<br> }<br><br> connectedThreshold->Print(std::cout,17100);<br> <br> typedef itk::MetaDataDictionary DictionaryType;<br> <br> DictionaryType inputdict = reader->GetMetaDataDictionary();<br>
<br> writer->SetMetaDataDictionary( inputdict );<br> <br> writer->SetFileName( argv[2] );<br><br> //added per attribute_values.cxx<br><br> // define the object type. Here the ShapeLabelObject type<br> // is chosen in order to read some attribute related to the shape<br>
// of the objects (by opposition to the content of the object, with<br> // the StatisticsLabelObejct).<br> typedef unsigned long LabelType;<br> <br> typedef itk::ShapeLabelObject< LabelType, 3 > LabelObjectType;<br>
<br> typedef itk::LabelMap< LabelObjectType > LabelMapType;<br><br> // convert the image in a collection of objects<br> typedef itk::BinaryImageToLabelMapFilter< InternalImageType, LabelMapType > ConverterType;<br>
<br> ConverterType::Pointer converter = ConverterType::New();<br> <br> converter->SetInput( connectedThreshold->GetOutput() );<br><br> //converter->SetForegroundValue( atoi(argv[2]) );<br> //converter->SetForegroundValue( 255 );<br>
<br> // valuate the attributes with the dedicated filter: ShapeLabelMapFilter<br><br> typedef itk::ShapeLabelMapFilter< LabelMapType > ShapeFilterType;<br> ShapeFilterType::Pointer shape = ShapeFilterType::New();<br>
shape->SetInput( converter->GetOutput() );<br><br> shape->Update();<br><br><br> // then we can read the attribute values we're interested in. The BinaryImageToShapeLabelMapFilter<br> // produce consecutive labels, so we can use a for loop and GetLabelObject() method to retrieve<br>
// the label objects. If the labels are not consecutive, the GetNthLabelObject() method must be<br> // use instead of GetLabelObject(), or an iterator on the label object container of the label map.<br> LabelMapType::Pointer labelMap = shape->GetOutput();<br>
<br> std::cout << "Number of label objects = " << labelMap->GetNumberOfLabelObjects() << std::endl;<br><br><br> for( unsigned int label=1; label<=labelMap->GetNumberOfLabelObjects(); label++ )<br>
{<br> // we don't need a SmartPointer of the label object here, because the reference is kept in<br> // in the label map.<br> const LabelObjectType * labelObject = labelMap->GetLabelObject( label );<br>
std::cout << label << "\t" << labelObject->GetPhysicalSize() << "\t" << labelObject->GetCentroid() << std::endl;<br> }<br><br> writer->SetInput( caster->GetOutput() );<br>
<br> try<br> {<br> writer->Update();<br> }<br> catch( itk::ExceptionObject & excep )<br> {<br> std::cerr << "Exception caught !" << std::endl;<br> std::cerr << excep << std::endl;<br>
}<br><br> std::cout << "output from reader->GetOutput()->GetDirection()" << std::endl;<br> std::cout << reader->GetOutput()->GetDirection() << std::endl;<br> <br> std::cout << "output from castFilter->GetOutput()->GetDirection()" << std::endl;<br>
std::cout << castFilter->GetOutput()->GetDirection() << std::endl;<br> <br> std::cout << "output from connectedThreshold->GetOutput()->GetDirection()" << std::endl;<br> std::cout << connectedThreshold->GetOutput()->GetDirection() << std::endl;<br>
<br> std::cout << "output from caster->GetOutput()->GetDirection()" << std::endl;<br> std::cout << caster->GetOutput()->GetDirection() << std::endl;<br><br> return 0;<br>}<br>
<br>