[ITK-users] segmentation a 3D image takes a long time , any help to speed it ?

alaamegawer alaamegawer at yahoo.com
Tue Mar 25 07:37:29 EDT 2014


Hi All 

I'm trying to segment the lung from 3D Ct image using this algorithm 
1- determine the optimal threshold 
2- using connected region to delete the unwanted region 
3- filling holes by using closing operation 

but the algorithm is very slow it takes more than 10 min  

so please i want to ask if any one can guide me to speed it .

and what's the difference between segment the lung slice per slice or as a
whole 

image information

NDims = 3
DimSize = 512  512  148
ElementSpacing =  0.69531  0.69531  2.00001
Position =  -17.76523  -42.56523  -6.5
ElementByteOrderMSB = False
ElementType = MET_USHORT
ElementDataFile = ImageSet_5.img



my code is 


#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "itkImageRegionIterator.h"
#include "itkImageConstIterator.h"
#include "itkNeighborhoodConnectedImageFilter.h"
#include "itkMaskNegatedImageFilter.h"
#include "itkMaskImageFilter.h"
#include "itkVotingBinaryIterativeHoleFillingImageFilter.h"
#include "itkBinaryErodeImageFilter.h"
#include "itkBinaryDilateImageFilter.h"
#include "itkBinaryBallStructuringElement.h"
#include "itkRegionOfInterestImageFilter.h"

#define IMAGE_DIMENSIONS 3
#define IMAGE_DATA_EXT short
#define IMAGE_DATA_INT unsigned short
#define INITIAL_THRESHOLD_VALUE 128


typedef itk::Image< IMAGE_DATA_EXT, IMAGE_DIMENSIONS > ImageTypeExt;
typedef itk::Image< IMAGE_DATA_INT, IMAGE_DIMENSIONS > ImageTypeInt;
typedef itk::ImageFileReader< ImageTypeInt > ReaderType;
typedef itk::ImageFileWriter< ImageTypeInt > WriterType;
typedef itk::RescaleIntensityImageFilter< ImageTypeInt, ImageTypeInt >
RescaleType;
typedef itk::BinaryThresholdImageFilter < ImageTypeInt, ImageTypeInt > 
ThresholdFilterType;
typedef itk::ImageRegionConstIterator< ImageTypeInt > ConstIteratorType;
typedef itk::ImageRegionIterator< ImageTypeInt > IteratorType;
typedef itk::NeighborhoodConnectedImageFilter< ImageTypeInt, ImageTypeInt >
ConnectedFilterType;
typedef itk::MaskNegatedImageFilter<ImageTypeInt, ImageTypeInt,
ImageTypeInt> MaskNegatedFilterType;
typedef itk::MaskImageFilter<ImageTypeInt, ImageTypeInt> MaskFilterType;
typedef itk::VotingBinaryIterativeHoleFillingImageFilter< ImageTypeInt >
HoleFillingType;
typedef itk::BinaryBallStructuringElement < IMAGE_DATA_INT, IMAGE_DIMENSIONS
> StructuringElementType;
typedef itk::BinaryErodeImageFilter < ImageTypeInt, ImageTypeInt,
StructuringElementType> ErodeFilterType;
typedef itk::BinaryDilateImageFilter < ImageTypeInt, ImageTypeInt,
StructuringElementType> DilateFilterType;
typedef itk::RegionOfInterestImageFilter< ImageTypeInt, ImageTypeInt >
ROIFilterType;


void invertBinaryValues(ImageTypeInt *image) {
	IteratorType iterator(image, image->GetLargestPossibleRegion());
	for(iterator.GoToBegin(); !iterator.IsAtEnd(); ++iterator) {
		iterator.Set(1 - iterator.Value());
	}
}

int main (int argc, char *argv[])
{
	const char * inputFilename  ="C:/Users/Desktop/lung images/ImageSet_5.mha";
	const char * outputFilename ="C:/Users/Desktop/lung
images/ImageSettest.mha";

	ReaderType::Pointer reader = ReaderType::New();
	reader->SetFileName(inputFilename);
	WriterType::Pointer writer = WriterType::New();
	RescaleType::Pointer rescalerFilter = RescaleType::New();
	rescalerFilter->SetInput(reader->GetOutput());
	rescalerFilter->SetOutputMinimum(0);
	rescalerFilter->SetOutputMaximum(255);
	
	IMAGE_DATA_INT thresholdValue = INITIAL_THRESHOLD_VALUE;
	IMAGE_DATA_INT thresholdValueOLD = INITIAL_THRESHOLD_VALUE + 1;
	ImageTypeInt::IndexType index;
	ThresholdFilterType::Pointer thresholdFilter = ThresholdFilterType::New();
	thresholdFilter->SetOutsideValue(1); 
	thresholdFilter->SetInsideValue(0); 
	thresholdFilter->SetLowerThreshold(0);
	thresholdFilter->SetInput(rescalerFilter->GetOutput());
	
	while(thresholdValue != thresholdValueOLD) {
		unsigned long long averageAbove, averageBelow;
		unsigned int quantityAbove, quantityBelow;
		
		averageAbove = averageBelow = quantityAbove = quantityBelow = 0;
		
		thresholdFilter->SetUpperThreshold(thresholdValue);
		thresholdFilter->Update();

		ConstIteratorType threshold_it(thresholdFilter->GetOutput(),
thresholdFilter->GetOutput()->GetLargestPossibleRegion());
		ConstIteratorType reader_it(rescalerFilter->GetOutput(),
rescalerFilter->GetOutput()->GetLargestPossibleRegion());
		for(threshold_it.GoToBegin(), reader_it.GoToBegin();
!threshold_it.IsAtEnd(); ++threshold_it, ++reader_it) {
			if(threshold_it.Get()) {
				averageAbove += reader_it.Get();
				quantityAbove++;
			}
			else {
				averageBelow += reader_it.Get();
				quantityBelow++;
			}
		}
		if(quantityAbove==0)quantityAbove=1;
		if(quantityBelow==0)quantityBelow=1;

		averageAbove /= quantityAbove;
		averageBelow /= quantityBelow;
		thresholdValueOLD = thresholdValue;
		thresholdValue = (averageAbove + averageBelow)/2;
	}
	invertBinaryValues(thresholdFilter->GetOutput());

	ConnectedFilterType::Pointer neighborhoodConnected =
ConnectedFilterType::New();
 	neighborhoodConnected->SetInput( thresholdFilter->GetOutput() );
	neighborhoodConnected->SetLower(1);
	neighborhoodConnected->SetUpper(1);
	neighborhoodConnected->SetReplaceValue(1);//TODO: magic number
	//Seeds
	index[0] = 0;
	index[1] = 0;
	index[2] = 0;
	neighborhoodConnected->SetSeed(index);
	{
		unsigned int x =
thresholdFilter->GetOutput()->GetLargestPossibleRegion().GetSize()[0];
		unsigned int y =
thresholdFilter->GetOutput()->GetLargestPossibleRegion().GetSize()[1];
		unsigned int z =
thresholdFilter->GetOutput()->GetLargestPossibleRegion().GetSize()[2];
		int i;
		//for(int k =0 ; k<z ; k++){
		for (i = 1; i < x; i++) {
			index[0] = i;
			index[1] = 0;
			index[2] = 0;
			neighborhoodConnected->AddSeed(index);
		}

		//for(int k =0 ; k<z ; k++){
		for (i = 0; i < x; i++) {
			index[0] = i;
			index[1] = y-1;
			index[2] = 0;
			neighborhoodConnected->AddSeed(index);
		}

	}
	ImageTypeInt::SizeType radius;
 	radius[0] = 0;
 	radius[1] = 0;
	radius[2] = 0;
 	neighborhoodConnected->SetRadius(radius);
	
	MaskNegatedFilterType::Pointer maskNegatedFilter =
MaskNegatedFilterType::New();
	maskNegatedFilter->SetInput1(thresholdFilter->GetOutput());
	maskNegatedFilter->SetInput2(neighborhoodConnected->GetOutput());

	HoleFillingType::Pointer holeFillingFilter = HoleFillingType::New();
	radius[0] = 2;
 	radius[1] = 2;
	radius[2] = 2;
 	holeFillingFilter->SetRadius(radius);
	holeFillingFilter->SetInput(maskNegatedFilter->GetOutput());
	holeFillingFilter->SetBackgroundValue( 1 );
	holeFillingFilter->SetForegroundValue( 0 );
	holeFillingFilter->SetMajorityThreshold( 2 );
	holeFillingFilter->SetMaximumNumberOfIterations( 4 );
	
	DilateFilterType::Pointer binaryDilateFilter = DilateFilterType::New();   
 	ErodeFilterType::Pointer binaryErodeFilter = ErodeFilterType::New();
 	
 	StructuringElementType structuringElement;
 	structuringElement.SetRadius( 6 ); 
 	structuringElement.CreateStructuringElement();
 	binaryDilateFilter->SetKernel( structuringElement );
 	binaryErodeFilter->SetKernel( structuringElement );
 	
 	binaryDilateFilter->SetInput( holeFillingFilter->GetOutput() );
 	binaryErodeFilter->SetInput( binaryDilateFilter->GetOutput() );
 	binaryDilateFilter->SetDilateValue( 1 );
 	binaryErodeFilter->SetErodeValue( 1 );


	ImageTypeInt *image;
	binaryErodeFilter->Update();
	image = binaryErodeFilter->GetOutput();
	

	writer->SetFileName( outputFilename );
	writer->SetInput(image);
	writer->Update();





--
View this message in context: http://itk-insight-users.2283740.n2.nabble.com/segmentation-a-3D-image-takes-a-long-time-any-help-to-speed-it-tp7585238.html
Sent from the ITK Insight Users mailing list archive at Nabble.com.


More information about the Insight-users mailing list