31 #include <QGLViewer/qglviewer.h>
34 #include "DGtal/base/Common.h"
35 #include "DGtal/helpers/StdDefs.h"
36 #include "DGtal/io/viewers/Viewer3D.h"
37 #include "DGtal/io/DrawWithDisplay3DModifier.h"
38 #include "DGtal/io/readers/PointListReader.h"
39 #include "DGtal/io/readers/MeshReader.h"
40 #include "DGtal/io/colormaps/GradientColorMap.h"
42 #include "DGtal/topology/helpers/Surfaces.h"
43 #include "DGtal/topology/SurfelAdjacency.h"
44 #include "DGtal/topology/CanonicCellEmbedder.h"
45 #include "DGtal/math/Statistic.h"
47 #include "DGtal/io/Color.h"
48 #include "DGtal/io/colormaps/GradientColorMap.h"
49 #include "DGtal/io/readers/GenericReader.h"
51 #include <boost/program_options/options_description.hpp>
52 #include <boost/program_options/parsers.hpp>
53 #include <boost/program_options/variables_map.hpp>
58 using namespace DGtal;
62 namespace po = boost::program_options;
130 template <
typename Space = DGtal::Z3i::Space,
typename KSpace = DGtal::Z3i::KSpace>
141 QObject::connect(
this, SIGNAL(drawFinished(
bool)),
this, SLOT(saveSnapshot(
bool)));
148 template <
typename Po
int>
150 getBoundingUpperAndLowerPoint(
const std::vector<Point> &vectorPt,
Point &ptLower,
Point &ptUpper){
151 for(
unsigned int i =1; i<vectorPt.size(); i++){
152 if(vectorPt.at(i)[0] < ptLower[0]){
153 ptLower[0] = vectorPt.at(i)[0];
155 if(vectorPt.at(i)[1] < ptLower[1]){
156 ptLower[1] = vectorPt.at(i)[1];
158 if(vectorPt.at(i)[2] < ptLower[2]){
159 ptLower[2] =vectorPt.at(i)[2];
161 if(vectorPt.at(i)[0] < ptLower[0]){
162 ptLower[0] = vectorPt.at(i)[0];
164 if(vectorPt.at(i)[1] < ptLower[1]){
165 ptLower[1] = vectorPt.at(i)[1];
167 if(vectorPt.at(i)[2] < ptLower[2]){
168 ptLower[2] =vectorPt.at(i)[2];
174 int main(
int argc,
char** argv )
181 po::options_description general_opt(
"Allowed options are: ");
182 general_opt.add_options()
183 (
"help,h",
"display this message")
184 (
"input,i", po::value<std::string>(),
"input file: sdpa (sequence of discrete points with attribute)" )
185 (
"reference,r", po::value<std::string>(),
"input reference file: sdpa (sequence of discrete points with attribute)" )
186 (
"compAccordingLabels,l",
"apply the comparisos only on points with same labels (by default fifth colomn)" )
187 (
"drawSurfelAssociations,a",
"Draw the surfel association." )
188 (
"fileMeasureOutput,o", po::value<std::string>(),
"specify the output file to store (append) the error stats else the result is given to std output. " )
189 (
"noWindows,n",
"Don't display Viewer windows." )
190 (
"doSnapShotAndExit,d", po::value<std::string>(),
"save display snapshot into file. Notes that the camera setting is set by default according the last saved configuration (use SHIFT+Key_M to save current camera setting in the Viewer3D)." )
191 (
"fixMaxColorValue", po::value<double>(),
"fix the maximal color value for the scale error display (else the scale is set from the maximal value)" )
192 (
"labelIndex", po::value<unsigned int>(),
"set the index of the label (by default set to 4) " )
193 (
"SDPindex", po::value<std::vector <unsigned int> >()->multitoken(),
"specify the sdp index (by default 0,1,2,3).");
197 bool cannotStart=
false;
198 po::variables_map vm;
202 po::store(po::parse_command_line(argc, argv, general_opt), vm);
203 }
catch(
const std::exception& ex){
205 trace.
error()<<
"Error checking program options: "<< ex.what()<< endl;
208 if(parseOK && ! vm.count(
"input"))
210 trace.
error() <<
" The input file name was not defined" << endl;
215 if( !parseOK || cannotStart || vm.count(
"help")||argc<=1)
217 trace.
info() <<
"Usage: " << argv[0] <<
" [input]\n"
218 <<
"It computes generic scalar surfel data comparisons (squared error) ( given from an input data file and from a reference one). \n \n"
219 <<
"Each surfels are associated to the nearest one of the reference surfels (computed by a 'brut force' search) "
220 <<
"This association can also be limited to surfel of same label (if available in the data and by using the --compAccordingLabels option )."
221 <<
"The comparison and surfel association can be displayed and result statistics are saved on output file (--fileMeasureOutput)."
222 <<
"You can also remove the interactive 3d view by just doing a snapshot and exit with option --doSnapShotAndExit. \n \n"
223 <<
"Example of use: \n \n"
224 <<
"3dCompSurfelData -i surfelCurvatureInput.dat -r surfelCurvatureRef.dat --fixMaxColorValue 0.8 -d visuSEcurvature.png -o statMeasures.dat \n \n "
225 <<
"=> From the two compared files you should obtain the result of the comparison (statMeasures.dat) with the associated visualisation (visuSEcurvature.png). \n \n \n "
226 << general_opt <<
"\n";
231 string inputFilename = vm[
"input"].as<std::string>();
232 string referenceFilename = vm[
"reference"].as<std::string>();
234 std::vector<Point4D> surfelAndScalarInput;
235 std::vector<Point4D> surfelAndScalarReference;
236 std::vector<Point1D> vectLabelsInput;
237 std::vector<Point1D> vectLabelsReference;
238 bool useLabels = vm.count(
"compAccordingLabels");
241 if(vm.count(
"labelIndex")){
242 std::vector<unsigned int > vectIndex;
243 vectIndex.push_back(vm[
"lSDPindex"].as<unsigned int >());
254 if(vm.count(
"SDPindex")) {
255 std::vector<unsigned int > vectIndex = vm[
"SDPindex"].as<std::vector<unsigned int > >();
256 if(vectIndex.size()!=4){
257 trace.
error() <<
"you need to specify the three indexes of vertex." << std::endl;
268 Point4D ptLower = surfelAndScalarReference.at(0);
269 Point4D ptUpper = surfelAndScalarReference.at(0);
270 getBoundingUpperAndLowerPoint(surfelAndScalarReference, ptLower, ptUpper);
271 getBoundingUpperAndLowerPoint(surfelAndScalarInput, ptLower, ptUpper);
273 K.
init(
Z3i::Point(2*ptLower[0]+1, 2*ptLower[1]+1, 2*ptLower[2]+1),
274 Z3i::Point(2*ptUpper[0]+1, 2*ptUpper[1]+1, 2*ptUpper[2]+1),
true);
277 std::vector<Cell> vectSurfelsReference;
278 std::vector<Cell> vectSurfelsInput;
281 for(
unsigned int i =0; i<surfelAndScalarReference.size(); i++){
282 Point4D pt4d = surfelAndScalarReference.at(i);
284 vectSurfelsReference.push_back(c);
287 for(
unsigned int i =0; i<surfelAndScalarInput.size(); i++){
288 Point4D pt4d = surfelAndScalarInput.at(i);
290 vectSurfelsInput.push_back(c);
300 std::vector<unsigned int> vectIndexMinToReference;
302 trace.
info() <<
"Associating each input surfel to reference:" << std::endl;
305 for(
unsigned int i=0;i <vectSurfelsInput.size(); i++){
308 unsigned int indexDistanceMin = 0;
309 double distanceMin = std::numeric_limits<int>::max() ;
310 for(
unsigned int j=0; j <vectSurfelsReference.size(); j++){
311 if(useLabels && vectLabelsReference.at(j) != vectLabelsInput.at(i)){
315 double distance = (ptCenterRef - ptCenterInput).norm();
316 if(distance < distanceMin){
317 distanceMin = distance;
318 indexDistanceMin = j;
321 vectIndexMinToReference.push_back(indexDistanceMin);
324 trace.
progressBar(surfelAndScalarInput.size(), surfelAndScalarInput.size());
333 QApplication application(argc,argv);
334 typedef ViewerSnap<>
Viewer;
337 Viewer viewer(K, vm.count(
"doSnapShotAndExit"));
338 if(vm.count(
"doSnapShotAndExit")){
339 viewer.setSnapshotFileName(QString(vm[
"doSnapShotAndExit"].as<std::string>().c_str()));
341 viewer.setWindowTitle(
"3dCompSurfel Viewer");
345 std::ofstream outputStatStream;
346 if(vm.count(
"fileMeasureOutput")){
347 outputStatStream.open(vm[
"fileMeasureOutput"].as<std::string>().c_str(), ios::app );
353 for(
unsigned int i=0;i <surfelAndScalarInput.size(); i++){
354 double scalarInput = surfelAndScalarInput.at(i)[3];
355 double scalarRef = surfelAndScalarReference.at(vectIndexMinToReference.at(i))[3];
356 double sqError = (scalarRef-scalarInput)*(scalarRef-scalarInput);
357 statErrors.addValue(sqError);
358 if(sqError> maxSqError){
362 double maxVal = vm.count(
"fixMaxColorValue")? vm[
"fixMaxColorValue"].as<
double>(): maxSqError;
365 gradientColorMap.addColor(
Color(255,255,255,100 ));
366 gradientColorMap.addColor(
Color(255,0,0,100 ) );
367 gradientColorMap.addColor(
Color(0,0,255,100 ) );
374 viewer <<
SetMode3D(vectSurfelsInput.at(0).className(),
"Basic");
375 for(
unsigned int i=0; i <surfelAndScalarInput.size(); i++){
376 double scalarInput = surfelAndScalarInput.at(i)[3];
377 double scalarRef = surfelAndScalarReference.at(vectIndexMinToReference.at(i))[3];
378 double sqError = (scalarRef-scalarInput)*(scalarRef-scalarInput);
379 viewer.setFillColor(gradientColorMap(sqError));
381 viewer << vectSurfelsInput.at(i);
382 if(vm.count(
"drawSurfelAssociations")){
383 viewer.addLine(embeder(vectSurfelsInput.at(i)),embeder(vectSurfelsReference.at(vectIndexMinToReference.at(i))));
387 statErrors.terminate();
388 if(vm.count(
"fileMeasureOutput")){
389 outputStatStream <<
"input= " << inputFilename <<
" reference=" << referenceFilename <<
" " ;
390 outputStatStream << statErrors << std::endl;
396 if(vm.count(
"doSnapShotAndExit")){
398 viewer.restoreStateFromFile();
399 std::string name = vm[
"doSnapShotAndExit"].as<std::string>();
400 std::string extension = name.substr(name.find_last_of(
".") + 1);
401 std::string basename = name.substr(0, name.find_last_of(
"."));
402 for(
int i=0; i< viewer.snapshotCounter()-1; i++){
404 s << basename <<
"-"<< setfill(
'0') << setw(4)<< i <<
"." << extension;
405 trace.
info() <<
"erase temp file: " << s.str() << std::endl;
406 remove(s.str().c_str());
409 s << basename <<
"-"<< setfill(
'0') << setw(4)<< viewer.snapshotCounter()-1 <<
"." << extension;
410 rename(s.str().c_str(), name.c_str());
414 if(vm.count(
"noWindows")){
417 return application.exec();
void progressBar(const double currentValue, const double maximalValue)
Cell uCell(const PreCell &c) const
bool init(const Point &lower, const Point &upper, bool isClosed)
Trace trace(traceWriterTerm)
typename Self::Point Point