DGtalTools  1.2.0
sliceViewer.cpp
1 
29 #include <iostream>
30 #ifndef Q_MOC_RUN
31 #include "DGtal/base/Common.h"
32 #include "DGtal/base/BasicFunctors.h"
33 #include "DGtal/helpers/StdDefs.h"
34 #include "DGtal/io/readers/GenericReader.h"
35 #include "DGtal/io/Color.h"
36 #include "DGtal/io/DrawWithDisplay3DModifier.h"
37 #endif
38 
39 #include "sliceViewer.h"
40 #include "ui_sliceViewer.h"
41 
42 
43 #ifndef Q_MOC_RUN
44 #include "DGtal/io/viewers/Viewer3D.h"
45 #include "DGtal/io/viewers/DrawWithViewer3DModifier.h"
46 #include "DGtal/io/readers/PointListReader.h"
47 #include "DGtal/images/ConstImageAdapter.h"
48 #endif
49 
50 #include "CLI11.hpp"
51 
52 using namespace std;
53 using namespace DGtal;
54 using namespace Z3i;
55 
56 
57 
58 
98 // Set to define slider int value and grid size
99 
100 static const int MIN_ZOOM_FACTOR = 10.0;
101 static const int MAX_ZOOM_FACTOR = 40.0;
102 static const int INIT_SCALE1_ZOOM_FACTOR = 20.0;
103 
104 
105 
106 template <typename TImage>
107 static QImage
108 getImage(const TImage &anImage, double gridSize, const MainWindow::ColorMapFunctor &colFunctor ){
109  typedef ConstImageAdapter<TImage, typename TImage::Domain,
110  functors::BasicDomainSubSampler<typename TImage::Domain, int, double>,
111  unsigned int,
112  MainWindow::ColorMapFunctor> ConstImageAdapterForSubSampling;
113 
114  std::vector<double> scales;
115  scales.push_back(gridSize);
116  scales.push_back(gridSize);
117  functors::BasicDomainSubSampler<typename TImage::Domain, int, double> subSampler (anImage.domain(),
118  scales, Z2i::Point(0,0));
119  typename TImage::Domain newDomain = subSampler.getSubSampledDomain();
120  ConstImageAdapterForSubSampling scaledImage (anImage, newDomain, subSampler, colFunctor );
121  unsigned int height = scaledImage.domain().upperBound()[1]-scaledImage.domain().lowerBound()[1];
122  unsigned int width = scaledImage.domain().upperBound()[0]-scaledImage.domain().lowerBound()[0];
123  QImage res (width, height,QImage::Format_RGB32 );
124  for(unsigned int i=0; i<height; i++){
125  for(unsigned int j=0; j<width; j++){
126  res.setPixel(j, height-i-1, scaledImage(Z2i::Point(j,i)+scaledImage.domain().lowerBound()));
127  }
128  }
129  return res;
130 }
131 
132 
133 MainWindow::MainWindow(DGtal::Viewer3D<> *aViewer,
134  DGtal::ImageContainerBySTLVector < DGtal::Z3i::Domain, unsigned char > *anImage,
135  const ColorMapFunctor &aFunctor, QWidget *parent, Qt::WindowFlags flags) :
136  QMainWindow(parent),
137  ui(new Ui::MainWindow),
138  myViewer(aViewer),
139  myImage3D(anImage),
140  myColorMap(aFunctor)
141 {
142 
143  ui->setupUi(this);
144  ui->verticalLayout_5->addWidget(aViewer);
145 
146 
147  ui->_horizontalSliderZ->setMinimum(anImage->domain().lowerBound()[2]);
148  ui->_horizontalSliderZ->setMaximum(anImage->domain().upperBound()[2]);
149  ui->_horizontalSliderZ->setValue(anImage->domain().lowerBound()[2]);
150 
151  ui->_horizontalSliderY->setMinimum(anImage->domain().lowerBound()[1]);
152  ui->_horizontalSliderY->setMaximum(anImage->domain().upperBound()[1]);
153  ui->_horizontalSliderY->setValue(anImage->domain().lowerBound()[1]);
154 
155  ui->_horizontalSliderX->setMinimum(anImage->domain().lowerBound()[0]);
156  ui->_horizontalSliderX->setMaximum(anImage->domain().upperBound()[0]);
157  ui->_horizontalSliderX->setValue(anImage->domain().lowerBound()[0]);
158 
159  ui->_zoomXSlider->setMinimum( MIN_ZOOM_FACTOR);
160  ui->_zoomXSlider->setMaximum( MAX_ZOOM_FACTOR);
161  ui->_zoomXSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
162 
163  ui->_zoomYSlider->setMinimum(MIN_ZOOM_FACTOR);
164  ui->_zoomYSlider->setMaximum(MAX_ZOOM_FACTOR);
165  ui->_zoomYSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
166 
167  ui->_zoomZSlider->setMinimum(MIN_ZOOM_FACTOR);
168  ui->_zoomZSlider->setMaximum(MAX_ZOOM_FACTOR);
169  ui->_zoomZSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
170 
171  QObject::connect(ui->_horizontalSliderX, SIGNAL(valueChanged(int)), this, SLOT(updateSliceImageX()));
172  QObject::connect(ui->_horizontalSliderY, SIGNAL(valueChanged(int)), this, SLOT(updateSliceImageY()));
173  QObject::connect(ui->_horizontalSliderZ, SIGNAL(valueChanged(int)), this, SLOT(updateSliceImageZ()));
174  QObject::connect(ui->_zoomXSlider, SIGNAL(valueChanged(int)), this, SLOT(updateZoomImageX()));
175  QObject::connect(ui->_zoomYSlider, SIGNAL(valueChanged(int)), this, SLOT(updateZoomImageY()));
176  QObject::connect(ui->_zoomZSlider, SIGNAL(valueChanged(int)), this, SLOT(updateZoomImageZ()));
177 
178  QObject::connect(ui->_scale1ButtonX, SIGNAL(clicked()), this, SLOT(setScale1_1_ImageX()));
179  QObject::connect(ui->_scale1ButtonY, SIGNAL(clicked()), this, SLOT(setScale1_1_ImageY()));
180  QObject::connect(ui->_scale1ButtonZ, SIGNAL(clicked()), this, SLOT(setScale1_1_ImageZ()));
181 
182  QObject::connect(ui->_CoolButton, SIGNAL(clicked()), this, SLOT(changeCoolColorMap()));
183  QObject::connect(ui->_HotButton, SIGNAL(clicked()), this, SLOT(changeHotColorMap()));
184  QObject::connect(ui->_HueButton, SIGNAL(clicked()), this, SLOT(changeHueColorMap()));
185  QObject::connect(ui->_NormalButton, SIGNAL(clicked()), this, SLOT(changeNormalColorMap()));
186 
187 
188 }
189 
191 {
192  delete ui;
193 }
194 
199 }
203 }
204 
208 }
212 }
216 }
217 
218 
219 void MainWindow::setImageProjX(const QPixmap &aPixMap){
220  ui->ImageProjX->setPixmap(aPixMap);
221 }
222 void MainWindow::setImageProjY(const QPixmap &aPixMap){
223  ui->ImageProjY->setPixmap(aPixMap);
224 }
225 void MainWindow::setImageProjZ(const QPixmap &aPixMap){
226  ui->ImageProjZ->setPixmap(aPixMap);
227 }
228 
229 
231  updateSliceImageX(ui->_horizontalSliderX->value(), false);
232 }
233 
235  updateSliceImageY(ui->_horizontalSliderY->value(), false);
236 }
237 
239  updateSliceImageZ(ui->_horizontalSliderZ->value(), false);
240 }
241 
242 
244  ui->_zoomXSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
246 }
247 
249  ui->_zoomYSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
251 }
252 
254  ui->_zoomZSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
256 }
257 
258 
259 
261  double gridSize = (double)INIT_SCALE1_ZOOM_FACTOR/ui->_zoomXSlider->value();
262  updateZoomImageX(ui->_horizontalSliderX->value(), gridSize );
263  QString gridStr = QString::number(gridSize, 'f', 3);
264  QString scaleStr = QString::number(1.0/gridSize, 'f', 3);
265  ui->_groupBoxX->setTitle(QString("Slice View X: sampling grid size: ").append(gridStr).
266  append(QString(" (zoom x "). append(scaleStr).append(QString(")") )));
267 }
269  double gridSize = (double)INIT_SCALE1_ZOOM_FACTOR/ui->_zoomYSlider->value();
270  updateZoomImageY(ui->_horizontalSliderY->value(), gridSize );
271  QString gridStr = QString::number(gridSize, 'f', 3);
272  QString scaleStr = QString::number(1.0/gridSize, 'f', 3);
273  ui->_groupBoxY->setTitle(QString("Slice View Y: sampling grid size: ").append(gridStr).
274  append(QString(" (zoom x "). append(scaleStr).append(QString(")") )));
275 
276 }
278  double gridSize = (double)INIT_SCALE1_ZOOM_FACTOR/ui->_zoomZSlider->value();
279  updateZoomImageZ(ui->_horizontalSliderZ->value(), gridSize );
280  QString gridStr = QString::number(gridSize, 'f', 3);
281  QString scaleStr = QString::number(1.0/gridSize, 'f', 3);
282  ui->_groupBoxZ->setTitle(QString("Slice View Z: sampling grid size: ").append(gridStr).
283  append(QString(" (zoom x "). append(scaleStr).append(QString(")") )));
284 
285 }
286 
287 
288 void MainWindow::updateZoomImageX(int sliceNumber, double gridSize){
289  DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(0);
290  DGtal::Z2i::Domain domain2D(invFunctor(myImage3D->domain().lowerBound()),
291  invFunctor(myImage3D->domain().upperBound()));
292  DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctor(sliceNumber); aSliceFunctor.initAddOneDim(0);
293  const functors::Identity identityFunctor{};
294  SliceImageAdapter sliceImage( *myImage3D, domain2D, aSliceFunctor, identityFunctor );
295  QImage anImage = getImage(sliceImage, gridSize, myColorMap);
296  setImageProjX(QPixmap::fromImage(anImage));
297 }
298 
299 void MainWindow::updateZoomImageY(int sliceNumber, double gridSize){
300  DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(1);
301  DGtal::Z2i::Domain domain2D(invFunctor(myImage3D->domain().lowerBound()),
302  invFunctor(myImage3D->domain().upperBound()));
303  DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctor(sliceNumber); aSliceFunctor.initAddOneDim(1);
304  const functors::Identity identityFunctor{};
305  SliceImageAdapter sliceImage( *myImage3D, domain2D, aSliceFunctor, identityFunctor );
306 
307  QImage anImage = getImage(sliceImage, gridSize, myColorMap);
308  setImageProjY(QPixmap::fromImage(anImage));
309 }
310 
311 
312 void MainWindow::updateZoomImageZ(int sliceNumber, double gridSize){
313  DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(2);
314  DGtal::Z2i::Domain domain2D(invFunctor(myImage3D->domain().lowerBound()),
315  invFunctor(myImage3D->domain().upperBound()));
316  DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctor(sliceNumber); aSliceFunctor.initAddOneDim(2);
317  const functors::Identity identityFunctor{};
318  SliceImageAdapter sliceImage( *myImage3D, domain2D, aSliceFunctor, identityFunctor );
319  QImage anImage = getImage(sliceImage, gridSize, myColorMap );
320  setImageProjZ(QPixmap::fromImage(anImage));
321 }
322 
323 
324 void MainWindow::updateSliceImageX(int sliceNumber, bool init){
325  DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(0);
326  DGtal::Z2i::Domain domain2D(invFunctor(myImage3D->domain().lowerBound()),
327  invFunctor(myImage3D->domain().upperBound()));
328  DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctor(sliceNumber); aSliceFunctor.initAddOneDim(0);
329  const functors::Identity identityFunctor{};
330  SliceImageAdapter sliceImage ( *myImage3D, domain2D, aSliceFunctor, identityFunctor );
331 
332  double gridSize = ((double)INIT_SCALE1_ZOOM_FACTOR)/ui->_zoomXSlider->value();
333  QImage anImage = getImage(sliceImage, gridSize,myColorMap);
334  setImageProjX(QPixmap::fromImage(anImage));
335  Z3i::Point imageOrigin = myImage3D->domain().lowerBound();
336  if(init){
337  (*myViewer) << DGtal::AddTextureImage2DWithFunctor<SliceImageAdapter, ColorMapFunctor, Z3i::Space, Z3i::KSpace>(sliceImage, myColorMap, DGtal::Viewer3D<Z3i::Space, Z3i::KSpace>::RGBMode);
338  (*myViewer) << DGtal::UpdateImagePosition< Space, KSpace >(0, DGtal::Viewer3D<>::xDirection, sliceNumber,
339  imageOrigin[1], imageOrigin[2]);
340  (*myViewer) << Viewer3D<>::updateDisplay;
341  }else{
342  (*myViewer) << DGtal::UpdateImageData< SliceImageAdapter, ColorMapFunctor > (0, sliceImage, 0, 0, 0 ,0, DGtal::Viewer3D<>::xDirection, myColorMap);
343  (*myViewer) << DGtal::UpdateImagePosition< Space, KSpace >(0, DGtal::Viewer3D<>::xDirection, sliceNumber, imageOrigin[1],
344  imageOrigin[2]);
345 
346  (*myViewer).updateList(init);
347  (*myViewer).update();
348  }
349 
350 
351 }
352 
353 
354 void MainWindow::updateSliceImageY( int sliceNumber, bool init){
355 
356  DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(1);
357  DGtal::Z2i::Domain domain2D(invFunctor(myImage3D->domain().lowerBound()),
358  invFunctor(myImage3D->domain().upperBound()));
359  DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctor(sliceNumber); aSliceFunctor.initAddOneDim(1);
360  const functors::Identity identityFunctor{};
361  SliceImageAdapter sliceImage( *myImage3D, domain2D, aSliceFunctor, identityFunctor );
362 
363  double gridSize = ((double)INIT_SCALE1_ZOOM_FACTOR)/ui->_zoomYSlider->value();
364  QImage anImage = getImage(sliceImage, gridSize, myColorMap);
365  setImageProjY(QPixmap::fromImage(anImage));
366  Z3i::Point imageOrigin = myImage3D->domain().lowerBound();
367  if(init){
368  (*myViewer) << DGtal::AddTextureImage2DWithFunctor<SliceImageAdapter, ColorMapFunctor, Z3i::Space, Z3i::KSpace>(sliceImage, myColorMap, DGtal::Viewer3D<Z3i::Space, Z3i::KSpace>::RGBMode);
369  (*myViewer) << DGtal::UpdateImagePosition< Space, KSpace >(1, DGtal::Viewer3D<>::yDirection, imageOrigin[0],
370  sliceNumber, imageOrigin[2]);
371  (*myViewer) << Viewer3D<>::updateDisplay;
372  }else{
373  (*myViewer) << DGtal::UpdateImageData< SliceImageAdapter, ColorMapFunctor > (1, sliceImage, 0,0, 0, 0, DGtal::Viewer3D<>::yDirection, myColorMap);
374  (*myViewer) << DGtal::UpdateImagePosition< Space, KSpace >(1, DGtal::Viewer3D<>::yDirection, imageOrigin[0],
375  sliceNumber, imageOrigin[2]);
376  (*myViewer).updateList(init);
377  (*myViewer).update();
378  }
379 
380 }
381 
382 
383 void MainWindow::updateSliceImageZ(int sliceNumber, bool init){
384 
385  DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(2);
386  DGtal::Z2i::Domain domain2D(invFunctor(myImage3D->domain().lowerBound()),
387  invFunctor(myImage3D->domain().upperBound()));
388  DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctor(sliceNumber); aSliceFunctor.initAddOneDim(2);
389  const functors::Identity identityFunctor{};
390  SliceImageAdapter sliceImage( *myImage3D, domain2D, aSliceFunctor, identityFunctor );
391  double gridSize = (double)INIT_SCALE1_ZOOM_FACTOR/ui->_zoomZSlider->value();
392  QImage anImage = getImage(sliceImage, gridSize, myColorMap);
393  setImageProjZ(QPixmap::fromImage(anImage));
394  Z3i::Point imageOrigin = myImage3D->domain().lowerBound();
395  if(init){
396  (*myViewer) << DGtal::AddTextureImage2DWithFunctor<SliceImageAdapter, ColorMapFunctor, Z3i::Space, Z3i::KSpace>(sliceImage, myColorMap, DGtal::Viewer3D<Z3i::Space, Z3i::KSpace>::RGBMode);
397  (*myViewer) << DGtal::UpdateImagePosition< Space, KSpace >(2, DGtal::Viewer3D<>::zDirection, imageOrigin[0],
398  imageOrigin[1], sliceNumber);
399 
400  (*myViewer) << Viewer3D<>::updateDisplay;
401  }else{
402  (*myViewer) << DGtal::UpdateImageData< SliceImageAdapter,ColorMapFunctor > (2, sliceImage, 0,0, 0, 0, DGtal::Viewer3D<>::zDirection,
403  myColorMap);
404  (*myViewer) << DGtal::UpdateImagePosition< Space, KSpace >(2, DGtal::Viewer3D<>::zDirection, imageOrigin[0],
405  imageOrigin[1], sliceNumber);
406  (*myViewer).updateList(init);
407  (*myViewer).update();
408  }
409 
410 
411 }
412 
413 
414 
415 int main( int argc, char** argv )
416 {
417 
418  // parse command line using CLI ----------------------------------------------
419  CLI::App app;
420  std::string inputFileName;
421  DGtal::int64_t rescaleInputMin {0};
422  DGtal::int64_t rescaleInputMax {255};
423  bool usehm {false};
424  bool usegh {false};
425  bool usegc {false};
426  app.description("Displays volume file with slice image by using QT and QGLviewer");
427  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." )
428  ->required()
429  ->check(CLI::ExistingFile);
430  app.add_flag("--hueColorMap", usehm, "use hue color map to display images." );
431  app.add_flag("--gradHotColorMap", usegh, "use hot gradient color map to display images." );
432  app.add_flag("--gradCoolColorMap", usegc, "use cool gradient color map to display images." );
433  app.add_option("--rescaleInputMin", rescaleInputMin,"min value used to rescale the input intensity (to avoid basic cast into 8 bits image)." );
434  app.add_option("--rescaleInputMax", rescaleInputMax,"max value used to rescale the input intensity (to avoid basic cast into 8 bits image)." );
435 
436  app.get_formatter()->column_width(40);
437  CLI11_PARSE(app, argc, argv);
438  // END parse command line using CLI ----------------------------------------------
439 
440 
441  typedef ImageContainerBySTLVector < Z3i::Domain, unsigned char > Image3D;
442  typedef ImageContainerBySTLVector < Z2i::Domain, unsigned char > Image2D;
443 
444 
445  typedef DGtal::functors::Rescaling<DGtal::int64_t ,unsigned char > RescalFCT;
446  Image3D image = GenericReader< Image3D >::importWithValueFunctor( inputFileName,RescalFCT(rescaleInputMin,
447  rescaleInputMax,
448  0, 255) );
449  trace.info() << "Imported..."<< std::endl;
450 
451 
452 
453 
454 
455  QApplication application(argc,argv);
456  Viewer3D<> *viewer = new Viewer3D<>();
457  viewer->show();
458 
459 
463  MainWindow::Id), 0,0);
464  w.setWindowTitle ( QString("sliceViewer"));
465  w.updateSliceImageX( image.domain().lowerBound()[0], true);
466  w.updateSliceImageY( image.domain().lowerBound()[1], true);
467  w.updateSliceImageZ( image.domain().lowerBound()[2], true);
468  w.show();
469  Z3i::Point size = image.domain().upperBound() - image.domain().lowerBound();
470  Z3i::Point center = image.domain().lowerBound()+size/2;
471  unsigned int maxDist = std::max(std::max(size[2], size[1]), size[2]);
472  viewer->camera()->setPosition(qglviewer::Vec(center[0],center[1],
473  center[2] + 2.0*maxDist));
474  viewer->camera()->setSceneCenter(qglviewer::Vec(center[0],center[1],center[2]));
475  application.exec();
476  delete viewer;
477 }
478 
void setImageProjY(const QPixmap &aPixMap)
void updateAllDisplayedImages()
void updateZoomImageX()
void changeNormalColorMap()
void updateSliceImageY()
Ui::MainWindow * ui
Definition: sliceViewer.h:142
Image3D * myImage3D
Definition: sliceViewer.h:144
void updateZoomImageY()
void setScale1_1_ImageY()
void changeCoolColorMap()
void setScale1_1_ImageZ()
ColorMapFunctor myColorMap
Definition: sliceViewer.h:145
void updateSliceImageX()
void setImageProjX(const QPixmap &aPixMap)
void updateZoomImageZ()
MainWindow(DGtal::Viewer3D<> *viewer, DGtal::ImageContainerBySTLVector< DGtal::Z3i::Domain, unsigned char > *myImage3D, const ColorMapFunctor &aFunctor, QWidget *parent=0, Qt::WindowFlags flags=0)
void updateSliceImageZ()
@ GradientMapCool
Definition: sliceViewer.h:54
@ GradientMapHot
Definition: sliceViewer.h:54
void changeHueColorMap()
void changeHotColorMap()
DGtal::ConstImageAdapter< Image3D, Image2D::Domain, DGtal::functors::Projector< DGtal::Z3i::Space >, Image3D::Value, DGtal::functors::Identity > SliceImageAdapter
Definition: sliceViewer.h:98
void setScale1_1_ImageX()
void setImageProjZ(const QPixmap &aPixMap)
Definition: ATu0v1.h:57
Definition: sliceViewer.h:43