7 #include "PlusConfigure.h" 14 #include "vnl/vnl_vector.h" 15 #include "vnl/vnl_matrix.h" 16 #include "vnl/vnl_cross.h" 17 #include "vnl/algo/vnl_qr.h" 18 #include "vnl/algo/vnl_svd.h" 29 for (
int i = 0 ;
i < 6 ;
i++)
34 for (
int i = 0 ;
i < 16 ;
i++)
58 LOG_TRACE(
"FidLineFinder::ComputeParameters");
61 std::vector<PlusNWire> nWires;
68 nWires.push_back(*tempNWire);
73 std::vector<double> thetaXrad, thetaYrad, thetaZrad;
74 thetaXrad.push_back(vtkMath::RadiansFromDegrees(imageNormalVectorInPhantomFrameMaximumRotationAngleDeg[0]));
75 thetaXrad.push_back(0);
76 thetaXrad.push_back(vtkMath::RadiansFromDegrees(imageNormalVectorInPhantomFrameMaximumRotationAngleDeg[1]));
77 thetaYrad.push_back(vtkMath::RadiansFromDegrees(imageNormalVectorInPhantomFrameMaximumRotationAngleDeg[2]));
78 thetaYrad.push_back(0);
79 thetaYrad.push_back(vtkMath::RadiansFromDegrees(imageNormalVectorInPhantomFrameMaximumRotationAngleDeg[3]));
80 thetaZrad.push_back(vtkMath::RadiansFromDegrees(imageNormalVectorInPhantomFrameMaximumRotationAngleDeg[4]));
81 thetaZrad.push_back(0);
82 thetaZrad.push_back(vtkMath::RadiansFromDegrees(imageNormalVectorInPhantomFrameMaximumRotationAngleDeg[5]));
84 vnl_matrix<double> imageToPhantomTransform(4, 4);
86 for (
int i = 0 ;
i < 4 ;
i++)
88 for (
int j = 0 ; j < 4 ; j++)
94 vnl_vector<double> pointA(3), pointB(3), pointC(3);
97 for (
int i = 0;
i < 3 ;
i++)
99 pointA.put(
i, nWires[0].GetWires()[0].EndPointFront[
i]);
100 pointB.put(
i, nWires[0].GetWires()[0].EndPointBack[
i]);
101 pointC.put(
i, nWires[0].GetWires()[1].EndPointFront[
i]);
105 vnl_vector<double> AB(3);
106 AB = pointB - pointA;
107 vnl_vector<double> AC(3);
108 AC = pointC - pointA;
110 vnl_vector<double> normalVectorInPhantomCoord(3);
111 normalVectorInPhantomCoord = vnl_cross_3d(AB, AC);
113 vnl_vector<double> normalVectorInPhantomCoordExtended(4, 0);
115 for (
unsigned int i = 0 ;
i < normalVectorInPhantomCoord.size() ;
i++)
117 normalVectorInPhantomCoordExtended.put(
i, normalVectorInPhantomCoord.get(
i));
120 vnl_vector<double> normalImagePlane(3, 0);
121 normalImagePlane.put(2, 1);
123 vnl_vector<double> imageYunitVector(3, 0);
124 imageYunitVector.put(1, 1);
126 std::vector<double> finalAngleTable;
128 for (
int i = 0 ;
i < 3 ;
i++)
130 for (
int j = 0 ; j < 3 ; j++)
132 for (
int k = 0 ; k < 3 ; k++)
134 vnl_matrix<double> totalRotation(4, 4, 0);
135 double tX = thetaYrad[
i];
136 double tY = thetaYrad[j];
137 double tZ = thetaYrad[k];
138 totalRotation.put(0, 0, cos(tY)*cos(tZ));
139 totalRotation.put(0, 1, -cos(tX)*sin(tZ) + sin(tX)*sin(tY)*cos(tZ));
140 totalRotation.put(0, 2, sin(tX)*sin(tZ) + cos(tX)*sin(tY)*cos(tZ));
141 totalRotation.put(1, 0, cos(tY)*sin(tZ));
142 totalRotation.put(1, 1, cos(tX)*cos(tZ) + sin(tX)*sin(tY)*sin(tZ));
143 totalRotation.put(1, 2, -sin(tX)*cos(tZ) + cos(tX)*sin(tY)*sin(tZ));
144 totalRotation.put(2, 0, -sin(tY));
145 totalRotation.put(2, 1, sin(tX)*cos(tY));
146 totalRotation.put(2, 2, cos(tX)*cos(tY));
147 totalRotation.put(3, 3, 1);
149 vnl_matrix<double> totalTranform(4, 4);
150 totalTranform = totalRotation * imageToPhantomTransform;
152 vnl_vector<double> normalVectorInImageCoordExtended(4);
155 normalVectorInImageCoordExtended = totalTranform * normalVectorInPhantomCoordExtended;
157 vnl_vector<double> normalVectorInImageCoord(3);
159 for (
unsigned int i = 0 ;
i < normalVectorInImageCoord.size() ;
i++)
161 normalVectorInImageCoord.put(
i, normalVectorInImageCoordExtended.get(
i));
164 vnl_vector<double> lineDirectionVector(3);
165 lineDirectionVector = vnl_cross_3d(normalVectorInImageCoord, normalImagePlane);
167 double dotProductValue = dot_product(lineDirectionVector, imageYunitVector);
168 double normOfLineDirectionvector = lineDirectionVector.two_norm();
169 double angle = acos(dotProductValue / normOfLineDirectionvector);
170 finalAngleTable.push_back(angle);
176 m_MaxThetaRad = (*std::max_element(finalAngleTable.begin(), finalAngleTable.end()));
177 m_MinThetaRad = (*std::min_element(finalAngleTable.begin(), finalAngleTable.end()));
184 LOG_TRACE(
"FidLineFinder::ReadConfiguration");
186 XML_FIND_NESTED_ELEMENT_OPTIONAL(segmentationParameters, configData,
"Segmentation");
187 if (!segmentationParameters)
189 segmentationParameters = igsioXmlUtils::GetNestedElementWithName(configData,
"Segmentation");
193 XML_READ_SCALAR_ATTRIBUTE_WARNING(
double, ApproximateSpacingMmPerPixel, segmentationParameters);
196 int computeSegmentationParametersFromPhantomDefinition(0);
197 if (segmentationParameters->GetScalarAttribute(
"ComputeSegmentationParametersFromPhantomDefinition", computeSegmentationParametersFromPhantomDefinition)
198 && computeSegmentationParametersFromPhantomDefinition != 0)
200 XML_FIND_NESTED_ELEMENT_REQUIRED(phantomDefinition, segmentationParameters,
"PhantomDefinition");
201 XML_FIND_NESTED_ELEMENT_REQUIRED(customTransforms, segmentationParameters,
"CustomTransforms");
202 XML_READ_VECTOR_ATTRIBUTE_WARNING(
double, 16, ImageToPhantomTransform, customTransforms);
204 XML_READ_VECTOR_ATTRIBUTE_WARNING(
double, 6, ImageNormalVectorInPhantomFrameMaximumRotationAngleDeg, segmentationParameters);
205 XML_READ_SCALAR_ATTRIBUTE_WARNING(
double, CollinearPointsMaxDistanceFromLineMm, segmentationParameters);
211 XML_READ_SCALAR_ATTRIBUTE_WARNING(
double, MinThetaDegrees, segmentationParameters);
212 XML_READ_SCALAR_ATTRIBUTE_WARNING(
double, MaxThetaDegrees, segmentationParameters);
213 XML_READ_SCALAR_ATTRIBUTE_WARNING(
double, CollinearPointsMaxDistanceFromLineMm, segmentationParameters);
223 std::vector<PlusNWire> nWires;
230 nWires.push_back(*tempNWire);
241 LOG_TRACE(
"FidLineFinder::SetFrameSize(" << frameSize[0] <<
", " << frameSize[1] <<
")");
265 double y = (
y2 -
y1);
266 double x = (
x2 -
x1);
268 double angleRad = atan2(
y,
x);
277 if (
line.GetNumberOfPoints() < 1)
279 LOG_WARNING(
"Cannot compute parameters for an empty line");
284 std::vector<int> pointNum;
285 double lineIntensity = 0;
286 for (
unsigned int i = 0;
i <
line.GetNumberOfPoints();
i++)
288 pointNum.push_back(
line.GetPoint(
i));
289 lineIntensity +=
m_DotsVector[pointNum[
i]].GetDotIntensity();
291 line.SetIntensity(lineIntensity);
294 if (
line.GetNumberOfPoints() == 1)
296 line.SetStartPointIndex(
line.GetPoint(0));
297 line.SetEndPointIndex(
line.GetPoint(0));
302 line.SetStartPointIndex(
line.GetPoint(0));
305 for (
unsigned int i = 0;
i <
line.GetNumberOfPoints();
i++)
308 if (currentXposition > largestXposition)
310 largestXposition = currentXposition;
311 line.SetStartPointIndex(
line.GetPoint(
i));
316 for (
unsigned int i = 0;
i <
line.GetNumberOfPoints();
i++)
327 for (
unsigned int i = 0;
i <
line.GetNumberOfPoints();
i++)
333 line.SetStartPointIndex(
line.GetPoint(
i));
340 if (
line.GetNumberOfPoints() > 2)
343 std::vector<double>
x;
344 std::vector<double>
y;
348 vnl_matrix<double> A(
line.GetNumberOfPoints(), 3, 1);
350 for (
unsigned int i = 0;
i <
line.GetNumberOfPoints();
i++)
359 vnl_qr<double> QR(A);
360 vnl_matrix<double> Q = QR.Q();
361 vnl_matrix<double>
R = QR.R();
364 vnl_matrix<double> B(2, 2, 0);
365 B.put(0, 0,
R(1, 1));
366 B.put(0, 1,
R(1, 2));
367 B.put(1, 1,
R(2, 2));
370 vnl_svd<double> SVD(B);
371 vnl_matrix<double>
V = SVD.V();
376 c = -(n1 *
R(0, 1) + n2 *
R(0, 2)) /
R(0, 0);
378 if (-n2 < 0 && n1 < 0)
380 line.SetDirectionVector(0, n2);
381 line.SetDirectionVector(1, -n1);
385 line.SetDirectionVector(0, -n2);
386 line.SetDirectionVector(1, n1);
394 line.SetDirectionVector(0, xdif);
395 line.SetDirectionVector(1, ydif);
407 return sqrtf(xd * xd + yd * yd);
414 double x[3],
y[3], z[3];
428 return igsioMath::ComputeDistanceLinePoint(
x,
y, z);
435 LOG_TRACE(
"FidLineFinder::FindLines2Points");
442 std::vector<PlusFidLine> twoPointsLinesVector;
449 for (
unsigned int dot1Index = 0; dot1Index <
m_DotsVector.size() - 1; dot1Index++)
451 for (
unsigned int dot2Index = dot1Index + 1; dot2Index <
m_DotsVector.size(); dot2Index++)
467 bool duplicate = std::binary_search(twoPointsLinesVector.begin(), twoPointsLinesVector.end(), twoPointsLine,
PlusFidLine::compareLines);
474 twoPointsLinesVector.push_back(twoPointsLine);
496 LOG_TRACE(
"FidLineFinder::FindLines3Points");
499 unsigned int maxNumberOfPointsPerLine(0);
503 if (
int(
m_Patterns[
i]->GetWires().size()) > maxNumberOfPointsPerLine)
505 maxNumberOfPointsPerLine =
m_Patterns[
i]->GetWires().size();
511 for (
unsigned int linesVectorIndex = 3 ; linesVectorIndex <= maxNumberOfPointsPerLine ; linesVectorIndex++)
518 for (
unsigned int l = 0; l <
m_LinesVector[linesVectorIndex - 1].size(); l++)
521 currentShorterPointsLine =
m_LinesVector[linesVectorIndex - 1][l];
523 for (
unsigned int b3 = 0; b3 <
m_DotsVector.size(); b3++)
525 std::vector<int> candidatesIndex;
526 bool checkDuplicateFlag =
false;
528 for (
unsigned int previousPoints = 0 ; previousPoints < currentShorterPointsLine.
GetNumberOfPoints() ; previousPoints++)
530 candidatesIndex.push_back(currentShorterPointsLine.
GetPoint(previousPoints));
531 if (candidatesIndex[previousPoints] == b3)
533 checkDuplicateFlag =
true;
537 if (checkDuplicateFlag)
542 candidatesIndex.push_back(b3);
545 if (pointToLineDistance <= dist)
550 std::sort(candidatesIndex.begin(), candidatesIndex.end());
552 for (
unsigned int f = 0; f < candidatesIndex.size(); f++)
554 line.AddPoint(candidatesIndex[f]);
580 double dot = vtkMath::Dot(originToEndPointVector, originToNewPointVector);
590 std::vector<PlusFidLine> emptyLine;
625 std::vector<PlusFidLine> emptyLine;
677 LOG_TRACE(
"FidLineFinder::FindLines");
710 for (
int i = 0;
i < 16;
i++)
719 for (
int i = 0;
i < 6;
i++)
double m_MaxLinePairDistanceErrorPercent
double m_CollinearPointsMaxDistanceFromLineMm
static bool lessThan(const PlusFidLine &line1, const PlusFidLine &line2)
static double SegmentLength(const PlusFidDot &dot1, const PlusFidDot &dot2)
unsigned int GetNumberOfPoints() const
double m_ApproximateSpacingMmPerPixel
PlusStatus ReadConfiguration(vtkXMLDataElement *rootConfigElement)
Initial rotation matrix R
void SetImageToPhantomTransform(double *matrixElements)
int GetEndPointIndex() const
static double ComputeAngleRad(const PlusFidDot &dot1, const PlusFidDot &dot2)
int GetStartPointIndex() const
static bool compareLines(const PlusFidLine &line1, const PlusFidLine &line2)
bool AcceptAngleRad(double angleRad)
std::vector< PlusFidDot > m_CandidateFidValues
std::vector< PlusNWire > GetNWires()
bool AcceptLine(PlusFidLine &line)
void SetFrameSize(const FrameSizeType &frameSize)
void AddPoint(int aPoint)
FrameSizeType m_FrameSize
double m_ImageNormalVectorInPhantomFrameMaximumRotationAngleDeg[6]
void SetStartPointIndex(int index)
std::vector< std::vector< PlusFidLine > > & GetLinesVector()
std::vector< PlusFidPattern * > m_Patterns
double ComputeDistancePointLine(const PlusFidDot &dot, const PlusFidLine &line)
static void SetDefaultSegmentationParameters(vtkXMLDataElement *segmentationElement)
void SetMinThetaDegrees(double angleDeg)
int GetPoint(int aIndex) const
static double ComputeAngleRad(const PlusFidLine &line1)
void SetImageNormalVectorInPhantomFrameMaximumRotationAngleDeg(double *anglesDeg)
Direction vectors of rods y
double * GetImageNormalVectorInPhantomFrameMaximumRotationAngleDeg()
double * GetImageToPhantomTransform()
std::vector< PlusFidDot > m_DotsVector
std::vector< std::vector< PlusFidLine > > m_LinesVector
void ComputeLine(PlusFidLine &line)
void SetMaxThetaDegrees(double angleDeg)
virtual ~PlusFidLineFinder()
double m_ImageToPhantomTransform[16]