1 #include <tclap/CmdLine.h> 5 #include <itkSignedDanielssonDistanceMapImageFilter.h> 6 #include <itkRegionalMaximaImageFilter.h> 7 #include <itkConnectedComponentImageFilter.h> 8 #include <itkGrayscaleDilateImageFilter.h> 9 #include <itkBinaryBallStructuringElement.h> 10 #include <itkImageRegionIterator.h> 11 #include <itkExtractImageFilter.h> 15 int main(
int argc,
char **argv)
17 TCLAP::CmdLine cmd(
"INRIA / IRISA - VisAGeS/Empenn Team",
' ',ANIMA_VERSION);
19 TCLAP::ValueArg<std::string> inArg(
"i",
"input",
"Input binary image",
true,
"",
"input binary image",cmd);
20 TCLAP::ValueArg<std::string> outArg(
"o",
"output",
"Output image",
true,
"",
"output image",cmd);
21 TCLAP::ValueArg<unsigned int> radiusArg(
"r",
"radius",
"Dilation radius for regional maxima",
false,1,
"dilation radius",cmd);
23 TCLAP::ValueArg<unsigned int> numThreadsArg(
"T",
"threads",
"Number of execution threads (default: all cores)",
false,itk::MultiThreaderBase::GetGlobalDefaultNumberOfThreads(),
"number of threads",cmd);
29 catch (TCLAP::ArgException& e)
31 std::cerr <<
"Error: " << e.error() <<
"for argument " << e.argId() << std::endl;
35 typedef itk::Image <unsigned char,3> InputImageType;
36 typedef itk::Image <unsigned short,3> OutputImageType;
37 typedef itk::Image <double,3> DistanceImageType;
39 InputImageType::Pointer inputImage = anima::readImage <InputImageType> (inArg.getValue());
41 InputImageType::RegionType reqRegion = inputImage->GetLargestPossibleRegion();
42 itk::ImageRegionConstIteratorWithIndex <InputImageType> inItr(inputImage,reqRegion);
43 int xMin = reqRegion.GetSize()[0];
45 int yMin = reqRegion.GetSize()[1];
47 int zMin = reqRegion.GetSize()[2];
50 InputImageType::IndexType currentIndex;
51 while (!inItr.IsAtEnd())
55 currentIndex = inItr.GetIndex();
56 if (xMax < currentIndex[0])
57 xMax = currentIndex[0];
58 if (yMax < currentIndex[1])
59 yMax = currentIndex[1];
60 if (zMax < currentIndex[2])
61 zMax = currentIndex[2];
63 if (xMin >= currentIndex[0])
64 xMin = currentIndex[0];
65 if (yMin >= currentIndex[1])
66 yMin = currentIndex[1];
67 if (zMin >= currentIndex[2])
68 zMin = currentIndex[2];
74 xMin = std::max(0,xMin - 2);
75 yMin = std::max(0,yMin - 2);
76 zMin = std::max(0,zMin - 2);
78 xMax = std::min((
int)(reqRegion.GetIndex()[0] + reqRegion.GetSize()[0] - 1),xMax + 2);
79 yMax = std::min((
int)(reqRegion.GetIndex()[1] + reqRegion.GetSize()[1] - 1),yMax + 2);
80 zMax = std::min((
int)(reqRegion.GetIndex()[2] + reqRegion.GetSize()[2] - 1),zMax + 2);
82 reqRegion.SetIndex(0,xMin);
83 reqRegion.SetIndex(1,yMin);
84 reqRegion.SetIndex(2,zMin);
86 reqRegion.SetSize(0,xMax - xMin + 1);
87 reqRegion.SetSize(1,yMax - yMin + 1);
88 reqRegion.SetSize(2,zMax - zMin + 1);
91 typedef itk::ExtractImageFilter<InputImageType, InputImageType> ExtractFilterType;
92 typename ExtractFilterType::Pointer extractFilter = ExtractFilterType::New();
93 extractFilter->SetExtractionRegion(reqRegion);
94 extractFilter->SetDirectionCollapseToGuess();
95 extractFilter->SetInput(inputImage);
96 extractFilter->SetNumberOfWorkUnits(numThreadsArg.getValue());
98 typedef itk::SignedDanielssonDistanceMapImageFilter <InputImageType, DistanceImageType, OutputImageType> DistanceMapFilterType;
99 DistanceMapFilterType::Pointer distanceMap = DistanceMapFilterType::New();
100 distanceMap->SetInput(extractFilter->GetOutput());
101 distanceMap->InsideIsPositiveOn();
102 distanceMap->SetUseImageSpacing(
true);
103 distanceMap->SetNumberOfWorkUnits(numThreadsArg.getValue());
105 typedef itk::RegionalMaximaImageFilter <DistanceImageType,InputImageType> RegionalMaximaFilterType;
106 RegionalMaximaFilterType::Pointer regionalFilter = RegionalMaximaFilterType::New();
107 regionalFilter->SetInput(distanceMap->GetOutput());
108 regionalFilter->SetFullyConnected(
true);
109 regionalFilter->SetNumberOfWorkUnits(numThreadsArg.getValue());
111 typedef itk::BinaryBallStructuringElement<InputImageType::PixelType,3> StructuringElementType;
112 StructuringElementType structuringElement;
113 structuringElement.SetRadius(radiusArg.getValue());
114 structuringElement.CreateStructuringElement();
116 typedef itk::GrayscaleDilateImageFilter <InputImageType,InputImageType,StructuringElementType> DilateFilterType;
117 DilateFilterType::Pointer dilateFilter = DilateFilterType::New();
118 dilateFilter->SetInput(regionalFilter->GetOutput());
119 dilateFilter->SetKernel(structuringElement);
120 dilateFilter->SetNumberOfWorkUnits(numThreadsArg.getValue());
122 typedef itk::ConnectedComponentImageFilter <InputImageType,OutputImageType> CCFilterType;
123 CCFilterType::Pointer ccFilter = CCFilterType::New();
124 ccFilter->SetInput(dilateFilter->GetOutput());
125 ccFilter->SetFullyConnected(
true);
126 ccFilter->SetNumberOfWorkUnits(numThreadsArg.getValue());
128 typedef itk::SignedDanielssonDistanceMapImageFilter <OutputImageType, DistanceImageType, OutputImageType> VoronoiMapFilterType;
129 VoronoiMapFilterType::Pointer voronoiFilter = VoronoiMapFilterType::New();
130 voronoiFilter->SetInput(ccFilter->GetOutput());
131 voronoiFilter->SetUseImageSpacing(
true);
132 voronoiFilter->InsideIsPositiveOff();
133 voronoiFilter->SetNumberOfWorkUnits(numThreadsArg.getValue());
135 voronoiFilter->Update();
137 OutputImageType::Pointer voronoiImage = voronoiFilter->GetVoronoiMap();
139 OutputImageType::Pointer outImage = OutputImageType::New();
140 outImage->Initialize();
141 outImage->SetRegions(inputImage->GetLargestPossibleRegion());
142 outImage->SetSpacing (inputImage->GetSpacing());
143 outImage->SetOrigin (inputImage->GetOrigin());
144 outImage->SetDirection (inputImage->GetDirection());
145 outImage->Allocate();
146 outImage->FillBuffer(0);
148 itk::ImageRegionIterator <OutputImageType> voronoiIt(voronoiImage,voronoiImage->GetLargestPossibleRegion());
149 itk::ImageRegionIterator <OutputImageType> outIt(outImage,reqRegion);
150 itk::ImageRegionIterator <InputImageType> inputIt(inputImage,reqRegion);
152 while (!inputIt.IsAtEnd())
154 if (inputIt.Get() != 0)
155 outIt.Set(voronoiIt.Get());
162 anima::writeImage <OutputImageType> (outArg.getValue(),outImage);
int main(int argc, char **argv)