7 #include "PlusConfigure.h" 10 #include "vtkPoints.h" 13 #include "vtkIGSIOTrackedFrameList.h" 14 #include "igsioTrackedFrame.h" 36 LOG_TRACE(
"FidPatternRecognition::ReadConfiguration");
40 LOG_ERROR(
"Reading phantom definition failed!");
56 LOG_TRACE(
"FidPatternRecognition::RecognizePattern");
62 LOG_ERROR(
"Recognizing pattern failed!");
80 LOG_TRACE(
"FidPatternRecognition::RecognizePattern");
92 if (trackedFrame->GetImageData()->GetVTKScalarPixelType() != VTK_UNSIGNED_CHAR)
94 LOG_ERROR(
"FidPatternRecognition::RecognizePattern only supports 8-bit images");
108 bool tooManyCandidates =
false;
110 if (tooManyCandidates)
114 if (!clusteringSuccessful)
145 vtkSmartPointer<vtkPoints> fiducialPoints = vtkSmartPointer<vtkPoints>::New();
146 fiducialPoints->SetNumberOfPoints(fiducials.size());
148 for (
unsigned int i = 0;
i < fiducials.size(); ++
i)
150 fiducialPoints->InsertPoint(
i, fiducials[
i][0], fiducials[
i][1], 0.0);
152 fiducialPoints->Modified();
154 trackedFrame->SetFiducialPointsCoordinatePx(fiducialPoints);
163 LOG_TRACE(
"FidPatternRecognition::RecognizePattern");
168 if (vtkIGSIOTrackedFrameList::VerifyProperties(trackedFrameList, US_IMG_ORIENT_MF, US_IMG_BRIGHTNESS) !=
PLUS_SUCCESS)
170 LOG_ERROR(
"Failed to perform calibration - tracked frame list is invalid");
176 if (numberOfSuccessfullySegmentedImages)
178 *numberOfSuccessfullySegmentedImages = 0;
181 for (
unsigned int currentFrameIndex = 0; currentFrameIndex < trackedFrameList->GetNumberOfTrackedFrames(); currentFrameIndex++)
183 igsioTrackedFrame* trackedFrame = trackedFrameList->GetTrackedFrame(currentFrameIndex);
186 if (trackedFrame->GetFiducialPointsCoordinatePx() != NULL)
195 LOG_ERROR(
"Recognizing pattern failed on frame " << currentFrameIndex);
200 if (numberOfSuccessfullySegmentedImages)
203 if (trackedFrame->GetFiducialPointsCoordinatePx()
204 && trackedFrame->GetFiducialPointsCoordinatePx()->GetNumberOfPoints() > 0)
206 (*numberOfSuccessfullySegmentedImages)++;
207 if (segmentedFramesIndices != NULL)
209 segmentedFramesIndices->push_back(currentFrameIndex);
222 LOG_TRACE(
"FidPatternRecognition::DrawDots");
229 for (
double t = 0;
t < 2 * vtkMath::Pi();
t += vtkMath::Pi() /
DOT_STEPS)
251 LOG_TRACE(
"FidPatternRecognition::DrawLines");
253 for (
unsigned int l = 0; l < foundLines.size(); l++)
256 double directionVector[2] = { foundLines[l].GetDirectionVector()[0], foundLines[l].GetDirectionVector()[1]};
257 if (directionVector[0] > 0)
259 directionVector[0] = -directionVector[0];
260 directionVector[1] = -directionVector[1];
263 vtkMath::Normalize2D(directionVector);
264 double r = origin[1] - 0.2 * foundLines[l].GetLength() * directionVector[1];
265 double c = origin[0] - 0.2 * foundLines[l].GetLength() * directionVector[0];
272 for (
int i = 0 ;
i < foundLines[l].GetLength() * 1.4 ;
i++)
274 r += directionVector[1];
275 c += directionVector[0];
303 LOG_TRACE(
"FidPatternRecognition::ReadPhantomDefinition");
307 LOG_ERROR(
"Configuration XML data element is NULL");
311 bool nwireFlag =
false;
313 vtkXMLDataElement* phantomDefinition = config->FindNestedElementWithName(
"PhantomDefinition");
314 if (phantomDefinition == NULL)
316 LOG_ERROR(
"No phantom definition is found in the XML tree!");
321 std::vector<PlusFidPattern*> tempPatterns;
324 vtkXMLDataElement* geometry = phantomDefinition->FindNestedElementWithName(
"Geometry");
325 if (geometry == NULL)
327 LOG_ERROR(
"Phantom geometry information not found!");
333 int numberOfGeometryChildren = geometry->GetNumberOfNestedElements();
334 for (
int i = 0;
i < numberOfGeometryChildren; ++
i)
336 vtkXMLDataElement* patternElement = geometry->GetNestedElement(
i);
338 if ((patternElement == NULL) || (STRCASECMP(
"Pattern", patternElement->GetName())))
346 int numberOfWires = patternElement->GetNumberOfNestedElements();
348 if ((numberOfWires != 3) && !(STRCASECMP(
"NWire", patternElement->GetAttribute(
"Type"))))
350 LOG_WARNING(
"NWire contains unexpected number of wires - skipped");
354 for (
int j = 0; j < numberOfWires; ++j)
356 vtkXMLDataElement* wireElement = patternElement->GetNestedElement(j);
358 if (wireElement == NULL)
360 LOG_WARNING(
"Invalid wire description in Pattern - skipped");
366 const char* wireName = wireElement->GetAttribute(
"Name");
367 if (wireName != NULL)
371 if (! wireElement->GetVectorAttribute(
"EndPointFront", 3, wire.
EndPointFront))
373 LOG_WARNING(
"Wrong wire end point detected - skipped");
376 if (! wireElement->GetVectorAttribute(
"EndPointBack", 3, wire.
EndPointBack))
378 LOG_WARNING(
"Wrong wire end point detected - skipped");
382 if (STRCASECMP(
"CoplanarParallelWires", patternElement->GetAttribute(
"Type")) == 0)
384 coplanarParallelWires->
AddWire(wire);
386 else if (STRCASECMP(
"NWire", patternElement->GetAttribute(
"Type")) == 0)
392 if (STRCASECMP(
"CoplanarParallelWires", patternElement->GetAttribute(
"Type")) == 0)
394 tempPatterns.push_back(coplanarParallelWires);
398 tempPatterns[
i]->AddDistanceToOriginElementMm(0);
399 tempPatterns[
i]->AddDistanceToOriginToleranceElementMm(0);
400 tempPatterns[
i]->AddDistanceToOriginElementMm(10 * std::sqrt(2.0));
401 tempPatterns[
i]->AddDistanceToOriginToleranceElementMm(2);
402 tempPatterns[
i]->AddDistanceToOriginElementMm(20 * std::sqrt(2.0));
403 tempPatterns[
i]->AddDistanceToOriginToleranceElementMm(2);
404 tempPatterns[
i]->AddDistanceToOriginElementMm(30 * std::sqrt(2.0));
405 tempPatterns[
i]->AddDistanceToOriginToleranceElementMm(2);
406 tempPatterns[
i]->AddDistanceToOriginElementMm(40 * std::sqrt(2.0));
407 tempPatterns[
i]->AddDistanceToOriginToleranceElementMm(2);
411 tempPatterns[
i]->AddDistanceToOriginElementMm(0);
412 tempPatterns[
i]->AddDistanceToOriginToleranceElementMm(0);
413 tempPatterns[
i]->AddDistanceToOriginElementMm(10);
414 tempPatterns[
i]->AddDistanceToOriginToleranceElementMm(2);
415 tempPatterns[
i]->AddDistanceToOriginElementMm(20);
416 tempPatterns[
i]->AddDistanceToOriginToleranceElementMm(2);
417 tempPatterns[
i]->AddDistanceToOriginElementMm(30);
418 tempPatterns[
i]->AddDistanceToOriginToleranceElementMm(2);
419 tempPatterns[
i]->AddDistanceToOriginElementMm(40);
420 tempPatterns[
i]->AddDistanceToOriginToleranceElementMm(2);
423 else if (STRCASECMP(
"NWire", patternElement->GetAttribute(
"Type")) == 0)
426 tempPatterns.push_back(nWire);
428 tempPatterns[
i]->AddDistanceToOriginElementMm(0);
429 tempPatterns[
i]->AddDistanceToOriginToleranceElementMm(0);
431 double originToMiddle[3] = {(tempPatterns[
i]->GetWires()[1].EndPointBack[0] + tempPatterns[
i]->GetWires()[1].EndPointFront[0]) / 2 - tempPatterns[
i]->GetWires()[0].EndPointFront[0],
432 (tempPatterns[
i]->GetWires()[1].EndPointBack[1] + tempPatterns[
i]->GetWires()[1].EndPointFront[1]) / 2 - tempPatterns[
i]->GetWires()[0].EndPointFront[1],
433 (tempPatterns[
i]->GetWires()[1].EndPointBack[2] + tempPatterns[
i]->GetWires()[1].EndPointFront[2]) / 2 - tempPatterns[
i]->GetWires()[0].EndPointFront[2]
436 double originToEnd[3] = {tempPatterns[
i]->GetWires()[2].EndPointFront[0] - tempPatterns[
i]->GetWires()[0].EndPointFront[0],
437 tempPatterns[
i]->GetWires()[2].EndPointFront[1] - tempPatterns[
i]->GetWires()[0].EndPointFront[1],
438 tempPatterns[
i]->GetWires()[2].EndPointFront[2] - tempPatterns[
i]->GetWires()[0].EndPointFront[2]
441 vtkMath::Normalize(originToEnd);
443 double dot = vtkMath::Dot(originToMiddle, originToEnd);
444 const double projectedMiddle[3] = {originToEnd[0]* dot, originToEnd[1]* dot, originToEnd[2]* dot};
445 double distMidToOrigin = vtkMath::Norm(projectedMiddle);
447 tempPatterns[
i]->AddDistanceToOriginElementMm(distMidToOrigin);
448 tempPatterns[
i]->AddDistanceToOriginToleranceElementMm(15);
450 double distEndToOrigin = sqrt((tempPatterns[
i]->GetWires()[0].EndPointBack[0] - tempPatterns[
i]->GetWires()[2].EndPointBack[0]) * (tempPatterns[
i]->GetWires()[0].EndPointBack[0] - tempPatterns[
i]->GetWires()[2].EndPointBack[0]) + (tempPatterns[
i]->GetWires()[0].EndPointBack[1] - tempPatterns[
i]->GetWires()[2].EndPointBack[1]) * (tempPatterns[
i]->GetWires()[0].EndPointBack[1] - tempPatterns[
i]->GetWires()[2].EndPointBack[1]));
451 tempPatterns[
i]->AddDistanceToOriginElementMm(distEndToOrigin);
462 LOG_DEBUG(
"Endpoints of wires = ");
465 for (
unsigned int k = 0 ; k < tempPatterns.size() ; ++k)
467 unsigned int layer = k;
469 for (
int i = 0;
i < 3; ++
i)
471 vnl_vector<double> endPointFront(3);
472 vnl_vector<double> endPointBack(3);
474 for (
int j = 0; j < 3; ++j)
476 endPointFront[j] = tempPatterns[k]->GetWires()[
i].EndPointFront[j];
477 endPointBack[j] = tempPatterns[k]->GetWires()[
i].EndPointBack[j];
480 LOG_DEBUG(
"\t Front endpoint of wire " <<
i <<
" on layer " << layer <<
" = " << endPointFront);
481 LOG_DEBUG(
"\t Back endpoint of wire " <<
i <<
" on layer " << layer <<
" = " << endPointBack);
495 vtkMath::Subtract(tempPatterns[k]->GetWires()[0].EndPointFront, tempPatterns[k]->GetWires()[0].EndPointBack, wire1);
496 vtkMath::Subtract(tempPatterns[k]->GetWires()[2].EndPointFront, tempPatterns[k]->GetWires()[2].EndPointBack, wire3);
497 vtkMath::Cross(wire1, wire3, cross);
498 if (vtkMath::Norm(cross) > 0.001)
500 LOG_ERROR(
"The first and third wire of layer " << layer <<
" are not parallel!");
503 double closestTemp[3];
504 double parametricCoord1, parametricCoord2;
509 if (vtkLine::DistanceBetweenLines(
510 const_cast<double*>(tempNWire->
GetWires()[0].EndPointFront),
511 const_cast<double*>(tempNWire->
GetWires()[0].EndPointBack),
512 const_cast<double*>(tempNWire->
GetWires()[1].EndPointFront),
513 const_cast<double*>(tempNWire->
GetWires()[1].EndPointBack),
514 tempNWire->
IntersectPosW12, closestTemp, parametricCoord1, parametricCoord2) > 0.000001)
516 LOG_ERROR(
"The first and second wire of layer " << layer <<
" do not intersect each other!");
519 if (vtkLine::DistanceBetweenLines(
520 const_cast<double*>(tempNWire->
GetWires()[2].EndPointFront),
521 const_cast<double*>(tempNWire->
GetWires()[2].EndPointBack),
522 const_cast<double*>(tempNWire->
GetWires()[1].EndPointFront),
523 const_cast<double*>(tempNWire->
GetWires()[1].EndPointBack),
524 tempNWire->
IntersectPosW32, closestTemp, parametricCoord1, parametricCoord2) > 0.000001)
526 LOG_ERROR(
"The second and third wire of layer " << layer <<
" do not intersect each other!");
555 numWires += (*it)->GetWires().size();
557 if (aValue < numWires)
559 LOG_WARNING(
"Number of maximum fiducial point candidates is smaller than the number of wires contained in the pattern.");
PlusStatus ReadPhantomDefinition(vtkXMLDataElement *rootConfigElement)
void SetLinesVector(std::vector< std::vector< PlusFidLine > > &value)
std::vector< PlusFidPattern * > & GetPatterns()
void SetDotsFound(bool value)
void SetNumberOfMaximumFiducialPointCandidates(int aValue)
std::vector< PlusFidPattern * > & GetPatterns()
double GetPatternIntensity()
void DrawDots(PlusFidSegmentation::PixelType *image)
void SetNumberOfMaximumFiducialPointCandidates(int aMax)
PlusStatus ReadConfiguration(vtkXMLDataElement *rootConfigElement)
PlusFidPatternRecognition()
void WritePossibleFiducialOverlayImage(const std::vector< std::vector< double > > &fiducials, PlusFidSegmentation::PixelType *unalteredImage, const char *namePrefix, int frameIndex)
void SetName(const std::string &aName)
PlusFidSegmentation::PixelType * GetUnalteredImage()
double IntersectPosW32[3]
void SetFrameSize(const FrameSizeType &frameSize)
void SetPatterns(const std::vector< PlusFidPattern * > &value)
void SetNumDots(double value)
void SetCandidateFidValues(std::vector< PlusFidDot > value)
void SetDotsVector(std::vector< PlusFidDot > &value)
void SetIntensity(double value)
void MorphologicalOperations()
void SetFrameSize(const FrameSizeType &frameSize)
double GetThresholdImagePercent()
void SetCandidateFidValues(const std::vector< PlusFidDot > &value)
std::vector< PlusFidDot > & GetDotsVector()
PlusFidSegmentation m_FidSegmentation
static const double DOT_RADIUS
void SetDotsVector(const std::vector< PlusFidDot > &value)
std::vector< PlusFidDot > & GetCandidateFidValues()
std::vector< std::vector< double > > GetFoundDotsCoordinateValue()
const std::vector< PlusFidWire > & GetWires() const
bool Cluster(bool &tooManyCandidates)
const char const char * value
void SetFoundDotsCoordinateValue(std::vector< std::vector< double > > value)
virtual ~PlusFidPatternRecognition()
PlusStatus ReadConfiguration(vtkXMLDataElement *rootConfigElement, double minThetaRad, double maxThetaRad)
std::vector< std::vector< PlusFidLine > > & GetLinesVector()
std::vector< PlusFidPattern * > m_Patterns
double m_MaxLineLengthToleranceMm
void AddWire(const PlusFidWire &wire)
std::vector< PlusFidLine > & GetFoundLinesVector()
void DrawResults(PlusFidSegmentation::PixelType *image)
PlusStatus ReadConfiguration(vtkXMLDataElement *rootConfigElement)
void SetFrameSize(const FrameSizeType &frameSize)
PlusStatus RecognizePattern(vtkIGSIOTrackedFrameList *trackedFrameList, PatternRecognitionError &patternRecognitionError, int *numberOfSuccessfullySegmentedImages=NULL, std::vector< unsigned int > *segmentedFramesIndices=NULL)
static const double DOT_STEPS
void SetPatterns(const std::vector< PlusFidPattern * > &value)
void SetCandidateFidValues(const std::vector< PlusFidDot > &value)
PlusFidSegmentation::PixelType * GetWorking()
void Suppress(PlusFidSegmentation::PixelType *image, double percent_thresh)
PlusFidLineFinder m_FidLineFinder
PlusFidLabeling m_FidLabeling
std::vector< PlusFidDot > & GetDotsVector()
void SetMaxLineLengthToleranceMm(double value)
FrameSizeType GetFrameSize()
PlusStatus ReadConfiguration(vtkXMLDataElement *rootConfigElement)
double IntersectPosW12[3]