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"
39 #include "sliceViewer.h"
40 #include "ui_sliceViewer.h"
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"
53 using namespace DGtal;
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;
106 template <
typename TImage>
109 typedef ConstImageAdapter<TImage,
typename TImage::Domain,
110 functors::BasicDomainSubSampler<typename TImage::Domain, int, double>,
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()));
134 DGtal::ImageContainerBySTLVector < DGtal::Z3i::Domain, unsigned char > *anImage,
135 const ColorMapFunctor &aFunctor, QWidget *parent, Qt::WindowFlags flags) :
144 ui->verticalLayout_5->addWidget(aViewer);
147 ui->_horizontalSliderZ->setMinimum(anImage->domain().lowerBound()[2]);
148 ui->_horizontalSliderZ->setMaximum(anImage->domain().upperBound()[2]);
149 ui->_horizontalSliderZ->setValue(anImage->domain().lowerBound()[2]);
151 ui->_horizontalSliderY->setMinimum(anImage->domain().lowerBound()[1]);
152 ui->_horizontalSliderY->setMaximum(anImage->domain().upperBound()[1]);
153 ui->_horizontalSliderY->setValue(anImage->domain().lowerBound()[1]);
155 ui->_horizontalSliderX->setMinimum(anImage->domain().lowerBound()[0]);
156 ui->_horizontalSliderX->setMaximum(anImage->domain().upperBound()[0]);
157 ui->_horizontalSliderX->setValue(anImage->domain().lowerBound()[0]);
159 ui->_zoomXSlider->setMinimum( MIN_ZOOM_FACTOR);
160 ui->_zoomXSlider->setMaximum( MAX_ZOOM_FACTOR);
161 ui->_zoomXSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
163 ui->_zoomYSlider->setMinimum(MIN_ZOOM_FACTOR);
164 ui->_zoomYSlider->setMaximum(MAX_ZOOM_FACTOR);
165 ui->_zoomYSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
167 ui->_zoomZSlider->setMinimum(MIN_ZOOM_FACTOR);
168 ui->_zoomZSlider->setMaximum(MAX_ZOOM_FACTOR);
169 ui->_zoomZSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
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()));
220 ui->ImageProjX->setPixmap(aPixMap);
223 ui->ImageProjY->setPixmap(aPixMap);
226 ui->ImageProjZ->setPixmap(aPixMap);
244 ui->_zoomXSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
249 ui->_zoomYSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
254 ui->_zoomZSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
261 double gridSize = (double)INIT_SCALE1_ZOOM_FACTOR/
ui->_zoomXSlider->value();
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(
")") )));
269 double gridSize = (double)INIT_SCALE1_ZOOM_FACTOR/
ui->_zoomYSlider->value();
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(
")") )));
278 double gridSize = (double)INIT_SCALE1_ZOOM_FACTOR/
ui->_zoomZSlider->value();
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(
")") )));
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{};
295 QImage anImage = getImage(sliceImage, gridSize,
myColorMap);
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{};
307 QImage anImage = getImage(sliceImage, gridSize,
myColorMap);
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{};
319 QImage anImage = getImage(sliceImage, gridSize,
myColorMap );
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{};
332 double gridSize = ((double)INIT_SCALE1_ZOOM_FACTOR)/
ui->_zoomXSlider->value();
333 QImage anImage = getImage(sliceImage, gridSize,
myColorMap);
335 Z3i::Point imageOrigin =
myImage3D->domain().lowerBound();
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;
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],
346 (*myViewer).updateList(init);
347 (*myViewer).update();
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{};
363 double gridSize = ((double)INIT_SCALE1_ZOOM_FACTOR)/
ui->_zoomYSlider->value();
364 QImage anImage = getImage(sliceImage, gridSize,
myColorMap);
366 Z3i::Point imageOrigin =
myImage3D->domain().lowerBound();
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;
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();
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{};
391 double gridSize = (double)INIT_SCALE1_ZOOM_FACTOR/
ui->_zoomZSlider->value();
392 QImage anImage = getImage(sliceImage, gridSize,
myColorMap);
394 Z3i::Point imageOrigin =
myImage3D->domain().lowerBound();
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);
400 (*myViewer) << Viewer3D<>::updateDisplay;
402 (*myViewer) << DGtal::UpdateImageData< SliceImageAdapter,ColorMapFunctor > (2, sliceImage, 0,0, 0, 0, DGtal::Viewer3D<>::zDirection,
404 (*myViewer) << DGtal::UpdateImagePosition< Space, KSpace >(2, DGtal::Viewer3D<>::zDirection, imageOrigin[0],
405 imageOrigin[1], sliceNumber);
406 (*myViewer).updateList(init);
407 (*myViewer).update();
415 int main(
int argc,
char** argv )
420 std::string inputFileName;
421 DGtal::int64_t rescaleInputMin {0};
422 DGtal::int64_t rescaleInputMax {255};
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." )
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)." );
436 app.get_formatter()->column_width(40);
437 CLI11_PARSE(app, argc, argv);
441 typedef ImageContainerBySTLVector < Z3i::Domain, unsigned char > Image3D;
442 typedef ImageContainerBySTLVector < Z2i::Domain, unsigned char > Image2D;
445 typedef DGtal::functors::Rescaling<DGtal::int64_t ,unsigned char > RescalFCT;
446 Image3D image = GenericReader< Image3D >::importWithValueFunctor( inputFileName,RescalFCT(rescaleInputMin,
449 trace.info() <<
"Imported..."<< std::endl;
455 QApplication application(argc,argv);
456 Viewer3D<> *viewer =
new Viewer3D<>();
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);
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]));
void setImageProjY(const QPixmap &aPixMap)
void updateAllDisplayedImages()
void changeNormalColorMap()
void setScale1_1_ImageY()
void changeCoolColorMap()
void setScale1_1_ImageZ()
ColorMapFunctor myColorMap
void setImageProjX(const QPixmap &aPixMap)
MainWindow(DGtal::Viewer3D<> *viewer, DGtal::ImageContainerBySTLVector< DGtal::Z3i::Domain, unsigned char > *myImage3D, const ColorMapFunctor &aFunctor, QWidget *parent=0, Qt::WindowFlags flags=0)
DGtal::ConstImageAdapter< Image3D, Image2D::Domain, DGtal::functors::Projector< DGtal::Z3i::Space >, Image3D::Value, DGtal::functors::Identity > SliceImageAdapter
void setScale1_1_ImageX()
void setImageProjZ(const QPixmap &aPixMap)