DGtalTools  1.5.beta
3dVolViewer.cpp
1 
28 #include <iostream>
29 
30 #include "DGtal/base/Common.h"
31 #include "DGtal/base/BasicFunctors.h"
32 #include "DGtal/helpers/StdDefs.h"
33 #include "DGtal/io/readers/GenericReader.h"
34 #include "DGtal/io/viewers/Viewer3D.h"
35 #include "DGtal/io/DrawWithDisplay3DModifier.h"
36 #include "DGtal/io/readers/PointListReader.h"
37 #include "DGtal/io/readers/MeshReader.h"
38 
39 #include "DGtal/io/Color.h"
40 #include "DGtal/io/colormaps/GradientColorMap.h"
41 #include "DGtal/images/ImageSelector.h"
42 
43 #include "CLI11.hpp"
44 
45 using namespace std;
46 using namespace DGtal;
47 using namespace Z3i;
48 
49 
104 template < typename Space = DGtal::Z3i::Space, typename KSpace = DGtal::Z3i::KSpace>
105 struct ViewerSnap: DGtal::Viewer3D <Space, KSpace>
106 {
107 
108  ViewerSnap(bool saveSnap): Viewer3D<Space, KSpace>(), mySaveSnap(saveSnap){
109  };
110 
111  virtual void
112  init(){
114  if(mySaveSnap){
115  QObject::connect(this, SIGNAL(drawFinished(bool)), this, SLOT(saveSnapshot(bool)));
116  }
117  };
118  bool mySaveSnap;
119 };
120 
121 typedef ViewerSnap<> Viewer;
122 
123 
124 
125 // call back function to display voxel coordinates
126 template<typename TImage>
127 int
128 displayCoordsCallBack( void* viewer, int name, void* data )
129 {
130  TImage *image = (TImage *) data;
131  std::stringstream ss;
133  // Check needed since simetimes the point appears outside (only in non debug mode).
134  if (image->domain().isInside(p)){
135  ss << "Selected intensity: " << (*image)(p) << "p " << p[0] << " "<< p[1] << " " << p[2] ;
136  ((Viewer *) viewer)->displayMessage(QString(ss.str().c_str()), 100000);
137  }
138  return 0;
139 }
140 
141 
142 template <typename TImage>
143 void
144 processDisplay(ViewerSnap<> &viewer, TImage &image,
145  const typename TImage::Value &thresholdMin,
146  const typename TImage::Value &thresholdMax,
147  unsigned int numDisplayedMax,
148  unsigned int transparency,
149  bool useTransIntensity=false,
150  bool interDisplay=false,
151  bool squaredTransp=false)
152 {
153  Domain domain = image.domain();
154  GradientColorMap<typename TImage::Value> gradient( thresholdMin, thresholdMax);
155  unsigned int numDisplayed = 0;
156  gradient.addColor(Color::Blue);
157  gradient.addColor(Color::Green);
158  gradient.addColor(Color::Yellow);
159  gradient.addColor(Color::Red);
160  typename TImage::Value varInt = 0;
161  if (useTransIntensity){
162  varInt = thresholdMax-thresholdMin;
163  }
164  for(Domain::ConstIterator it = domain.begin(), itend=domain.end(); it!=itend; ++it){
165  double trInt = 1.0;
166  if (useTransIntensity){
167  trInt = ((float)(image( (*it) )-thresholdMin)/(float)varInt);
168  }
169  typename TImage::Value val= image( (*it) );
170  if(numDisplayed > numDisplayedMax)
171  break;
172 
173  Color c= gradient(val);
174  if(val<=thresholdMax && val >=thresholdMin)
175  {
176 
177  viewer << CustomColors3D(Color(c.red(), c.green(),c.blue(),
178  static_cast<unsigned int>(transparency*trInt*(squaredTransp? trInt : 1.0))),
179  Color(c.red(), c.green(),c.blue(),
180  static_cast<unsigned int>(transparency*trInt*(squaredTransp? trInt: 1.0))));
181  if (interDisplay)
182  {
183  auto p = *it;
185  viewer << SetName3D( index ) ;
186  }
187  viewer << *it;
188  numDisplayed++;
189  }
190  }
191  if (interDisplay){
192  viewer << SetSelectCallback3D(displayCoordsCallBack<TImage>,
193  &image );
194  }
195 }
196 
197 
198 
199 
200 int main( int argc, char** argv )
201 {
202  // parse command line using CLI ----------------------------------------------
203  CLI::App app;
204  app.description("Display volume file as a voxel set by using QGLviewer. \n Example: \n \t 3dVolViewer $DGtal/examples/samples/lobster.vol -m 60 -t 10");
205  std::string inputFileName;
206  DGtal::int64_t rescaleInputMin {0};
207  DGtal::int64_t rescaleInputMax {255};
208  double thresholdMin {0};
209  double thresholdMax {255};
210  unsigned int transparency {255};
211  unsigned int numDisplayedMax {500000};
212  std::string displayMesh;
213  std::string snapShotFile;
214  std::vector<unsigned int> colorMesh;
215  std::vector<unsigned int > customBGColor;
216 
217  string inputType {""};
218  bool interactiveDisplayVoxCoords {false};
219  bool transIntensity {false};
220  bool transIntensitySq {false};
221  bool useLastCamSet {false};
222 
223  app.add_option("-i,--input,1", inputFileName, "vol file (.vol, .longvol .p3d, .pgm3d and if WITH_ITK is selected: dicom, dcm, mha, mhd). For longvol, dicom, dcm, mha or mhd formats, the input values are linearly scaled between 0 and 255." )
224  ->required()
225  ->check(CLI::ExistingFile);
226 #ifdef WITH_ITK
227  app.add_option("--inputType", inputType, "to specify the input image type (int or double).")
228  -> check(CLI::IsMember({"int", "double"}));
229 #endif
230  app.add_option("--thresholdMin,-m", thresholdMin, "threshold min (excluded) to define binary shape.", true);
231  app.add_option("--thresholdMax,-M", thresholdMax, "threshold max (included) to define binary shape.", true);
232  app.add_option("--rescaleInputMin", rescaleInputMin, "min value used to rescale the input intensity (to avoid basic cast into 8 bits image).", true);
233  app.add_option("--rescaleInputMax", rescaleInputMax, "max value used to rescale the input intensity (to avoid basic cast into 8 bits image).", true);
234  app.add_option("--numMaxVoxel,-n", numDisplayedMax, "set the maximal voxel number to be displayed.");
235  app.add_option("--displayMesh", displayMesh, "display a Mesh given in OFF or OFS format.");
236  app.add_option("--colorMesh", colorMesh, "set the color of Mesh (given from displayMesh option) : r g b a ")
237  ->expected(4);
238  app.add_option("--doSnapShotAndExit,-d", snapShotFile, "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). If the camera setting was not saved it will use the default camera setting.");
239  app.add_option("--customBGColor,-b", customBGColor, "set the R, G, B, A components of the colors of the sdp view")
240  ->expected(3);
241  app.add_option("--transparency,-t", transparency, "change the defaukt transparency", true);
242  app.add_flag("--transIntensity",transIntensity , "Used vocel intensity to define transparency valeue");
243  app.add_flag("--transIntensitySq",transIntensitySq , "Used squared vocel intensity to define transparency valeue");
244  app.add_flag("--interactiveDisplayVoxCoords,-c", interactiveDisplayVoxCoords, " by using this option the coordinates can be displayed after selection (shift+left click on voxel).");
245  app.add_flag("--useLastCameraSetting", useLastCamSet, "use the last camera setting of the user (i.e if a .qglviewer.xml file is present in the current directory)");
246  app.get_formatter()->column_width(40);
247  CLI11_PARSE(app, argc, argv);
248  // END parse command line using CLI ----------------------------------------------
249 
250  QApplication application(argc,argv);
251 
252  Viewer viewer(snapShotFile != "");
253  if(snapShotFile != ""){
254  viewer.setSnapshotFileName(QString(snapShotFile.c_str()));
255  }
256  viewer.setWindowTitle("simple Volume Viewer");
257  viewer.show();
261 
262  string extension = inputFileName.substr(inputFileName.find_last_of(".") + 1);
263 
264  std::vector<double> vectValD;
265  std::vector<int> vectValI;
266  std::vector<unsigned char> vectValUC;
267  // Image of different types are pre constructed here else it will be deleted after the type selection
268  // (and it is used in display callback)
269  Z3i::Domain d;
270  Image3D_D imageD = Image3D_D(d);
271  Image3D_I imageI = Image3D_I(d);
272  Image image = Image(d);
273  if (customBGColor.size() == 3)
274  {
275  viewer.myDefaultBackgroundColor = DGtal::Color(customBGColor[0],
276  customBGColor[1],
277  customBGColor[2], 255);
278  viewer.update();
279  viewer.draw();
280  }
281  if(extension != "sdp")
282  {
283  unsigned int numDisplayed=0;
284 
285 #ifdef WITH_ITK
286  if (inputType=="double")
287  {
288  imageD = DGtal::GenericReader<Image3D_D>::import(inputFileName);
289  trace.info() << "[done]"<< std::endl;
290  trace.info() << "Image loaded: D "<<imageD<< std::endl;
291  processDisplay(viewer, imageD, thresholdMin, thresholdMax, numDisplayedMax, transparency,
292  transIntensity||transIntensitySq, interactiveDisplayVoxCoords, transIntensitySq);
293  }
294  else if (inputType=="int")
295  {
296  imageI= DGtal::GenericReader<Image3D_I>::import(inputFileName);
297  trace.info() << "Image loaded: "<<image<< std::endl;
298  processDisplay(viewer, imageI, (int)thresholdMin, (int)thresholdMax, numDisplayedMax, transparency,
299  transIntensity||transIntensitySq, interactiveDisplayVoxCoords, transIntensitySq);
300  } else {
302  image = GenericReader< Image >::importWithValueFunctor( inputFileName,RescalFCT(rescaleInputMin,
303  rescaleInputMax,
304  0, 255) );
305  trace.info() << "Image loaded: "<<image<< std::endl;
306  processDisplay(viewer, image, thresholdMin, thresholdMax, numDisplayedMax, transparency,
307  transIntensity||transIntensitySq, interactiveDisplayVoxCoords, transIntensitySq);
308  }
309 #else
311  image = GenericReader< Image >::importWithValueFunctor( inputFileName,RescalFCT(rescaleInputMin,
312  rescaleInputMax,
313  0, 255) );
314  trace.info() << "Image loaded: "<<image<< std::endl;
315  processDisplay(viewer, image, thresholdMin, thresholdMax, numDisplayedMax, transparency,
316  transIntensity||transIntensitySq, interactiveDisplayVoxCoords, transIntensitySq);
317 #endif
318  }
319  else if(extension=="sdp")
320  {
321  vector<Z3i::RealPoint> vectVoxels = PointListReader<Z3i::RealPoint>::getPointsFromFile(inputFileName);
322  for(unsigned int i=0;i< vectVoxels.size(); i++){
323  viewer << Z3i::Point(vectVoxels.at(i), functors::Round<>());
324  }
325  }
326  if(displayMesh != "")
327  {
328  if(colorMesh.size() != 0)
329  {
330  Color c(colorMesh[0], colorMesh[1], colorMesh[2], colorMesh[3]);
331  viewer.setFillColor(c);
332  }
333 
334  DGtal::Mesh<Z3i::RealPoint> aMesh(colorMesh.size() == 0);
335  MeshReader<Z3i::RealPoint>::importOFFFile(displayMesh, aMesh);
336  viewer << aMesh;
337  }
338 
339  viewer << Viewer3D<>::updateDisplay;
340  if(snapShotFile != "" )
341  {
342  // Recover mesh position
343  viewer.restoreStateFromFile();
344  viewer.saveSnapshot(QString(snapShotFile.c_str()), true);
345  return 0;
346  }
347 
348  if (useLastCamSet)
349  {
350  viewer.restoreStateFromFile();
351  }
352  // First display transparency improve
353  viewer.sortTriangleFromCamera();
354  viewer.sortQuadFromCamera();
355  viewer.sortSurfelFromCamera();
356  viewer.sortPolygonFromCamera();
357  viewer << Viewer::updateDisplay;
358  trace.info() << "[display ready]"<< std::endl;
359  return application.exec();
360 }
int main(int argc, char **argv)
void green(const unsigned char aGreenValue)
void red(const unsigned char aRedValue)
void blue(const unsigned char aBlueValue)
typename Self::Domain Domain
std::ostream & info()
virtual void init()
boost::int64_t int64_t
Trace trace(traceWriterTerm)
static TContainer import(const std::string &filename, std::vector< unsigned int > dimSpace=std::vector< unsigned int >())