DGtalTools 2.0.0
Loading...
Searching...
No Matches
3dCompSurfelData.cpp
1
30
31#include <iostream>
32#include <stdio.h>
33
34#include "DGtal/base/Common.h"
35#include "DGtal/helpers/StdDefs.h"
36#include "DGtal/io/viewers/PolyscopeViewer.h"
37#include "DGtal/io/readers/PointListReader.h"
38#include "DGtal/io/readers/MeshReader.h"
39
40#include "DGtal/topology/helpers/Surfaces.h"
41#include "DGtal/topology/SurfelAdjacency.h"
42#include "DGtal/topology/CanonicCellEmbedder.h"
43#include "DGtal/math/Statistic.h"
44
45#include "DGtal/io/Color.h"
46#include "DGtal/io/colormaps/GradientColorMap.h"
47#include "DGtal/io/readers/GenericReader.h"
48
49#include "CLI11.hpp"
50
51
52#include <limits>
53
54using namespace std;
55using namespace DGtal;
56using namespace Z3i;
57
58
59
116template < typename Point>
117void
118getBoundingUpperAndLowerPoint(const std::vector<Point> &vectorPt, Point &ptLower, Point &ptUpper){
119 for(unsigned int i =1; i<vectorPt.size(); i++){
120 if(vectorPt.at(i)[0] < ptLower[0]){
121 ptLower[0] = vectorPt.at(i)[0];
122 }
123 if(vectorPt.at(i)[1] < ptLower[1]){
124 ptLower[1] = vectorPt.at(i)[1];
125 }
126 if(vectorPt.at(i)[2] < ptLower[2]){
127 ptLower[2] =vectorPt.at(i)[2];
128 }
129 if(vectorPt.at(i)[0] < ptLower[0]){
130 ptLower[0] = vectorPt.at(i)[0];
131 }
132 if(vectorPt.at(i)[1] < ptLower[1]){
133 ptLower[1] = vectorPt.at(i)[1];
134 }
135 if(vectorPt.at(i)[2] < ptLower[2]){
136 ptLower[2] =vectorPt.at(i)[2];
137 }
138 }
139}
140
141
142int main( int argc, char** argv )
143{
144 typedef PointVector<4, double> Point4D;
145 typedef PointVector<1, int> Point1D;
146
147 // parse command line using CLI ----------------------------------------------
148 CLI::App app;
149 std::string inputFileName;
150 std::string referenceFileName;
151 std::string fileMeasureOutput;
152 std::string snapShotName;
153 bool useLabels {false};
154 bool drawSurfelAssociations {false};
155 unsigned int labelIndex {4};
156 std::vector<unsigned int> vectSDPindex;
157
158 app.description("Computes generic scalar surfel data comparisons (squared error) (given from an input data file and from a reference one).\n Each surfels are associated to the nearest one of the reference surfels (computed by a 'brut force' search). This association can also be limited to surfel of same label (if available in the data and by using the --compAccordingLabels option). The comparison and surfel association can be displayed and result statistics are saved on output file (--fileMeasureOutput). You can also remove the interactive 3d view by just doing a snapshot and exit with option --doSnapShotAndExit.\n \t Example of use: \n \t \t 3dCompSurfelData -i surfelCurvatureInput.dat -r surfelCurvatureRef.dat --fixMaxColorValue 0.8 -d visuSEcurvature.png -o statMeasures.dat \n \n \t \t => From the two compared files you should obtain the result of the comparison (statMeasures.dat) with the associated visualisation (visuSEcurvature.png).\n");
159
160 app.add_option("-i,--input,1", inputFileName, "input file: sdpa (sequence of discrete points with attribute)" )
161 ->required()
162 ->check(CLI::ExistingFile);
163
164 app.add_option("-r,--reference,2", referenceFileName, "input file: sdpa (sequence of discrete points with attribute)" )
165 ->required()
166 ->check(CLI::ExistingFile);
167 app.add_flag("-l,--compAccordingLabels", useLabels, "apply the comparisos only on points with same labels (by default fifth colomn)" );
168 app.add_flag("-a,--drawSurfelAssociations", drawSurfelAssociations, "Draw the surfel association.");
169 app.add_option("-o,--fileMeasureOutput",fileMeasureOutput, "specify the output file to store (append) the error stats else the result is given to std output. ");
170
171 auto labOptio = app.add_option("--labelIndex", labelIndex,"set the index of the label (by default set to 4) " );
172 app.add_option("--SDPindex",vectSDPindex, "specify the sdp index (by default 0,1,2,3).")
173 ->expected(4);
174
175 app.get_formatter()->column_width(40);
176 CLI11_PARSE(app, argc, argv);
177 // END parse command line using CLI ----------------------------------------------
178
179
180
181
182 Z3i::KSpace K;
183
184 std::vector<Point4D> surfelAndScalarInput;
185 std::vector<Point4D> surfelAndScalarReference;
186 std::vector<Point1D> vectLabelsInput;
187 std::vector<Point1D> vectLabelsReference;
188
189 if(useLabels){
190 if(labOptio->count() > 0){
191 std::vector<unsigned int > vectIndex;
192 vectIndex.push_back(labelIndex);
193 vectLabelsInput = PointListReader<Point1D>::getPointsFromFile(inputFileName, vectIndex);
194 vectLabelsReference = PointListReader<Point1D>::getPointsFromFile(referenceFileName, vectIndex);
195 }else{
196 vectLabelsInput = PointListReader<Point1D>::getPointsFromFile(inputFileName);
197 vectLabelsReference = PointListReader<Point1D>::getPointsFromFile(referenceFileName);
198 }
199 }
200
201
202 if(vectSDPindex.size() == 4) {
203 surfelAndScalarInput = PointListReader<Point4D>::getPointsFromFile(inputFileName, vectSDPindex);
204 surfelAndScalarReference = PointListReader<Point4D>::getPointsFromFile(referenceFileName, vectSDPindex);
205 }else{
206 surfelAndScalarInput = PointListReader<Point4D>::getPointsFromFile(inputFileName);
207 surfelAndScalarReference = PointListReader<Point4D>::getPointsFromFile(referenceFileName);
208 }
209
210
211 Point4D ptLower = surfelAndScalarReference.at(0);
212 Point4D ptUpper = surfelAndScalarReference.at(0);
213 getBoundingUpperAndLowerPoint(surfelAndScalarReference, ptLower, ptUpper);
214 getBoundingUpperAndLowerPoint(surfelAndScalarInput, ptLower, ptUpper);
215
216 K.init(Z3i::Point(2*ptLower[0]+1, 2*ptLower[1]+1, 2*ptLower[2]+1),
217 Z3i::Point(2*ptUpper[0]+1, 2*ptUpper[1]+1, 2*ptUpper[2]+1), true);
218
219
220 std::vector<Cell> vectSurfelsReference;
221 std::vector<Cell> vectSurfelsInput;
222
223 // Construction of the set of surfels
224 for(unsigned int i =0; i<surfelAndScalarReference.size(); i++){
225 Point4D pt4d = surfelAndScalarReference.at(i);
226 Cell c = K.uCell(Z3i::Point(pt4d[0], pt4d[1], pt4d[2]));
227 vectSurfelsReference.push_back(c);
228 }
229 // Construction of the set of surfels
230 for(unsigned int i =0; i<surfelAndScalarInput.size(); i++){
231 Point4D pt4d = surfelAndScalarInput.at(i);
232 Cell c = K.uCell(Z3i::Point(pt4d[0], pt4d[1], pt4d[2]));
233 vectSurfelsInput.push_back(c);
234 }
235
236
237 // Brut force association of each surfel of the input to the reference with the minimal distance.
238 // For each surfel of the input we associate an index to the nearest surfel of the reference.
239 // if the option --compAccordingLabels is selected then we search only surfel of same label (more precise comparisons in some cases)
240
241
242 CanonicCellEmbedder<KSpace> embeder(K);
243 std::vector<unsigned int> vectIndexMinToReference;
244
245 trace.info() << "Associating each input surfel to reference:" << std::endl;
246 trace.progressBar(0, surfelAndScalarInput.size());
247
248 for(unsigned int i=0;i <vectSurfelsInput.size(); i++){
249 trace.progressBar(i, vectSurfelsInput.size());
250 Z3i::RealPoint ptCenterInput = embeder(vectSurfelsInput.at(i));
251 unsigned int indexDistanceMin = 0;
252 double distanceMin = std::numeric_limits<int>::max() ;
253 for(unsigned int j=0; j <vectSurfelsReference.size(); j++){
254 if(useLabels && vectLabelsReference.at(j) != vectLabelsInput.at(i)){
255 continue;
256 }
257 Z3i::RealPoint ptCenterRef = embeder(vectSurfelsReference.at(j));
258 double distance = (ptCenterRef - ptCenterInput).norm();
259 if(distance < distanceMin){
260 distanceMin = distance;
261 indexDistanceMin = j;
262 }
263 }
264 vectIndexMinToReference.push_back(indexDistanceMin);
265
266 }
267 trace.progressBar(surfelAndScalarInput.size(), surfelAndScalarInput.size());
268 trace.info() << std::endl;
269
270
271
272 //-------------------------
273 // Displaying input with error and computing statistics
274
275
276 typedef PolyscopeViewer<> Viewer;
277 Viewer viewer(K);
278 viewer.allowReuseList = true;
279
280 Statistic<double> statErrors(true);
281 std::ofstream outputStatStream;
282
283 if(fileMeasureOutput != ""){
284 outputStatStream.open(fileMeasureOutput.c_str(), ios::app );
285 }
286
287 double maxSqError=0;
288 for(unsigned int i=0;i <surfelAndScalarInput.size(); i++){
289 double scalarInput = surfelAndScalarInput.at(i)[3];
290 double scalarRef = surfelAndScalarReference.at(vectIndexMinToReference.at(i))[3];
291 double sqError = (scalarRef-scalarInput)*(scalarRef-scalarInput);
292 statErrors.addValue(sqError);
293 if(sqError> maxSqError){
294 maxSqError =sqError;
295 }
296 }
297
298 trace.info() << "Maximal error:" << maxSqError << std::endl;
299 for(unsigned int i=0; i <surfelAndScalarInput.size(); i++){
300 double scalarInput = surfelAndScalarInput.at(i)[3];
301 double scalarRef = surfelAndScalarReference.at(vectIndexMinToReference.at(i))[3];
302 double sqError = (scalarRef-scalarInput)*(scalarRef-scalarInput);
303
304 viewer << WithQuantity(vectSurfelsInput.at(i), "Squared Error", sqError);
305 }
306
307 if(drawSurfelAssociations){
308 // Second loop to draw associations
309 // Allow for easier groupping with viewer
310 for(unsigned int i=0; i <surfelAndScalarInput.size(); i++){
311 viewer.drawLine(embeder(vectSurfelsInput.at(i)),embeder(vectSurfelsReference.at(vectIndexMinToReference.at(i))));
312 }
313 }
314
315 statErrors.terminate();
316 if(fileMeasureOutput != ""){
317 outputStatStream << "input= " << inputFileName << " reference=" << referenceFileName << " " ;
318 outputStatStream << statErrors << std::endl;
319 }else{
320 trace.info() << statErrors;
321 }
322
323 viewer.show();
324 return 0;
325}
Definition ATu0v1.h:57