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 "DGtal/io/readers/DicomReader.h" 42 #include "sliceViewer.h" 43 #include "ui_sliceViewer.h" 47 #include "DGtal/io/viewers/Viewer3D.h" 48 #include "DGtal/io/viewers/DrawWithViewer3DModifier.h" 49 #include "DGtal/io/readers/PointListReader.h" 50 #include "DGtal/images/ConstImageAdapter.h" 51 #include <boost/program_options/options_description.hpp> 52 #include <boost/program_options/parsers.hpp> 53 #include <boost/program_options/variables_map.hpp> 57 using namespace DGtal;
61 namespace po = boost::program_options;
102 static const int MIN_ZOOM_FACTOR = 10.0;
103 static const int MAX_ZOOM_FACTOR = 40.0;
104 static const int INIT_SCALE1_ZOOM_FACTOR = 20.0;
108 template <
typename TImage>
111 typedef ConstImageAdapter<TImage,
typename TImage::Domain,
112 functors::BasicDomainSubSampler<typename TImage::Domain, int, double>,
116 std::vector<double> scales;
117 scales.push_back(gridSize);
118 scales.push_back(gridSize);
119 functors::BasicDomainSubSampler<typename TImage::Domain, int, double> subSampler (anImage.domain(),
120 scales, Z2i::Point(0,0));
121 typename TImage::Domain newDomain = subSampler.getSubSampledDomain();
122 ConstImageAdapterForSubSampling scaledImage (anImage, newDomain, subSampler, colFunctor );
123 unsigned int height = scaledImage.domain().upperBound()[1]-scaledImage.domain().lowerBound()[1];
124 unsigned int width = scaledImage.domain().upperBound()[0]-scaledImage.domain().lowerBound()[0];
125 QImage res (width, height,QImage::Format_RGB32 );
126 for(
unsigned int i=0; i<height; i++){
127 for(
unsigned int j=0; j<width; j++){
128 res.setPixel(j, height-i-1, scaledImage(Z2i::Point(j,i)+scaledImage.domain().lowerBound()));
136 DGtal::ImageContainerBySTLVector < DGtal::Z3i::Domain, unsigned char > *anImage,
137 const ColorMapFunctor &aFunctor, QWidget *parent, Qt::WindowFlags flags) :
146 ui->verticalLayout_5->addWidget(aViewer);
149 ui->_horizontalSliderZ->setMinimum(anImage->domain().lowerBound()[2]);
150 ui->_horizontalSliderZ->setMaximum(anImage->domain().upperBound()[2]);
151 ui->_horizontalSliderZ->setValue(anImage->domain().lowerBound()[2]);
153 ui->_horizontalSliderY->setMinimum(anImage->domain().lowerBound()[1]);
154 ui->_horizontalSliderY->setMaximum(anImage->domain().upperBound()[1]);
155 ui->_horizontalSliderY->setValue(anImage->domain().lowerBound()[1]);
157 ui->_horizontalSliderX->setMinimum(anImage->domain().lowerBound()[0]);
158 ui->_horizontalSliderX->setMaximum(anImage->domain().upperBound()[0]);
159 ui->_horizontalSliderX->setValue(anImage->domain().lowerBound()[0]);
161 ui->_zoomXSlider->setMinimum( MIN_ZOOM_FACTOR);
162 ui->_zoomXSlider->setMaximum( MAX_ZOOM_FACTOR);
163 ui->_zoomXSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
165 ui->_zoomYSlider->setMinimum(MIN_ZOOM_FACTOR);
166 ui->_zoomYSlider->setMaximum(MAX_ZOOM_FACTOR);
167 ui->_zoomYSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
169 ui->_zoomZSlider->setMinimum(MIN_ZOOM_FACTOR);
170 ui->_zoomZSlider->setMaximum(MAX_ZOOM_FACTOR);
171 ui->_zoomZSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
173 QObject::connect(
ui->_horizontalSliderX, SIGNAL(valueChanged(
int)),
this, SLOT(
updateSliceImageX()));
174 QObject::connect(
ui->_horizontalSliderY, SIGNAL(valueChanged(
int)),
this, SLOT(
updateSliceImageY()));
175 QObject::connect(
ui->_horizontalSliderZ, SIGNAL(valueChanged(
int)),
this, SLOT(
updateSliceImageZ()));
176 QObject::connect(
ui->_zoomXSlider, SIGNAL(valueChanged(
int)),
this, SLOT(
updateZoomImageX()));
177 QObject::connect(
ui->_zoomYSlider, SIGNAL(valueChanged(
int)),
this, SLOT(
updateZoomImageY()));
178 QObject::connect(
ui->_zoomZSlider, SIGNAL(valueChanged(
int)),
this, SLOT(
updateZoomImageZ()));
222 ui->ImageProjX->setPixmap(aPixMap);
225 ui->ImageProjY->setPixmap(aPixMap);
228 ui->ImageProjZ->setPixmap(aPixMap);
246 ui->_zoomXSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
251 ui->_zoomYSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
256 ui->_zoomZSlider->setValue(INIT_SCALE1_ZOOM_FACTOR);
263 double gridSize = (double)INIT_SCALE1_ZOOM_FACTOR/
ui->_zoomXSlider->value();
265 QString gridStr = QString::number(gridSize,
'f', 3);
266 QString scaleStr = QString::number(1.0/gridSize,
'f', 3);
267 ui->_groupBoxX->setTitle(QString(
"Slice View X: sampling grid size: ").append(gridStr).
268 append(QString(
" (zoom x "). append(scaleStr).append(QString(
")") )));
271 double gridSize = (double)INIT_SCALE1_ZOOM_FACTOR/
ui->_zoomYSlider->value();
273 QString gridStr = QString::number(gridSize,
'f', 3);
274 QString scaleStr = QString::number(1.0/gridSize,
'f', 3);
275 ui->_groupBoxY->setTitle(QString(
"Slice View Y: sampling grid size: ").append(gridStr).
276 append(QString(
" (zoom x "). append(scaleStr).append(QString(
")") )));
280 double gridSize = (double)INIT_SCALE1_ZOOM_FACTOR/
ui->_zoomZSlider->value();
282 QString gridStr = QString::number(gridSize,
'f', 3);
283 QString scaleStr = QString::number(1.0/gridSize,
'f', 3);
284 ui->_groupBoxZ->setTitle(QString(
"Slice View Z: sampling grid size: ").append(gridStr).
285 append(QString(
" (zoom x "). append(scaleStr).append(QString(
")") )));
291 DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(0);
292 DGtal::Z2i::Domain domain2D(invFunctor(
myImage3D->domain().lowerBound()),
293 invFunctor(
myImage3D->domain().upperBound()));
294 DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctor(sliceNumber); aSliceFunctor.initAddOneDim(0);
295 const functors::Identity identityFunctor{};
297 QImage anImage = getImage(sliceImage, gridSize,
myColorMap);
302 DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(1);
303 DGtal::Z2i::Domain domain2D(invFunctor(
myImage3D->domain().lowerBound()),
304 invFunctor(
myImage3D->domain().upperBound()));
305 DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctor(sliceNumber); aSliceFunctor.initAddOneDim(1);
306 const functors::Identity identityFunctor{};
309 QImage anImage = getImage(sliceImage, gridSize,
myColorMap);
315 DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(2);
316 DGtal::Z2i::Domain domain2D(invFunctor(
myImage3D->domain().lowerBound()),
317 invFunctor(
myImage3D->domain().upperBound()));
318 DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctor(sliceNumber); aSliceFunctor.initAddOneDim(2);
319 const functors::Identity identityFunctor{};
321 QImage anImage = getImage(sliceImage, gridSize,
myColorMap );
327 DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(0);
328 DGtal::Z2i::Domain domain2D(invFunctor(
myImage3D->domain().lowerBound()),
329 invFunctor(
myImage3D->domain().upperBound()));
330 DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctor(sliceNumber); aSliceFunctor.initAddOneDim(0);
331 const functors::Identity identityFunctor{};
334 double gridSize = ((double)INIT_SCALE1_ZOOM_FACTOR)/
ui->_zoomXSlider->value();
335 QImage anImage = getImage(sliceImage, gridSize,
myColorMap);
337 Z3i::Point imageOrigin =
myImage3D->domain().lowerBound();
339 (*myViewer) << DGtal::AddTextureImage2DWithFunctor<SliceImageAdapter, ColorMapFunctor, Z3i::Space, Z3i::KSpace>(sliceImage,
myColorMap, DGtal::Viewer3D<Z3i::Space, Z3i::KSpace>::RGBMode);
340 (*myViewer) << DGtal::UpdateImagePosition< Space, KSpace >(0, DGtal::Viewer3D<>::xDirection, sliceNumber,
341 imageOrigin[1], imageOrigin[2]);
342 (*myViewer) << Viewer3D<>::updateDisplay;
344 (*myViewer) << DGtal::UpdateImageData< SliceImageAdapter, ColorMapFunctor > (0, sliceImage, 0, 0, 0 ,0, DGtal::Viewer3D<>::xDirection,
myColorMap);
345 (*myViewer) << DGtal::UpdateImagePosition< Space, KSpace >(0, DGtal::Viewer3D<>::xDirection, sliceNumber, imageOrigin[1],
348 (*myViewer).updateList(init);
349 (*myViewer).update();
358 DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(1);
359 DGtal::Z2i::Domain domain2D(invFunctor(
myImage3D->domain().lowerBound()),
360 invFunctor(
myImage3D->domain().upperBound()));
361 DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctor(sliceNumber); aSliceFunctor.initAddOneDim(1);
362 const functors::Identity identityFunctor{};
365 double gridSize = ((double)INIT_SCALE1_ZOOM_FACTOR)/
ui->_zoomYSlider->value();
366 QImage anImage = getImage(sliceImage, gridSize,
myColorMap);
368 Z3i::Point imageOrigin =
myImage3D->domain().lowerBound();
370 (*myViewer) << DGtal::AddTextureImage2DWithFunctor<SliceImageAdapter, ColorMapFunctor, Z3i::Space, Z3i::KSpace>(sliceImage,
myColorMap, DGtal::Viewer3D<Z3i::Space, Z3i::KSpace>::RGBMode);
371 (*myViewer) << DGtal::UpdateImagePosition< Space, KSpace >(1, DGtal::Viewer3D<>::yDirection, imageOrigin[0],
372 sliceNumber, imageOrigin[2]);
373 (*myViewer) << Viewer3D<>::updateDisplay;
375 (*myViewer) << DGtal::UpdateImageData< SliceImageAdapter, ColorMapFunctor > (1, sliceImage, 0,0, 0, 0, DGtal::Viewer3D<>::yDirection,
myColorMap);
376 (*myViewer) << DGtal::UpdateImagePosition< Space, KSpace >(1, DGtal::Viewer3D<>::yDirection, imageOrigin[0],
377 sliceNumber, imageOrigin[2]);
378 (*myViewer).updateList(init);
379 (*myViewer).update();
387 DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(2);
388 DGtal::Z2i::Domain domain2D(invFunctor(
myImage3D->domain().lowerBound()),
389 invFunctor(
myImage3D->domain().upperBound()));
390 DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctor(sliceNumber); aSliceFunctor.initAddOneDim(2);
391 const functors::Identity identityFunctor{};
393 double gridSize = (double)INIT_SCALE1_ZOOM_FACTOR/
ui->_zoomZSlider->value();
394 QImage anImage = getImage(sliceImage, gridSize,
myColorMap);
396 Z3i::Point imageOrigin =
myImage3D->domain().lowerBound();
398 (*myViewer) << DGtal::AddTextureImage2DWithFunctor<SliceImageAdapter, ColorMapFunctor, Z3i::Space, Z3i::KSpace>(sliceImage,
myColorMap, DGtal::Viewer3D<Z3i::Space, Z3i::KSpace>::RGBMode);
399 (*myViewer) << DGtal::UpdateImagePosition< Space, KSpace >(2, DGtal::Viewer3D<>::zDirection, imageOrigin[0],
400 imageOrigin[1], sliceNumber);
402 (*myViewer) << Viewer3D<>::updateDisplay;
404 (*myViewer) << DGtal::UpdateImageData< SliceImageAdapter,ColorMapFunctor > (2, sliceImage, 0,0, 0, 0, DGtal::Viewer3D<>::zDirection,
406 (*myViewer) << DGtal::UpdateImagePosition< Space, KSpace >(2, DGtal::Viewer3D<>::zDirection, imageOrigin[0],
407 imageOrigin[1], sliceNumber);
408 (*myViewer).updateList(init);
409 (*myViewer).update();
417 int main(
int argc,
char** argv )
420 po::options_description general_opt(
"Allowed options are: ");
421 general_opt.add_options()
422 (
"help,h",
"display this message")
423 (
"input,i", po::value<std::string>(),
"vol file (.vol) , pgm3d (.p3d or .pgm3d, pgm (with 3 dims)) file or sdp (sequence of discrete points)" )
424 (
"hueColorMap",
"use hue color map to display images." )
425 (
"gradHotColorMap",
"use hot gradient color map to display images." )
426 (
"gradCoolColorMap",
"use cool gradient color map to display images." )
429 (
"dicomMin", po::value<int>()->default_value(-1000),
"set minimum density threshold on Hounsfield scale")
430 (
"dicomMax", po::value<int>()->default_value(3000),
"set maximum density threshold on Hounsfield scale")
435 po::variables_map vm;
437 po::store(po::parse_command_line(argc, argv, general_opt), vm);
438 }
catch(
const std::exception& ex){
440 trace.info()<<
"Error checking program options: "<< ex.what()<< endl;
443 if( !parseOK || vm.count(
"help")||argc<=1)
445 std::cout <<
"Usage: " << argv[0] <<
" [input]\n" 446 <<
"Displays volume file with slice image by using QT and QGLviewer"<< endl
447 << general_opt <<
"\n";
451 if(! vm.count(
"input"))
453 trace.error() <<
" The file name was defined" << endl;
456 string inputFilename = vm[
"input"].as<std::string>();
459 typedef ImageContainerBySTLVector < Z3i::Domain, unsigned char >
Image3D;
460 typedef ImageContainerBySTLVector < Z2i::Domain, unsigned char >
Image2D;
462 string extension = inputFilename.substr(inputFilename.find_last_of(
".") + 1);
463 if(extension!=
"vol" && extension !=
"p3d" && extension !=
"pgm3D" && extension !=
"pgm3d" && extension !=
"sdp" && extension !=
"pgm" 468 trace.info() <<
"File extension not recognized: "<< extension << std::endl;
472 if(extension==
"vol" || extension==
"pgm3d" || extension==
"pgm3D" 479 int dicomMin = vm[
"dicomMin"].as<
int>();
480 int dicomMax = vm[
"dicomMax"].as<
int>();
481 typedef functors::Rescaling<int ,unsigned char > RescalFCT;
482 Image3D image = extension ==
"dcm" ? DicomReader< Image3D, RescalFCT >::importDicom( inputFilename,
486 GenericReader<Image3D>::import( inputFilename );
487 trace.info() <<
"Imported ITK..."<< std::endl;
489 Image3D image = GenericReader<Image3D>::import (inputFilename );
490 trace.info() <<
"Imported..."<< std::endl;
495 QApplication application(argc,argv);
496 Viewer3D<> *viewer =
new Viewer3D<>();
497 bool usehm = vm.count(
"hueColorMap");
498 bool usegh = vm.count(
"gradHotColorMap");
499 bool usegc = vm.count(
"gradCoolColorMap");
505 w.setWindowTitle ( QString(
"sliceViewer"));
510 Z3i::Point size = image.domain().upperBound() - image.domain().lowerBound();
511 Z3i::Point center = image.domain().lowerBound()+size/2;
512 unsigned int maxDist = std::max(std::max(size[2], size[1]), size[2]);
513 viewer->camera()->setPosition(qglviewer::Vec(center[0],center[1],
514 center[2] + 2.0*maxDist));
515 viewer->camera()->setSceneCenter(qglviewer::Vec(center[0],center[1],center[2]));
void setScale1_1_ImageY()
void changeNormalColorMap()
MainWindow(DGtal::Viewer3D<> *viewer, DGtal::ImageContainerBySTLVector< DGtal::Z3i::Domain, unsigned char > *myImage3D, const ColorMapFunctor &aFunctor, QWidget *parent=0, Qt::WindowFlags flags=0)
void updateSliceImageZ(int sliceNumber, bool init)
void updateSliceImageX(int sliceNumber, bool init)
DGtal::ConstImageAdapter< Image3D, Image2D::Domain, DGtal::functors::Projector< DGtal::Z3i::Space >, Image3D::Value, DGtal::functors::Identity > SliceImageAdapter
DGtal::ImageContainerBySTLVector< DGtal::Z2i::Domain, unsigned char > Image2D
void changeCoolColorMap()
ColorMapFunctor myColorMap
void setScale1_1_ImageZ()
void updateSliceImageY(int sliceNumber, bool init)
void setImageProjY(const QPixmap &aPixMap)
void setImageProjZ(const QPixmap &aPixMap)
void updateAllDisplayedImages()
void setScale1_1_ImageX()
DGtal::ImageContainerBySTLVector< DGtal::Z3i::Domain, unsigned char > Image3D
void setImageProjX(const QPixmap &aPixMap)