7 #include "PlusConfigure.h" 11 #include "igsioTrackedFrame.h" 12 #include "vtkIGSIOSequenceIO.h" 13 #include "vtkSmartPointer.h" 14 #include "vtkIGSIOTrackedFrameList.h" 15 #include "vtkXMLDataElement.h" 16 #include "vtkXMLUtilities.h" 17 #include "vtksys/CommandLineArguments.hxx" 34 void SegmentImageSequence(vtkIGSIOTrackedFrameList* trackedFrameList, std::ofstream& outFile,
const std::string& inputTestcaseName,
const std::string& inputImageSequenceFileName,
PlusFidPatternRecognition& patternRecognition,
const char* fidPositionOutputFilename)
36 double sumFiducialNum = 0;
37 double sumFiducialCandidate = 0;
39 bool writeFidPositionsToFile = (fidPositionOutputFilename != NULL);
40 std::ofstream outFileFidPositions;
41 if (writeFidPositionsToFile)
43 outFileFidPositions.open(fidPositionOutputFilename);
44 outFileFidPositions <<
"Frame number, Unfiltered timestamp, Timestamp, w1x, w1y, w2x, w2y, w3x, w3y, w4x, w4y, w5x, w5y, w6x, w6y " << std::endl;
51 for (
unsigned int currentFrameIndex = 0; currentFrameIndex < trackedFrameList->GetNumberOfTrackedFrames(); currentFrameIndex++)
53 LOG_DEBUG(
"Frame: " << currentFrameIndex);
55 std::ostringstream possibleFiducialsImageFilename;
56 possibleFiducialsImageFilename << inputTestcaseName << std::setw(3) << std::setfill(
'0') << currentFrameIndex <<
".bmp" << std::ends;
61 if (trackedFrameList->GetTrackedFrame(currentFrameIndex)->GetImageData()->GetVTKScalarPixelType() != VTK_UNSIGNED_CHAR)
63 LOG_ERROR(
"UsFidSegTest only supports 8-bit images");
66 patternRecognition.
RecognizePattern(trackedFrameList->GetTrackedFrame(currentFrameIndex), segResults, error, currentFrameIndex);
68 sumFiducialCandidate += segResults.
GetNumDots();
73 if (currentFid[0] != 0 || currentFid[1] != 0)
78 sumFiducialNum = sumFiducialNum + numFid;
80 if (writeFidPositionsToFile)
83 std::string strFrameNumber = trackedFrameList->GetTrackedFrame(currentFrameIndex)->GetFrameField(
"FrameNumber");
84 std::string strTimestamp = trackedFrameList->GetTrackedFrame(currentFrameIndex)->GetFrameField(
"Timestamp");
85 std::string strUnfilteredTimestamp = trackedFrameList->GetTrackedFrame(currentFrameIndex)->GetFrameField(
"UnfilteredTimestamp");
87 outFileFidPositions << (!strFrameNumber.empty() ? strFrameNumber :
"unknown") <<
", " << (!strUnfilteredTimestamp.empty() ? strUnfilteredTimestamp :
"unknown") <<
", " << (!strTimestamp.empty() ? strTimestamp :
"unknown");
91 outFileFidPositions <<
", " << currentFid[0] <<
", " << currentFid[1];
93 outFileFidPositions << std::endl;
104 double meanFid = sumFiducialNum / trackedFrameList->GetNumberOfTrackedFrames();
105 double meanFidCandidate = sumFiducialCandidate / trackedFrameList->GetNumberOfTrackedFrames();
108 if (writeFidPositionsToFile)
110 outFileFidPositions.close();
117 const bool reportWarningsAsFailure =
true;
118 int numberOfFailures = 0;
120 vtkSmartPointer<vtkXMLDataElement> currentRootElem = vtkSmartPointer<vtkXMLDataElement>::Take(
121 vtkXMLUtilities::ReadElementFromFile(outputTestResultsFileName.c_str()));
122 vtkSmartPointer<vtkXMLDataElement> baselineRootElem = vtkSmartPointer<vtkXMLDataElement>::Take(
123 vtkXMLUtilities::ReadElementFromFile(inputBaselineFileName.c_str()));
128 if (baselineRootElem == NULL)
130 LOG_ERROR(
"Reading baseline data file failed: " << inputBaselineFileName);
132 return numberOfFailures;
134 if (currentRootElem == NULL)
136 LOG_ERROR(
"Reading newly generated data file failed: " << outputTestResultsFileName);
138 return numberOfFailures;
143 LOG_ERROR(
"Baseline data file is invalid");
145 return numberOfFailures;
149 LOG_ERROR(
"newly generated data file is invalid");
151 return numberOfFailures;
154 std::ofstream outFileFidFindingResults;
155 if (writeFidFoundRatioToFile)
157 outFileFidFindingResults.open(
"FiducialsFound.txt");
161 for (
int nestedElemInd = 0; nestedElemInd < currentRootElem->GetNumberOfNestedElements(); nestedElemInd++)
163 LOG_DEBUG(
"Current Frame: " << nestedElemInd);
164 vtkXMLDataElement* currentElem = currentRootElem->GetNestedElement(nestedElemInd);
165 if (currentElem == NULL)
167 LOG_WARNING(
"Frame " << nestedElemInd <<
": Invalid current data element");
168 if (reportWarningsAsFailure)
182 LOG_WARNING(
"Frame " << nestedElemInd <<
": Current data element doesn't have an id");
183 if (reportWarningsAsFailure)
194 if (baselineElem == NULL)
196 LOG_ERROR(
"Frame " << nestedElemInd <<
": Cannot find corresponding baseline element for current element " << currentElem->GetId());
203 LOG_WARNING(
"Frame " << nestedElemInd <<
": Test case name mismatch");
204 if (reportWarningsAsFailure) { numberOfFailures++; }
208 vtkXMLDataElement* outputElementBaseline = baselineElem->FindNestedElementWithName(
"Output");
209 vtkXMLDataElement* outputElementCurrent = currentElem->FindNestedElementWithName(
"Output");
212 int baselineSegmentationSuccess = 0;
213 int currentSegmentationSuccess = 0;
214 if (!outputElementBaseline->GetScalarAttribute(
"SegmentationSuccess", baselineSegmentationSuccess))
216 LOG_ERROR(
"Frame " << nestedElemInd <<
": baseline segmentation success is missing");
219 if (!outputElementCurrent->GetScalarAttribute(
"SegmentationSuccess", currentSegmentationSuccess))
221 LOG_ERROR(
"Frame " << nestedElemInd <<
": current segmentation success is missing");
225 if (baselineSegmentationSuccess != currentSegmentationSuccess)
227 LOG_ERROR(
"Frame " << nestedElemInd <<
": SegmentationSuccess mismatch: current=" << currentSegmentationSuccess <<
", baseline=" << baselineSegmentationSuccess);
231 if (!baselineSegmentationSuccess)
237 double baselineFiducialPoints[MAX_FIDUCIAL_COORDINATE_COUNT];
238 memset(baselineFiducialPoints, 0,
sizeof(baselineFiducialPoints[0] * MAX_FIDUCIAL_COORDINATE_COUNT));
239 int baselineFidPointsRead = outputElementBaseline->GetVectorAttribute(
"SegmentationPoints", MAX_FIDUCIAL_COORDINATE_COUNT, baselineFiducialPoints);
242 vtkXMLDataElement* fidCandidElement = currentElem->FindNestedElementWithName(
"FiducialPointCandidates");
243 const char* fidCandid =
"FiducialPointCandidates";
244 if ((fidCandidElement != NULL) && (strcmp(fidCandidElement->GetName(), fidCandid) == 0))
246 int foundBaselineFiducials = 0;
248 for (
int b = 0;
b + 1 < baselineFidPointsRead;
b += 2)
250 for (
int i = 0;
i < fidCandidElement->GetNumberOfNestedElements();
i++)
252 double fidCandidates[2] = {0, 0};
253 fidCandidElement->GetNestedElement(
i)->GetVectorAttribute(
"Positon", 2, fidCandidates);
258 LOG_DEBUG(
"Fiducial candidate (" << fidCandidates[0] <<
", " << fidCandidates[1]
259 <<
") matches the segmented baseline fiducial (" << baselineFiducialPoints[
b] <<
", " << baselineFiducialPoints[
b + 1] <<
")");
260 foundBaselineFiducials++;
267 LOG_DEBUG(
"Found fiducials / Fiducial candidates: " << foundBaselineFiducials <<
" / " << fidCandidElement->GetNumberOfNestedElements()) ;
268 if (writeFidFoundRatioToFile)
270 outFileFidFindingResults << nestedElemInd <<
": " << foundBaselineFiducials <<
" / " << fidCandidElement->GetNumberOfNestedElements() << std::endl;
274 if (!currentSegmentationSuccess)
280 double baselineIntensity = 0;
281 double testingElementIntensity = 0;
282 if (!outputElementBaseline->GetScalarAttribute(
"SegmentationQualityInIntensityScore", baselineIntensity))
284 LOG_ERROR(
"Frame " << nestedElemInd <<
": Cannot access baseline scalar");
287 else if (!outputElementCurrent->GetScalarAttribute(
"SegmentationQualityInIntensityScore", testingElementIntensity))
289 LOG_ERROR(
"Frame " << nestedElemInd <<
": Newly generated segmentation intensity is missing");
297 LOG_ERROR(
"Frame " << nestedElemInd <<
": Intensity mismatch: current=" << testingElementIntensity <<
", baseline=" << baselineIntensity);
302 double fiducialPositions[MAX_FIDUCIAL_COORDINATE_COUNT];
303 memset(fiducialPositions, 0,
sizeof(fiducialPositions[0])*MAX_FIDUCIAL_COORDINATE_COUNT);
304 int fidCoordinatesRead = outputElementCurrent->GetVectorAttribute(
"SegmentationPoints", MAX_FIDUCIAL_COORDINATE_COUNT, fiducialPositions);
306 if (baselineFidPointsRead != fidCoordinatesRead)
308 LOG_ERROR(
"Frame " << nestedElemInd <<
": Number of current fiducials (" << fidCoordinatesRead <<
") differs from the number of baseline fiducials (" << baselineFidPointsRead <<
")");
311 int fidCount = std::min(baselineFidPointsRead, fidCoordinatesRead);
313 if (baselineFidPointsRead < 1)
315 LOG_ERROR(
"Frame " << nestedElemInd <<
": Cannot access baseline fiducial points");
318 else if (fidCoordinatesRead < 1)
320 LOG_ERROR(
"Frame " << nestedElemInd <<
": Newly generated segmentation points are missing");
323 else if (baselineFidPointsRead % 2 != 0)
325 LOG_ERROR(
"Frame " << nestedElemInd <<
": Unpaired baseline fiducial coordinates");
328 else if (fidCoordinatesRead % 2 != 0)
330 LOG_ERROR(
"Frame " << nestedElemInd <<
": Unpaired Fiducial Coordinates");
333 else if (baselineFidPointsRead > MAX_FIDUCIAL_COORDINATE_COUNT)
335 LOG_WARNING(
"Frame " << nestedElemInd <<
": Too many baseline fiducials");
336 if (reportWarningsAsFailure) { numberOfFailures++; }
338 else if (fidCoordinatesRead > MAX_FIDUCIAL_COORDINATE_COUNT)
340 LOG_WARNING(
"Frame " << nestedElemInd <<
": Too many Fiducials");
341 if (reportWarningsAsFailure) { numberOfFailures++; }
347 for (
int traverseFiducials = 0; traverseFiducials < fidCount; ++traverseFiducials)
351 LOG_ERROR(
"Frame " << nestedElemInd <<
": Fiducial coordinate [" << traverseFiducials <<
"] mismatch: current=" << fiducialPositions[traverseFiducials] <<
", baseline=" << baselineFiducialPoints[traverseFiducials]);
359 std::cout << numberOfFailures << std::endl;
361 if (writeFidFoundRatioToFile)
363 outFileFidFindingResults.close();
365 return numberOfFailures;
368 int main(
int argc,
char** argv)
371 std::string inputImageSequenceFileName;
372 std::string inputBaselineFileName;
373 std::string inputTestcaseName;
374 std::string inputTestDataDir;
375 std::string inputConfigFileName;
376 std::string outputTestResultsFileName;
377 std::string outputFiducialPositionsFileName;
378 std::string fiducialGeomString;
380 int verboseLevel = vtkPlusLogger::LOG_LEVEL_UNDEFINED;
382 vtksys::CommandLineArguments args;
383 args.Initialize(argc, argv);
385 args.AddArgument(
"--test-data-dir", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputTestDataDir,
"Test data directory");
386 args.AddArgument(
"--img-seq-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputImageSequenceFileName,
"Filename of the input image sequence. Segmentation will be performed for all frames of the sequence.");
387 args.AddArgument(
"--testcase", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputTestcaseName,
"Name of the test case that will be printed to the output");
388 args.AddArgument(
"--baseline", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputBaselineFileName,
"Name of file storing baseline results (fiducial coordinates, intensity, angle)");
390 args.AddArgument(
"--output-xml-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &outputTestResultsFileName,
"Name of file storing results of a new segmentation (fiducial coordinates, intensity, angle)");
391 args.AddArgument(
"--output-fiducial-positions-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &outputFiducialPositionsFileName,
"Name of file for storing fiducial positions in time");
393 args.AddArgument(
"--config-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputConfigFileName,
"Calibration configuration file name");
395 args.AddArgument(
"--verbose", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &verboseLevel,
"Verbose level (1=error only, 2=warning, 3=info, 4=debug, 5=trace)");
399 std::cerr <<
"Problem parsing arguments" << std::endl;
400 std::cout <<
"Help: " << args.GetHelp() << std::endl;
406 if (inputImageSequenceFileName.empty() || inputConfigFileName.empty())
408 std::cerr <<
"At lease one of the following parameters is missing: --img-seq-file, --config-file" << std::endl;
413 vtkSmartPointer<vtkXMLDataElement> configRootElement = vtkSmartPointer<vtkXMLDataElement>::New();
416 LOG_ERROR(
"Unable to read configuration from file " << inputConfigFileName.c_str());
423 LOG_INFO(
"Read from metafile");
424 std::string inputImageSequencePath = inputTestDataDir +
"/" + inputImageSequenceFileName;
425 vtkSmartPointer<vtkIGSIOTrackedFrameList> trackedFrameList = vtkSmartPointer<vtkIGSIOTrackedFrameList>::New();
426 if (vtkIGSIOSequenceIO::Read(inputImageSequencePath, trackedFrameList) !=
PLUS_SUCCESS)
428 LOG_ERROR(
"Failed to read sequence metafile: " << inputImageSequencePath);
432 std::ofstream outFile;
433 outFile.open(outputTestResultsFileName.c_str(), ios::trunc);
435 if (! outFile.is_open())
437 LOG_ERROR(
"Failed to open file: " << outputTestResultsFileName);
444 const char* fidPositionOutputFilename = NULL;
445 if (!outputFiducialPositionsFileName.empty())
447 fidPositionOutputFilename = outputFiducialPositionsFileName.c_str();
450 LOG_INFO(
"Segment image sequence");
451 SegmentImageSequence(trackedFrameList.GetPointer(), outFile, inputTestcaseName, inputImageSequenceFileName, patternRecognition, fidPositionOutputFilename);
458 if (!inputBaselineFileName.empty())
460 LOG_INFO(
"Compare results");
463 LOG_ERROR(
"Comparison of segmentation data to baseline failed");
static void WriteSegmentationResultsFooter(std::ostream &outFile)
PlusFidSegmentation * GetFidSegmentation()
static void WriteSegmentationResultsParameters(std::ostream &outFile, PlusFidPatternRecognition &patternRcognitionObject, const std::string &trueFidFileName)
static void WriteSegmentationResults(std::ostream &outFile, PlusPatternRecognitionResult &segResults, const std::string &inputTestcaseName, int currentFrameIndex, const std::string &inputImageSequenceFileName)
static const char * TEST_CASE_ELEMENT_NAME
Initial rotation matrix b
static const double BASELINE_TO_ALGORITHM_TOLERANCE
std::vector< std::vector< double > > & GetFoundDotsCoordinateValue()
double GetThresholdImagePercent()
void SetDebugOutput(bool value)
static const double FIDUCIAL_POSITION_TOLERANCE
static const int MAX_FIDUCIAL_COUNT
static vtkIGSIOLogger * Instance()
static const char * TEST_RESULTS_ELEMENT_NAME
static const char * ID_ATTRIBUTE_NAME
double GetNumDots() const
PlusStatus RecognizePattern(vtkIGSIOTrackedFrameList *trackedFrameList, PatternRecognitionError &patternRecognitionError, int *numberOfSuccessfullySegmentedImages=NULL, std::vector< unsigned int > *segmentedFramesIndices=NULL)
int CompareSegmentationResults(const std::string &inputBaselineFileName, const std::string &outputTestResultsFileName, PlusFidPatternRecognition &patternRecognition)
void SegmentImageSequence(vtkIGSIOTrackedFrameList *trackedFrameList, std::ofstream &outFile, const std::string &inputTestcaseName, const std::string &inputImageSequenceFileName, PlusFidPatternRecognition &patternRecognition, const char *fidPositionOutputFilename)
int main(int argc, char **argv)
static void WriteSegmentationResultsStats(std::ostream &outFile, double meanFid, double meanFidCandidate=-1)
static void WriteSegmentationResultsHeader(std::ostream &outFile)
PlusStatus ReadConfiguration(vtkXMLDataElement *rootConfigElement)
static PlusStatus ReadDeviceSetConfigurationFromFile(vtkXMLDataElement *config, const char *filename)