00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "InspectorsImpl.h"
00037
00038 #include "PointMatcherPrivate.h"
00039
00040 #include <cassert>
00041 #include <iostream>
00042 #include <sstream>
00043 #include <fstream>
00044
00045 using namespace std;
00046
00047 template<typename T>
00048 InspectorsImpl<T>::PerformanceInspector::PerformanceInspector(const std::string& className, const ParametersDoc paramsDoc, const Parameters& params):
00049 Inspector(className,paramsDoc,params),
00050 baseFileName(Parametrizable::get<string>("baseFileName")),
00051 bDumpPerfOnExit(Parametrizable::get<bool>("dumpPerfOnExit")),
00052 bDumpStats(Parametrizable::get<bool>("dumpStats"))
00053
00054 {
00055 }
00056
00057 template<typename T>
00058 InspectorsImpl<T>::PerformanceInspector::PerformanceInspector(const Parameters& params):
00059 Inspector("PerformanceInspector", PerformanceInspector::availableParameters(), params),
00060 baseFileName(Parametrizable::get<string>("baseFileName")),
00061 bDumpPerfOnExit(Parametrizable::get<bool>("dumpPerfOnExit")),
00062 bDumpStats(Parametrizable::get<bool>("dumpStats"))
00063 {}
00064
00065 template<typename T>
00066 void InspectorsImpl<T>::PerformanceInspector::addStat(const std::string& name, double data)
00067 {
00068 if (!bDumpStats) return;
00069
00070 HistogramMap::iterator it(stats.find(name));
00071 if (it == stats.end()) {
00072 LOG_INFO_STREAM("Adding new stat: " << name);
00073 it = stats.insert(HistogramMap::value_type(name, Histogram(16, name, baseFileName, bDumpPerfOnExit))).first;
00074 }
00075 it->second.push_back(data);
00076 }
00077
00078 template<typename T>
00079 void InspectorsImpl<T>::PerformanceInspector::dumpStats(std::ostream& stream)
00080 {
00081
00082 for (BOOST_AUTO(it, stats.begin()); it != stats.end(); ++it)
00083 {
00084 it->second.dumpStats(stream);
00085 BOOST_AUTO(jt, it);
00086 ++jt;
00087 if (jt != stats.end())
00088 stream << ", ";
00089 }
00090 }
00091
00092 template<typename T>
00093 void InspectorsImpl<T>::PerformanceInspector::dumpStatsHeader(std::ostream& stream)
00094 {
00095 for (BOOST_AUTO(it, stats.begin()); it != stats.end(); ++it)
00096 {
00097 it->second.dumpStatsHeader(stream);
00098 BOOST_AUTO(jt, it);
00099 ++jt;
00100 if (jt != stats.end())
00101 stream << ", ";
00102 }
00103 }
00104
00105 template struct InspectorsImpl<float>::PerformanceInspector;
00106 template struct InspectorsImpl<double>::PerformanceInspector;
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 template<typename T>
00134 InspectorsImpl<T>::AbstractVTKInspector::AbstractVTKInspector(const std::string& className, const ParametersDoc paramsDoc, const Parameters& params):
00135 PerformanceInspector(className,paramsDoc,params),
00136 streamIter(0),
00137 bDumpIterationInfo(Parametrizable::get<bool>("dumpIterationInfo")),
00138 bDumpDataLinks(Parametrizable::get<bool>("dumpDataLinks")),
00139 bDumpReading(Parametrizable::get<bool>("dumpReading")),
00140 bDumpReference(Parametrizable::get<bool>("dumpReference"))
00141 {
00142 }
00143
00144
00145 template<typename T>
00146 void InspectorsImpl<T>::AbstractVTKInspector::dumpDataPoints(const DataPoints& data, std::ostream& stream)
00147 {
00148 const Matrix& features(data.features);
00149
00150
00151 stream << "# vtk DataFile Version 3.0\n";
00152 stream << "File created by libpointmatcher\n";
00153 stream << "ASCII\n";
00154 stream << "DATASET POLYDATA\n";
00155 stream << "POINTS " << features.cols() << " float\n";
00156 if(features.rows() == 4)
00157 {
00158 stream << features.topLeftCorner(3, features.cols()).transpose() << "\n";
00159 }
00160 else
00161 {
00162 stream << features.transpose() << "\n";
00163 }
00164
00165 stream << "VERTICES " << features.cols() << " "<< features.cols() * 2 << "\n";
00166 for (int i = 0; i < features.cols(); ++i)
00167 stream << "1 " << i << "\n";
00168
00169
00170
00171 stream << "POINT_DATA " << features.cols() << "\n";
00172
00173
00174 for(BOOST_AUTO(it, data.descriptorLabels.begin()); it != data.descriptorLabels.end(); it++)
00175 {
00176
00177
00178 if(it->text == "normals")
00179 {
00180 buildNormalStream(stream, "normals", data);
00181 }
00182 else if(it->text == "eigVectors")
00183 {
00184 buildTensorStream(stream, "eigVectors", data);
00185 }
00186 else if(it->text == "color")
00187 {
00188 buildColorStream(stream, "color", data);
00189 }
00190
00191 else if(it->span == 1)
00192 {
00193 buildScalarStream(stream, it->text, data);
00194 }
00195 else if(it->span == 3 || it->span == 2)
00196 {
00197 buildVectorStream(stream, it->text, data);
00198 }
00199 else
00200 {
00201 LOG_WARNING_STREAM("Could not save label named " << it->text << " (dim=" << it->span << ").");
00202 }
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 }
00223
00224 template<typename T>
00225 void InspectorsImpl<T>::AbstractVTKInspector::dumpMeshNodes(const DataPoints& data, std::ostream& stream)
00226 {
00227
00228 const Matrix& descriptors(data.descriptors.transpose());
00229
00230 assert(descriptors.cols() >= 15);
00231
00232 stream << "# vtk DataFile Version 3.0\n";
00233 stream << "Triangle mesh\n";
00234 stream << "ASCII\n";
00235 stream << "DATASET POLYDATA\n";
00236
00237 stream << "POINTS " << descriptors.rows() * 3 << " float\n";
00238 for (int i = 0; i < descriptors.rows(); i++)
00239 {
00240
00241 stream << descriptors.block(i, 3, 1, 3) << "\n";
00242 stream << descriptors.block(i, 6, 1, 3) << "\n";
00243 stream << descriptors.block(i, 9, 1, 3) << "\n";
00244 }
00245
00246
00247
00248
00249
00250
00251 stream << "POLYGONS " << descriptors.rows() << " " << descriptors.rows() * 4 << "\n";
00252 for (int i = 0; i < descriptors.rows(); i++)
00253 {
00254 stream << "3 " << (i*3) << " " << (i*3 + 1) << " " << (i*3 + 2) << "\n";
00255 }
00256
00257 stream << "CELL_DATA " << descriptors.rows() << "\n";
00258
00259 stream << "NORMALS triangle_normals float\n";
00260 stream << descriptors.block(0, 0, descriptors.rows(), 3) << "\n";
00261
00262
00263
00264
00265
00266
00267
00268
00269 }
00270
00271
00272 template<typename T>
00273 void InspectorsImpl<T>::AbstractVTKInspector::dumpDataLinks(
00274 const DataPoints& ref,
00275 const DataPoints& reading,
00276 const Matches& matches,
00277 const OutlierWeights& featureOutlierWeights,
00278 std::ostream& stream)
00279 {
00280
00281 const Matrix& refFeatures(ref.features);
00282 const int refPtCount(refFeatures.cols());
00283
00284 const Matrix& readingFeatures(reading.features);
00285 const int readingPtCount(readingFeatures.cols());
00286 const int totalPtCount(refPtCount+readingPtCount);
00287
00288 stream << "# vtk DataFile Version 3.0\n";
00289 stream << "comment\n";
00290 stream << "ASCII\n";
00291 stream << "DATASET POLYDATA\n";
00292
00293 stream << "POINTS " << totalPtCount << " float\n";
00294 if(refFeatures.rows() == 4)
00295 {
00296
00297 stream << refFeatures.topLeftCorner(3, refFeatures.cols()).transpose() << "\n";
00298
00299 stream << readingFeatures.topLeftCorner(3, readingFeatures.cols()).transpose() << "\n";
00300 }
00301 else
00302 {
00303
00304 stream << refFeatures.transpose() << "\n";
00305
00306 stream << readingFeatures.transpose() << "\n";
00307 }
00308 const int knn = matches.ids.rows();
00309
00310 stream << "LINES " << readingPtCount*knn << " " << readingPtCount*knn * 3 << "\n";
00311
00312 for(int k = 0; k < knn; k++)
00313 {
00314 for (int i = 0; i < readingPtCount; ++i)
00315 {
00316 stream << "2 " << refPtCount + i << " " << matches.ids(k, i) << "\n";
00317 }
00318 }
00319
00320 stream << "CELL_DATA " << readingPtCount*knn << "\n";
00321 stream << "SCALARS outlier float 1\n";
00322 stream << "LOOKUP_TABLE default\n";
00323
00324 for(int k = 0; k < knn; k++)
00325 {
00326 for (int i = 0; i < readingPtCount; ++i)
00327 {
00328 stream << featureOutlierWeights(k, i) << "\n";
00329 }
00330 }
00331
00332
00333
00334
00335
00336 }
00337
00338 template<typename T>
00339 void InspectorsImpl<T>::AbstractVTKInspector::dumpDataPoints(const DataPoints& filteredReference, const std::string& name)
00340 {
00341 ostream* stream(openStream(name));
00342 dumpDataPoints(filteredReference, *stream);
00343 closeStream(stream);
00344 }
00345
00346 template<typename T>
00347 void InspectorsImpl<T>::AbstractVTKInspector::dumpMeshNodes(const DataPoints& filteredReference, const std::string& name)
00348 {
00349 ostream* stream(openStream(name));
00350 dumpMeshNodes(filteredReference, *stream);
00351 closeStream(stream);
00352 }
00353
00354 template<typename T>
00355 void InspectorsImpl<T>::AbstractVTKInspector::dumpIteration(
00356 const size_t iterationNumber,
00357 const TransformationParameters& parameters,
00358 const DataPoints& filteredReference,
00359 const DataPoints& reading,
00360 const Matches& matches,
00361 const OutlierWeights& outlierWeights,
00362 const TransformationCheckers& transCheck)
00363 {
00364
00365 if (bDumpDataLinks){
00366 ostream* streamLinks(openStream("link", iterationNumber));
00367 dumpDataLinks(filteredReference, reading, matches, outlierWeights, *streamLinks);
00368 closeStream(streamLinks);
00369 }
00370
00371 if (bDumpReading){
00372 ostream* streamRead(openStream("reading", iterationNumber));
00373 dumpDataPoints(reading, *streamRead);
00374 closeStream(streamRead);
00375 }
00376
00377 if (bDumpReference){
00378 ostream* streamRef(openStream("reference", iterationNumber));
00379 dumpDataPoints(filteredReference, *streamRef);
00380 closeStream(streamRef);
00381 }
00382
00383 if (!bDumpIterationInfo) return;
00384
00385
00386 assert(streamIter);
00387
00388 if(iterationNumber == 0)
00389 {
00390
00391 for(unsigned int j = 0; j < transCheck.size(); j++)
00392 {
00393 for(unsigned int i=0; i < transCheck[j]->getConditionVariableNames().size(); i++)
00394 {
00395 if (!(j == 0 && i == 0))
00396 *streamIter << ", ";
00397 *streamIter << transCheck[j]->getConditionVariableNames()[i] << ", ";
00398 *streamIter << transCheck[j]->getLimitNames()[i];
00399 }
00400 }
00401
00402 *streamIter << "\n";
00403 }
00404
00405
00406 for(unsigned int j = 0; j < transCheck.size(); j++)
00407 {
00408 for(unsigned int i=0; i < transCheck[j]->getConditionVariables().size(); i++)
00409 {
00410
00411 if (!(j == 0 && i == 0))
00412 *streamIter << ", ";
00413
00414 *streamIter << transCheck[j]->getConditionVariables()[i] << ", ";
00415 *streamIter << transCheck[j]->getLimits()[i];
00416 }
00417 }
00418
00419 *streamIter << "\n";
00420 }
00421
00422 template<typename T>
00423 void InspectorsImpl<T>::AbstractVTKInspector::buildGenericAttributeStream(std::ostream& stream, const std::string& attribute, const std::string& nameTag, const DataPoints& cloud, const int forcedDim)
00424 {
00425 if (!cloud.descriptorExists(nameTag))
00426 return;
00427
00428 const BOOST_AUTO(desc, cloud.getDescriptorViewByName(nameTag));
00429 assert(desc.rows() <= forcedDim);
00430
00431 if(desc.rows() != 0)
00432 {
00433 if(attribute.compare("COLOR_SCALARS") == 0)
00434 {
00435 stream << attribute << " " << nameTag << " " << forcedDim << "\n";
00436 stream << padWithOnes(desc, forcedDim, desc.cols()).transpose();
00437 }
00438 else
00439 {
00440 stream << attribute << " " << nameTag << " float\n";
00441 if(attribute.compare("SCALARS") == 0)
00442 stream << "LOOKUP_TABLE default\n";
00443
00444 stream << padWithZeros(desc, forcedDim, desc.cols()).transpose();
00445 }
00446 stream << "\n";
00447 }
00448 }
00449
00450 template<typename T>
00451 void InspectorsImpl<T>::AbstractVTKInspector::buildScalarStream(std::ostream& stream,
00452 const std::string& name,
00453 const DataPoints& cloud)
00454 {
00455 buildGenericAttributeStream(stream, "SCALARS", name, cloud, 1);
00456 }
00457
00458 template<typename T>
00459 void InspectorsImpl<T>::AbstractVTKInspector::buildNormalStream(std::ostream& stream,
00460 const std::string& name,
00461 const DataPoints& cloud)
00462 {
00463 buildGenericAttributeStream(stream, "NORMALS", name, cloud, 3);
00464 }
00465
00466 template<typename T>
00467 void InspectorsImpl<T>::AbstractVTKInspector::buildVectorStream(std::ostream& stream,
00468 const std::string& name,
00469 const DataPoints& cloud)
00470 {
00471 buildGenericAttributeStream(stream, "VECTORS", name, cloud, 3);
00472 }
00473
00474 template<typename T>
00475 void InspectorsImpl<T>::AbstractVTKInspector::buildTensorStream(std::ostream& stream,
00476 const std::string& name,
00477 const DataPoints& cloud)
00478 {
00479 buildGenericAttributeStream(stream, "TENSORS", name, cloud, 9);
00480 }
00481
00482 template<typename T>
00483 void InspectorsImpl<T>::AbstractVTKInspector::buildColorStream(std::ostream& stream,
00484 const std::string& name,
00485 const DataPoints& cloud)
00486 {
00487 buildGenericAttributeStream(stream, "COLOR_SCALARS", name, cloud, 4);
00488 }
00489
00490 template<typename T>
00491 void InspectorsImpl<T>::AbstractVTKInspector::buildScalarStream(std::ostream& stream,
00492 const std::string& name,
00493 const DataPoints& ref,
00494 const DataPoints& reading)
00495 {
00496
00497 const Matrix descRef(ref.getDescriptorByName(name));
00498 const Matrix descRead(reading.getDescriptorByName(name));
00499
00500 if(descRef.rows() != 0 && descRead.rows() != 0)
00501 {
00502 stream << "SCALARS " << name << " float\n";
00503 stream << "LOOKUP_TABLE default\n";
00504
00505 stream << padWithZeros(
00506 descRef, 1, ref.descriptors.cols()).transpose();
00507 stream << "\n";
00508 stream << padWithZeros(
00509 descRead, 1, reading.descriptors.cols()).transpose();
00510 stream << "\n";
00511 }
00512 }
00513
00514
00515 template<typename T>
00516 void InspectorsImpl<T>::AbstractVTKInspector::buildNormalStream(std::ostream& stream,
00517 const std::string& name,
00518 const DataPoints& ref,
00519 const DataPoints& reading)
00520 {
00521
00522 const Matrix descRef(ref.getDescriptorByName(name));
00523 const Matrix descRead(reading.getDescriptorByName(name));
00524
00525 if(descRef.rows() != 0 && descRead.rows() != 0)
00526 {
00527 stream << "NORMALS " << name << " float\n";
00528
00529 stream << padWithZeros(
00530 descRef, 3, ref.descriptors.cols()).transpose();
00531 stream << "\n";
00532 stream << padWithZeros(
00533 descRead, 3, reading.descriptors.cols()).transpose();
00534 stream << "\n";
00535 }
00536 }
00537
00538
00539 template<typename T>
00540 void InspectorsImpl<T>::AbstractVTKInspector::buildVectorStream(std::ostream& stream,
00541 const std::string& name,
00542 const DataPoints& ref,
00543 const DataPoints& reading)
00544 {
00545
00546 const Matrix descRef(ref.getDescriptorByName(name));
00547 const Matrix descRead(reading.getDescriptorByName(name));
00548
00549 if(descRef.rows() != 0 && descRead.rows() != 0)
00550 {
00551 stream << "VECTORS " << name << " float\n";
00552
00553 stream << padWithZeros(
00554 descRef, 3, ref.descriptors.cols()).transpose();
00555 stream << "\n";
00556 stream << padWithZeros(
00557 descRead, 3, reading.descriptors.cols()).transpose();
00558 stream << "\n";
00559 }
00560 }
00561
00562
00563 template<typename T>
00564 void InspectorsImpl<T>::AbstractVTKInspector::buildTensorStream(std::ostream& stream,
00565 const std::string& name,
00566 const DataPoints& ref,
00567 const DataPoints& reading)
00568 {
00569
00570 const Matrix descRef(ref.getDescriptorByName(name));
00571 const Matrix descRead(reading.getDescriptorByName(name));
00572
00573 if(descRef.rows() != 0 && descRead.rows() != 0)
00574 {
00575 stream << "TENSORS " << name << " float\n";
00576
00577 stream << padWithZeros(
00578 descRef, 9, ref.descriptors.cols()).transpose();
00579 stream << "\n";
00580 stream << padWithZeros(
00581 descRead, 9, reading.descriptors.cols()).transpose();
00582 stream << "\n";
00583 }
00584 }
00585
00586 template<typename T>
00587 typename PointMatcher<T>::Matrix InspectorsImpl<T>::AbstractVTKInspector::padWithZeros(
00588 const Matrix m,
00589 const int expectedRow,
00590 const int expectedCols)
00591 {
00592 assert(m.cols() <= expectedCols || m.rows() <= expectedRow);
00593 if(m.cols() == expectedCols && m.rows() == expectedRow)
00594 {
00595 return m;
00596 }
00597 else
00598 {
00599 Matrix tmp = Matrix::Zero(expectedRow, expectedCols);
00600 tmp.topLeftCorner(m.rows(), m.cols()) = m;
00601 return tmp;
00602 }
00603
00604 }
00605
00606 template<typename T>
00607 typename PointMatcher<T>::Matrix InspectorsImpl<T>::AbstractVTKInspector::padWithOnes(
00608 const Matrix m,
00609 const int expectedRow,
00610 const int expectedCols)
00611 {
00612 assert(m.cols() <= expectedCols || m.rows() <= expectedRow);
00613 if(m.cols() == expectedCols && m.rows() == expectedRow)
00614 {
00615 return m;
00616 }
00617 else
00618 {
00619 Matrix tmp = Matrix::Ones(expectedRow, expectedCols);
00620 tmp.topLeftCorner(m.rows(), m.cols()) = m;
00621 return tmp;
00622 }
00623
00624 }
00625
00626 template<typename T>
00627 void InspectorsImpl<T>::AbstractVTKInspector::finish(const size_t iterationCount)
00628 {
00629 }
00630
00631
00632
00633
00634
00635 template<typename T>
00636 InspectorsImpl<T>::VTKFileInspector::VTKFileInspector(const Parameters& params):
00637 AbstractVTKInspector("VTKFileInspector", VTKFileInspector::availableParameters(), params),
00638 baseFileName(Parametrizable::get<string>("baseFileName")),
00639 bDumpIterationInfo(Parametrizable::get<bool>("dumpIterationInfo")),
00640 bDumpDataLinks(Parametrizable::get<bool>("dumpDataLinks")),
00641 bDumpReading(Parametrizable::get<bool>("dumpReading")),
00642 bDumpReference(Parametrizable::get<bool>("dumpReference"))
00643 {
00644 }
00645
00646 template<typename T>
00647 void InspectorsImpl<T>::VTKFileInspector::init()
00648 {
00649
00650 if (!bDumpIterationInfo) return;
00651
00652 ostringstream oss;
00653 oss << baseFileName << "-iterationInfo.csv";
00654 std::cerr << "writing to " << oss.str() << std::endl;
00655
00656 this->streamIter = new ofstream(oss.str().c_str());
00657 if (this->streamIter->fail())
00658 throw std::runtime_error("Couldn't open the file \"" + oss.str() + "\". Check if directory exist.");
00659
00660 }
00661
00662 template<typename T>
00663 void InspectorsImpl<T>::VTKFileInspector::finish(const size_t iterationCount)
00664 {
00665 if (!bDumpIterationInfo) return;
00666 closeStream(this->streamIter);
00667 }
00668
00669 template<typename T>
00670 std::ostream* InspectorsImpl<T>::VTKFileInspector::openStream(const std::string& role)
00671 {
00672 string filteredStr = role;
00673 if(role.substr(role.size()-4,4) == ".vtk")
00674 filteredStr = role.substr(0, role.size()-4);
00675
00676 ostringstream oss;
00677 if(baseFileName != "")
00678 oss << baseFileName << "-" << filteredStr << ".vtk";
00679 else
00680 oss << filteredStr << ".vtk";
00681
00682 std::cerr << "writing to " << oss.str() << std::endl;
00683 ofstream* file = new ofstream(oss.str().c_str());
00684 if (file->fail())
00685 throw std::runtime_error("Couldn't open the file \"" + oss.str() + "\". Check if directory exist.");
00686 return file;
00687 }
00688
00689 template<typename T>
00690 std::ostream* InspectorsImpl<T>::VTKFileInspector::openStream(const std::string& role, const size_t iterationNumber)
00691 {
00692 ostringstream oss;
00693 oss << baseFileName << "-" << role << "-" << iterationNumber << ".vtk";
00694 ofstream* file = new ofstream(oss.str().c_str());
00695 if (file->fail())
00696 throw std::runtime_error("Couldn't open the file \"" + oss.str() + "\". Check if directory exist.");
00697 return file;
00698 }
00699
00700 template<typename T>
00701 void InspectorsImpl<T>::VTKFileInspector::closeStream(std::ostream* stream)
00702 {
00703 delete stream;
00704 }
00705
00706
00707
00708 template struct InspectorsImpl<float>::VTKFileInspector;
00709 template struct InspectorsImpl<double>::VTKFileInspector;