7 #include "PlusConfigure.h" 11 #include "vnl/vnl_sparse_matrix.h" 12 #include "vnl/vnl_sparse_matrix_linear_system.h" 13 #include "vnl/algo/vnl_lsqr.h" 14 #include "vnl/vnl_cross.h" 17 #include "vtkTransform.h" 19 #define MINIMUM_NUMBER_OF_CALIBRATION_EQUATIONS 8 34 PlusStatus PlusMath::LSQRMinimize(
const std::vector< std::vector<double> >& aMatrix,
const std::vector<double>& bVector, vnl_vector<double>& resultVector,
double* mean,
double* stdev, vnl_vector<unsigned int>* notOutliersIndices)
36 LOG_TRACE(
"PlusMath::LSQRMinimize");
38 if (aMatrix.size() == 0)
40 LOG_ERROR(
"LSQRMinimize: A matrix is empty");
44 if (bVector.size() == 0)
46 LOG_ERROR(
"LSQRMinimize: b vector is empty");
52 const int n = aMatrix.begin()->size();
53 const int m = bVector.size();
55 std::vector<vnl_vector<double> > aMatrixVnl(m);
56 vnl_vector<double> row(n);
57 for (
unsigned int i = 0;
i < aMatrix.size(); ++
i)
59 for (
unsigned int r = 0; r < aMatrix[
i].size(); ++r)
61 row[r] = aMatrix[
i][r];
63 aMatrixVnl.push_back(row);
70 PlusStatus PlusMath::LSQRMinimize(
const std::vector< vnl_vector<double> >& aMatrix,
const std::vector<double>& bVector, vnl_vector<double>& resultVector,
double* mean,
double* stdev, vnl_vector<unsigned int>* notOutliersIndices )
72 LOG_TRACE(
"PlusMath::LSQRMinimize");
74 if (aMatrix.size() == 0)
76 LOG_ERROR(
"LSQRMinimize: A matrix is empty");
80 if (bVector.size() == 0)
82 LOG_ERROR(
"LSQRMinimize: b vector is empty");
88 const int n = aMatrix.begin()->size();
89 const int m = bVector.size();
91 vnl_sparse_matrix<double> sparseMatrixLeftSide(m, n);
92 vnl_vector<double> vectorRightSide(m);
94 for (
int row = 0; row < m; row++)
97 for (
int i = 0;
i < n;
i++)
99 sparseMatrixLeftSide(row,
i) = aMatrix[row].get(
i);
103 vectorRightSide.put(row, bVector[row]);
106 return PlusMath::LSQRMinimize(sparseMatrixLeftSide, vectorRightSide, resultVector, mean, stdev, notOutliersIndices);
111 PlusStatus PlusMath::LSQRMinimize(
const vnl_sparse_matrix<double>& sparseMatrixLeftSide,
const vnl_vector<double>& vectorRightSide, vnl_vector<double>& resultVector,
double* mean,
double* stdev, vnl_vector<unsigned int>* notOutliersIndices)
113 LOG_TRACE(
"PlusMath::LSQRMinimize");
117 vnl_sparse_matrix<double> aMatrix(sparseMatrixLeftSide);
118 vnl_vector<double> bVector(vectorRightSide);
120 bool outlierFound(
true);
125 vnl_sparse_matrix_linear_system<double> linearSystem(aMatrix, bVector);
128 vnl_lsqr lsqr(linearSystem);
131 int returnCode = lsqr.minimize(resultVector);
151 LOG_WARNING(
"LSQR fit may be inaccurate, CONLIM exceeded");
166 LOG_ERROR(
"LSQR fit may be inaccurate, ill-conditioned matrix");
169 LOG_WARNING(
"LSQR fit may be inaccurate, ITNLIM was reached");
173 LOG_ERROR(
"Unkown LSQR return code " << returnCode);
177 const double thresholdMultiplier = 3.0;
181 LOG_WARNING(
"Failed to remove outliers from linear equations!");
187 LOG_ERROR(
"It was not possible calibrate! Not enough equations!");
197 vnl_vector<double>& vectorRightSide,
198 vnl_vector<double>& resultVector,
200 double thresholdMultiplier,
203 vnl_vector<unsigned int>* nonOutlierIndices )
206 outlierFound =
false;
208 const unsigned int numberOfEquations = sparseMatrixLeftSide.rows();
209 const unsigned int numberOfUnknowns = resultVector.size();
211 if (vectorRightSide.size() != numberOfEquations)
213 LOG_ERROR(
"Input A matrix and b vector dimensions were not met (number of equations were not the same)!");
217 if (sparseMatrixLeftSide.cols() != numberOfUnknowns)
219 LOG_ERROR(
"Input A matrix dimension (columns) and number of unknowns are different (cols: " << sparseMatrixLeftSide.cols() <<
" unknowns: " << numberOfUnknowns <<
")");
224 vnl_vector<double> differenceVector(numberOfEquations, 0);
226 for (
unsigned int row = 0; row < numberOfEquations; ++row)
228 vnl_sparse_matrix<double>::row matrixRow = sparseMatrixLeftSide.get_row(row);
229 double difference(0);
231 for (
unsigned int i = 0;
i < numberOfUnknowns; ++
i)
234 difference += (matrixRow[
i].second * resultVector[
i]);
237 difference -= vectorRightSide[row];
240 differenceVector.put(row, difference);
244 const double meanDifference = differenceVector.mean();
247 vnl_vector<double> diffFromMean = differenceVector - meanDifference;
248 const double stdevDifference = sqrt(diffFromMean.squared_magnitude() / (1.0 * diffFromMean.size()));
250 LOG_DEBUG(
"Mean = " << std::fixed << meanDifference <<
" Stdev = " << stdevDifference);
254 *mean = meanDifference;
259 *stdev = stdevDifference;
263 std::vector< vnl_vector<double> > matrixRowsData;
264 std::vector< vnl_vector<int> > matrixRowsIndecies;
265 std::vector<double> bVector;
266 std::vector<double> auxiliarNonOutlierIndicesVector;
268 vnl_vector<double> rowData(numberOfUnknowns, 0.0);
269 vnl_vector<int> rowIndecies(numberOfUnknowns, 0);
273 for (
unsigned int row = 0; row < numberOfEquations; ++row)
275 if (fabs(differenceVector[row] - meanDifference) < thresholdMultiplier * stdevDifference)
280 vnl_sparse_matrix<double>::row matrixRow = sparseMatrixLeftSide.get_row(row);
281 for (
unsigned int i = 0;
i < matrixRow.size(); ++
i)
283 rowIndecies[
i] = matrixRow[
i].first;
284 rowData[
i] = matrixRow[
i].second;
288 matrixRowsData.push_back(rowData);
289 matrixRowsIndecies.push_back(rowIndecies);
290 bVector.push_back(vectorRightSide[row]);
291 if (nonOutlierIndices != NULL)
293 auxiliarNonOutlierIndicesVector.push_back(nonOutlierIndices->get(row));
300 LOG_DEBUG(
"Outlier: " << std::fixed << differenceVector[row] <<
"(mean: " << meanDifference <<
" stdev: " << stdevDifference <<
" outlierTreshold: " << thresholdMultiplier * stdevDifference <<
")");
308 vectorRightSide.clear();
309 vectorRightSide.set_size(bVector.size());
310 for (
unsigned int i = 0;
i < bVector.size(); ++
i)
312 vectorRightSide.put(
i, bVector[
i]);
315 if (nonOutlierIndices != NULL)
317 (*nonOutlierIndices).clear();
318 (*nonOutlierIndices).set_size(auxiliarNonOutlierIndicesVector.size());
319 for (
unsigned int i = 0;
i < auxiliarNonOutlierIndicesVector.size(); ++
i)
321 (*nonOutlierIndices).put(
i, auxiliarNonOutlierIndicesVector[
i]);
326 sparseMatrixLeftSide.resize(matrixRowsData.size(), numberOfUnknowns);
327 for (
unsigned int r = 0; r < matrixRowsData.size(); r++)
329 std::vector<int> rowIndices;
330 rowIndices.resize(matrixRowsIndecies[r].size());
331 memcpy(rowIndices.data(), matrixRowsIndecies[r].begin(),
sizeof(
int)*matrixRowsIndecies[r].size());
332 std::vector<double> rowData;
333 rowData.resize(matrixRowsData[r].size());
334 memcpy(rowData.data(), matrixRowsData[r].begin(),
sizeof(double)*matrixRowsData[r].size());
335 sparseMatrixLeftSide.set_row(r, rowIndices, rowData);
340 LOG_DEBUG(
"*** Outlier removal was successful! No more outlier found!");
349 LOG_TRACE(
"PlusMath::ConvertVtkMatrixToVnlMatrix");
351 for (
int row = 0; row < 4; row++)
353 for (
int column = 0; column < 4; column++)
355 outVnlMatrix.put(row, column, inVtkMatrix->GetElement(row, column));
363 LOG_TRACE(
"PlusMath::ConvertVnlMatrixToVtkMatrix");
365 outVtkMatrix->Identity();
367 for (
int row = 0; row < 3; row++)
369 for (
int column = 0; column < 4; column++)
371 outVtkMatrix->SetElement(row, column, inVnlMatrix.get(row, column));
379 vtkSmartPointer<vtkMatrix4x4> matrixVtk = vtkSmartPointer<vtkMatrix4x4>::New();
381 igsioMath::PrintVtkMatrix(matrixVtk, stream, precision);
387 vtkSmartPointer<vtkMatrix4x4> matrixVtk = vtkSmartPointer<vtkMatrix4x4>::New();
389 igsioMath::LogVtkMatrix(matrixVtk, precision);
static PlusStatus LSQRMinimize(const std::vector< std::vector< double > > &aMatrix, const std::vector< double > &bVector, vnl_vector< double > &resultVector, double *mean=NULL, double *stdev=NULL, vnl_vector< unsigned int > *notOutliersIndices=NULL)
#define MINIMUM_NUMBER_OF_CALIBRATION_EQUATIONS
static void PrintMatrix(vnl_matrix_fixed< double, 4, 4 > matrix, std::ostringstream &stream, int precision=3)
static void ConvertVtkMatrixToVnlMatrix(const vtkMatrix4x4 *inVtkMatrix, vnl_matrix_fixed< double, 4, 4 > &outVnlMatrix)
static void LogMatrix(const vnl_matrix_fixed< double, 4, 4 > &matrix, int precision=3)
static void ConvertVnlMatrixToVtkMatrix(const vnl_matrix_fixed< double, 4, 4 > &inVnlMatrix, vtkMatrix4x4 *outVtkMatrix)
static PlusStatus RemoveOutliersFromLSQR(vnl_sparse_matrix< double > &sparseMatrixLeftSide, vnl_vector< double > &vectorRightSide, vnl_vector< double > &resultVector, bool &outlierFound, double thresholdMultiplier=3.0, double *mean=NULL, double *stdev=NULL, vnl_vector< unsigned int > *nonOutlierIndices=NULL)