3 #include <itkConnectedComponentImageFilter.h> 4 #include <itkRelabelComponentImageFilter.h> 5 #include <itkImageRegionConstIterator.h> 6 #include <itkMultiThreaderBase.h> 7 #include <vnl/vnl_matrix.h> 9 #include <tclap/CmdLine.h> 15 bool operator()(
const std::pair <unsigned int, unsigned int> &a,
const std::pair <unsigned int, unsigned int> &b)
const 17 return a.second > b.second;
21 int main(
int argc,
char * *argv)
23 TCLAP::CmdLine cmd(
"INRIA / IRISA - VisAGeS/Empenn Team",
' ', ANIMA_VERSION);
25 TCLAP::ValueArg <std::string> refArg(
"r",
"ref",
"Reference binary segmentation",
true,
"",
"reference segmentation", cmd);
26 TCLAP::ValueArg <std::string> testArg(
"t",
"test",
"Test binary segmentation",
true,
"",
"test segmentation", cmd);
27 TCLAP::ValueArg <std::string> outArg(
"o",
"out-csv",
"output CSV data on lesions",
true,
"",
"output CSV", cmd);
29 TCLAP::ValueArg <double> alphaArg(
"a",
"alpha",
"Alpha threshold (in between 0 and 1, default: 0.1)",
false, 0.1,
"alpha threshold", cmd);
30 TCLAP::ValueArg <double> gammaArg(
"g",
"gamma",
"Gamma threshold (in between 0 and 1, default: 0.65)",
false, 0.65,
"gamma threshold", cmd);
31 TCLAP::ValueArg <double> betaArg(
"b",
"beta",
"Beta threshold (in between 0 and 1, default: 0.7)",
false, 0.7,
"beta threshold", cmd);
33 TCLAP::ValueArg <unsigned int> minVolumeArg(
"m",
"min-vol",
"Minimal volume for the component to be considered (default: 3 mm3)",
false, 3,
"minimal volume", cmd);
34 TCLAP::ValueArg <unsigned int> nbpArg(
"T",
"numberofthreads",
"Number of threads to run on (default : all cores)",
false,itk::MultiThreaderBase::GetGlobalDefaultNumberOfThreads(),
"number of threads",cmd);
36 TCLAP::SwitchArg fullConnectArg(
"F",
"full-connect",
"Use 26-connectivity instead of 6-connectivity",cmd,
false);
40 cmd.parse(argc, argv);
42 catch (TCLAP::ArgException& e)
44 std::cerr <<
"Error: " << e.error() <<
"for argument " << e.argId() << std::endl;
48 typedef itk::Image <unsigned short, 3> ImageType;
49 typedef itk::ImageRegionConstIterator <ImageType> ImageIteratorType;
51 ImageType::Pointer refSegmentation = anima::readImage <ImageType> (refArg.getValue());
52 ImageType::Pointer testSegmentation = anima::readImage <ImageType> (testArg.getValue());
54 typedef itk::ConnectedComponentImageFilter <ImageType, ImageType> CCFilterType;
55 typedef itk::RelabelComponentImageFilter <ImageType, ImageType> RelabelComponentFilterType;
57 CCFilterType::Pointer refCCFilter = CCFilterType::New();
58 refCCFilter->SetInput(refSegmentation);
59 refCCFilter->SetFullyConnected(fullConnectArg.isSet());
60 refCCFilter->SetNumberOfWorkUnits(nbpArg.getValue());
61 refCCFilter->Update();
63 ImageType::SpacingType spacing = refSegmentation->GetSpacing();
64 ImageType::SpacingValueType spacingTot = spacing[0];
65 for (
unsigned int i = 1;i < 3;++i)
66 spacingTot *= spacing[i];
69 unsigned int minSizeInVoxel = (
unsigned int)std::ceil(minVolumeArg.getValue() / spacingTot);
72 RelabelComponentFilterType::Pointer relabelRefFilter = RelabelComponentFilterType::New();
73 relabelRefFilter->SetInput(refCCFilter->GetOutput());
74 relabelRefFilter->SetMinimumObjectSize(minSizeInVoxel);
75 relabelRefFilter->SetNumberOfWorkUnits(nbpArg.getValue());
76 relabelRefFilter->Update();
79 refSegmentation = relabelRefFilter->GetOutput();
80 refSegmentation->DisconnectPipeline();
82 CCFilterType::Pointer testCCFilter = CCFilterType::New();
83 testCCFilter->SetInput(testSegmentation);
84 testCCFilter->SetFullyConnected(fullConnectArg.isSet());
85 testCCFilter->SetNumberOfWorkUnits(nbpArg.getValue());
86 testCCFilter->Update();
89 RelabelComponentFilterType::Pointer relabelTestFilter = RelabelComponentFilterType::New();
90 relabelTestFilter->SetInput(testCCFilter->GetOutput());
91 relabelTestFilter->SetMinimumObjectSize(minSizeInVoxel);
92 relabelTestFilter->SetNumberOfWorkUnits(nbpArg.getValue());
93 relabelTestFilter->Update();
96 testSegmentation = relabelTestFilter->GetOutput();
97 testSegmentation->DisconnectPipeline();
99 ImageIteratorType refItr(refSegmentation, refSegmentation->GetLargestPossibleRegion());
100 ImageIteratorType testItr(testSegmentation, testSegmentation->GetLargestPossibleRegion());
102 unsigned int maxRefLabel = 0;
103 unsigned int maxTestLabel = 0;
104 while (!refItr.IsAtEnd())
106 if (refItr.Get() > maxRefLabel)
107 maxRefLabel = refItr.Get();
109 if (testItr.Get() > maxTestLabel)
110 maxTestLabel = testItr.Get();
118 if (maxRefLabel <= 1)
124 vnl_matrix <unsigned int> labelsOverlap(maxRefLabel,maxTestLabel);
125 labelsOverlap.fill(0);
127 while (!refItr.IsAtEnd())
129 labelsOverlap(refItr.Get(),testItr.Get())++;
135 std::vector < std::pair <unsigned int, unsigned int> > subVectorForSort(maxTestLabel - 1);
136 std::vector < std::pair <double,unsigned int> > detectionTable(maxRefLabel-1);
137 std::vector <double> columnSums(maxTestLabel,0);
138 std::vector <double> lineSums(maxRefLabel,0);
140 for (
unsigned int i = 1;i < maxRefLabel;++i)
142 for (
unsigned int j = 1;j < maxTestLabel;++j)
144 lineSums[i] += labelsOverlap(i,j);
145 columnSums[j] += labelsOverlap(i,j);
149 for (
unsigned int i = 1;i < maxRefLabel;++i)
151 double denom = labelsOverlap(i,0) + lineSums[i];
152 double Si = lineSums[i] / denom;
154 if (Si <= alphaArg.getValue())
156 detectionTable[i-1] = std::make_pair(denom * spacingTot,0);
160 for (
unsigned int j = 1;j < maxTestLabel;++j)
161 subVectorForSort[j-1] = std::pair <unsigned int,unsigned int>(j,labelsOverlap(i,j));
166 unsigned int detectedObject = 1;
168 while (wSum < gammaArg.getValue())
170 unsigned int kIndex = subVectorForSort[k].first;
171 double sumK = labelsOverlap(0,kIndex) + columnSums[kIndex];
172 double Tk = labelsOverlap(0,kIndex) / sumK;
174 if (Tk > betaArg.getValue())
180 wSum += labelsOverlap(i,kIndex) / lineSums[i];
184 detectionTable[i-1] = std::make_pair(denom * spacingTot,detectedObject);
187 unsigned int totalNumberOfDetections = 0;
188 unsigned int refCount = 0;
189 for (
unsigned int i = 1;i < maxRefLabel;++i)
191 if (detectionTable[i].second > 0)
192 ++totalNumberOfDetections;
194 for (
unsigned int j = 0;j < maxTestLabel;++j)
195 refCount += labelsOverlap(i,j);
198 std::ofstream outputFile(outArg.getValue());
199 outputFile.precision(10);
200 outputFile <<
"Total number of reference objects:," << maxRefLabel - 1 << std::endl;
201 outputFile <<
"Total number of detections:," << totalNumberOfDetections << std::endl;
202 outputFile <<
"Total objects volume:," << refCount * spacingTot << std::endl;
204 outputFile <<
"Object number,Object volume,Detected flag" << std::endl;
205 for (
unsigned int i = 1;i < maxRefLabel;++i)
206 outputFile << i <<
"," << detectionTable[i-1].first <<
"," << detectionTable[i-1].second << std::endl;
int main(int argc, char **argv)
struct @0 pair_decreasing_comparator