28 #include <vtkSmartPointer.h> 29 #include <vtkFloatArray.h> 31 #include "milxDeformableModel.h" 32 #include "milxImage.h" 35 #include <tclap/CmdLine.h> 37 using namespace TCLAP;
39 typedef float FloatPixelType;
40 typedef itk::Image<FloatPixelType, 3> FloatImageType;
41 typedef unsigned char InputPixelType;
42 typedef itk::Image<InputPixelType, 3> LabelImageType;
43 typedef LabelImageType::SizeValueType SizeValueType;
45 int main(
int argc,
char* argv[])
49 milx::PrintInfo(
"--------------------------------------------------------");
50 milx::PrintInfo(
"MILX-SMILI Hausdorff Distance Tool for Medical Imaging");
56 milx::PrintInfo(
"--------------------------------------------------------\n");
63 ValueArg<std::string> outputArg(
"o",
"output",
"Output model name",
false,
"hausdorff.vtk",
"Output");
64 ValueArg<std::string> prefixArg(
"p",
"prefix",
"Output prefix for multiple output",
false,
"hausdorff_",
"Output Prefix");
65 ValueArg<std::string> labelArg(
"l",
"label",
"Compute the distances from the labelled image to the surface(s) provided.",
true,
"labelling.nii.gz",
"Label");
66 ValueArg<float> labelValueArg(
"",
"labelvalue",
"Set the label value for option --label.",
true, 255,
"Label Value");
67 ValueArg<size_t> caseArg(
"c",
"case",
"Set the case ID being done. Used to name extra output.",
false, 0,
"Case");
69 SwitchArg symmetricArg(
"s",
"symmetric",
"Compute forward and backward distances. This is required to get Hausdorff distance.",
false);
72 UnlabeledMultiArg<std::string> multinames(
"surfaces",
"Surfaces to compute the distances with.",
true,
"Surfaces");
75 cmd.add( multinames );
79 cmd.add( labelValueArg );
80 cmd.add( symmetricArg );
84 cmd.parse( argc, argv );
88 std::vector<std::string> filenames = multinames.getValue();
89 const std::string outputName = outputArg.getValue();
90 const std::string prefixName = prefixArg.getValue();
91 const std::string labelName = labelArg.getValue();
92 const float labelValue = labelValueArg.getValue();
93 const size_t caseID = caseArg.getValue();
100 if(labelValueArg.isSet())
102 if(!labelArg.isSet())
104 cerr <<
"Error in arguments! Label argument needs to be used with the label value argument." << endl;
110 bool success =
false;
113 cout <<
">> Hausdorff Distance: Reading Models" << endl;
114 vtkSmartPointer<vtkPolyDataCollection> collection;
118 cerr <<
"Error reading models!" << endl;
121 const size_t n = collection->GetNumberOfItems();
124 cerr <<
"At least one model must be provided!" << endl;
127 collection->InitTraversal();
128 vtkSmartPointer<vtkPolyData> surface = collection->GetNextItem();
130 surface->GetBounds(bounds);
131 std::cerr <<
"Done" << std::endl;
134 itk::SmartPointer<LabelImageType> labelledImage, resizedLabelledImage, thresholdedImage;
135 itk::SmartPointer<FloatImageType> distanceMap;
136 const bool binary =
false, signedDistance =
true, insideDistance =
false, squaredDistance =
false;
137 const unsigned char objectValue = 255;
140 cout <<
">> Hausdorff Distance: Using Labelling" << endl;
141 cout <<
"Loading... " << endl;
142 success = milx::File::OpenImage<LabelImageType>(labelName, labelledImage);
144 cout <<
"Thresholding... " << endl;
148 cout <<
"Computing Distance Map of Label... " << endl;
155 cerr <<
"Error Reading one or more of the input files. Exiting." << endl;
161 cout <<
">> Hausdorff Distance: Computing Absolute Surface Distances... " << endl;
162 vtkSmartPointer<vtkFloatArray> weights = vtkSmartPointer<vtkFloatArray>::New();
164 model.RemoveScalars();
165 model.MarkSurfaceInsideImage<FloatImageType>(model.GetOutput(), distanceMap, weights);
166 model.Clip(1.0, 1.0);
169 const bool absValues =
true;
170 vtkSmartPointer<vtkFloatArray> scalars = model.SurfaceScalarsFromImage<FloatImageType>(model.GetOutput(), distanceMap, absValues);
171 scalars->SetName(
"Surface Distance Errors");
172 model.SetScalars(scalars);
175 cout <<
"Regions of Surface Outside the Image are marked with -1." << endl;
176 weights->FillComponent(0, -1.0);
177 for(
int j = 0; j < model.GetOutput()->GetNumberOfPoints(); j ++)
179 vtkIdType index = surface->FindPoint(model.GetOutput()->GetPoint(j));
180 weights->SetTuple1(index, scalars->GetTuple1(j));
184 if(symmetricArg.isSet())
189 LabelImageType::SpacingType labelSpacing = labelledImage->GetSpacing();
192 vtkSmartPointer<vtkImageData> voxelisedModel = model.Voxelise(objectValue, labelSpacing.GetDataPointer(), bounds);
194 cout <<
"Computing Distance Map of Surface... " << endl;
201 cout <<
"Generating Iso Surface... " << endl;
202 vtkSmartPointer<vtkImageData> labelledImageVTK = vtkSmartPointer<vtkImageData>::New();
205 vtkSmartPointer<vtkMatrix4x4> matrix = vtkSmartPointer<vtkMatrix4x4>::New();
206 vtkSmartPointer<vtkImageData> restoredLabelledImageVTK = vtkSmartPointer<vtkImageData>::New();
216 isoSurface.
IsoSurface(restoredLabelledImageVTK, objectValue-1);
222 cout <<
">> Hausdorff Distance: Computing Backward Absolute Surface Distances... " << endl;
223 vtkSmartPointer<vtkFloatArray> weights2 = vtkSmartPointer<vtkFloatArray>::New();
230 symmetricModel.
Clip(1.0, 1.0);
233 const bool absValues =
true;
234 vtkSmartPointer<vtkFloatArray> scalars2 = model.SurfaceScalarsFromImage<FloatImageType>(symmetricModel.
GetOutput(), modelDistanceMap, absValues);
235 scalars2->SetName(
"Surface Distance Errors");
239 weights2->FillComponent(0, -1.0);
240 for(
int j = 0; j < symmetricModel.
GetOutput()->GetNumberOfPoints(); j ++)
242 vtkIdType index = isoSurface.
GetOutput()->FindPoint(symmetricModel.
GetOutput()->GetPoint(j));
243 weights2->SetTuple1(index, scalars2->GetTuple1(j));
247 double range1[2], range2[2];
248 surface->GetScalarRange(range1);
249 isoSurface.
GetOutput()->GetScalarRange(range2);
250 std::cout <<
"Forward Max Distance: " << range1[1] << std::endl;
251 std::cout <<
"Backward Max Distance: " << range2[1] << std::endl;
252 std::cout <<
"Hausdorff Distance: " << milx::Maximum<double>(range1[1], range2[1]) << std::endl;
255 cout <<
"Saving Backward Result... " << endl;
261 surface->GetPointData()->SetScalars(weights);
264 cout <<
"Saving Result... " << endl;
267 cout <<
">> Hausdorff Distance: Operation Complete" << endl;
void PrintDebug(const std::string msg)
Displays a generic msg to standard error with carriage return if in Debug mode.
void RemoveScalars()
Removes all the scalars from the current model. Same as ClearScalars()
static itk::SmartPointer< TImage > ConvertVTKImageToITKImage(vtkSmartPointer< vtkImageData > img)
Converts a VTK image object to an ITK image object.
This program Animates image slices and animates surfaces in the model view for creating movies...
static bool OpenModelCollection(std::vector< std::string > filenames, vtkSmartPointer< vtkPolyDataCollection > &collection)
Opens model files, which can be a VTK XML, Legacy VTK PolyData File (i.e. either a *...
void SetInput(vtkSmartPointer< vtkPolyData > model)
Assigns the input model to class.
Represents an image (i.e. an regular rectangular array with scalar values) and their common operation...
static bool SaveModel(const std::string filename, vtkSmartPointer< vtkPolyData > data, const bool binary=false)
Saves a model as a file, which can be a VTK XML or Legacy VTK PolyData File (i.e. either a *...
void PrintInfo(const std::string msg)
Displays a generic msg to standard output with carriage return.
std::string NumberToString(double num, unsigned zeroPad=0)
Number to string converter.
static void MarkSurfaceInsideImage(vtkSmartPointer< vtkPolyData > &surface, itk::SmartPointer< TImage > img, vtkFloatArray *weights, const float outsideValue=0.0)
Mark existing surface with all parts outside the image as 'outsideValue' value. Inside will remain th...
void Clip(const coordinateType belowValue, const coordinateType aboveValue)
Clip the mesh based on a scalar threshold of the mesh scalars.
vtkSmartPointer< vtkPolyData > & GetOutput()
Returns the current model, i.e. the result of the latest operation ITK/VTK style. ...
void SetScalars(vtkSmartPointer< vtkDataArray > modelScalars)
Sets the scalar field of the mesh (values per vertex of the surface)
void IsoSurface(vtkSmartPointer< vtkImageData > img, double minValue)
unsigned NumberOfProcessors()
Number of processors or cores on the machine.