32 #include "DGtal/base/Common.h"
33 #include "DGtal/base/BasicFunctors.h"
34 #include "DGtal/helpers/StdDefs.h"
35 #include "DGtal/io/readers/GenericReader.h"
37 #include "DGtal/io/readers/DicomReader.h"
39 #include "DGtal/io/viewers/Viewer3D.h"
40 #include "DGtal/io/DrawWithDisplay3DModifier.h"
41 #include "DGtal/io/readers/PointListReader.h"
42 #include "DGtal/io/readers/MeshReader.h"
44 #include "DGtal/io/Color.h"
45 #include "DGtal/io/colormaps/GradientColorMap.h"
46 #include "DGtal/images/ImageSelector.h"
48 #include <boost/program_options/options_description.hpp>
49 #include <boost/program_options/parsers.hpp>
50 #include <boost/program_options/variables_map.hpp>
53 using namespace DGtal;
110 template <
typename Space = DGtal::Z3i::Space,
typename KSpace = DGtal::Z3i::KSpace>
111 struct ViewerSnap: DGtal::Viewer3D <Space, KSpace>
114 ViewerSnap(
bool saveSnap): Viewer3D<Space, KSpace>(), mySaveSnap(saveSnap){
119 DGtal::Viewer3D<>::init();
121 QObject::connect(
this, SIGNAL(drawFinished(
bool)),
this, SLOT(saveSnapshot(
bool)));
129 namespace po = boost::program_options;
131 int main(
int argc,
char** argv )
134 po::options_description general_opt(
"Allowed options are: ");
135 general_opt.add_options()
136 (
"help,h",
"display this message")
137 (
"input,i", po::value<std::string>(),
"vol file (.vol) , pgm3d (.p3d or .pgm3d, pgm (with 3 dims)) file or sdp (sequence of discrete points)" )
138 (
"thresholdMin,m", po::value<int>()->default_value(0),
"threshold min to define binary shape" )
139 (
"thresholdMax,M", po::value<int>()->default_value(255),
"threshold max to define binary shape" )
140 (
"numMaxVoxel,n", po::value<int>()->default_value(500000),
"set the maximal voxel number to be displayed." )
141 (
"displayMesh", po::value<std::string>(),
"display a Mesh given in OFF or OFS format. " )
142 (
"colorMesh", po::value<std::vector <int> >()->multitoken(),
"set the color of Mesh (given from displayMesh option) : r g b a " )
143 (
"doSnapShotAndExit,d", po::value<std::string>(),
"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." )
145 (
"dicomMin", po::value<int>()->default_value(-1000),
"set minimum density threshold on Hounsfield scale")
146 (
"dicomMax", po::value<int>()->default_value(3000),
"set maximum density threshold on Hounsfield scale")
148 (
"transparency,t", po::value<uint>()->default_value(255),
"transparency") ;
151 po::variables_map vm;
153 po::store(po::parse_command_line(argc, argv, general_opt), vm);
154 }
catch(
const std::exception& ex){
156 trace.info()<<
"Error checking program options: "<< ex.what()<< endl;
159 if( !parseOK || vm.count(
"help")||argc<=1)
161 std::cout <<
"Usage: " << argv[0] <<
" [input]\n"
162 <<
"Display volume file as a voxel set by using QGLviewer"<< endl
163 << general_opt <<
"\n"
164 <<
"Example: "<< std::endl
165 <<
" \t 3dVolViewer -i $DGtal/examples/samples/lobster.vol -m 60 -t 10" << endl;
169 if(! vm.count(
"input"))
171 trace.error() <<
" The file name was defined" << endl;
174 string inputFilename = vm[
"input"].as<std::string>();
175 int thresholdMin = vm[
"thresholdMin"].as<
int>();
176 int thresholdMax = vm[
"thresholdMax"].as<
int>();
177 unsigned char transp = vm[
"transparency"].as<uint>();
179 bool limitDisplay=
false;
180 if(vm.count(
"numMaxVoxel")){
183 unsigned int numDisplayedMax = vm[
"numMaxVoxel"].as<
int>();
186 QApplication application(argc,argv);
187 typedef ViewerSnap<> Viewer;
189 Viewer viewer(vm.count(
"doSnapShotAndExit"));
190 if(vm.count(
"doSnapShotAndExit")){
191 viewer.setSnapshotFileName(QString(vm[
"doSnapShotAndExit"].as<std::string>().c_str()));
194 viewer.setWindowTitle(
"simple Volume Viewer");
197 typedef ImageSelector<Domain, unsigned char>::Type Image;
198 string extension = inputFilename.substr(inputFilename.find_last_of(
".") + 1);
199 if(extension!=
"vol" && extension !=
"p3d" && extension !=
"pgm3D" && extension !=
"pgm3d" && extension !=
"sdp" && extension !=
"pgm"
204 trace.info() <<
"File extension not recognized: "<< extension << std::endl;
208 if(extension==
"vol" || extension==
"pgm3d" || extension==
"pgm3D"
213 unsigned int numDisplayed=0;
216 int dicomMin = vm[
"dicomMin"].as<
int>();
217 int dicomMax = vm[
"dicomMax"].as<
int>();
218 typedef DGtal::functors::Rescaling<int ,unsigned char > RescalFCT;
219 Image image = extension ==
"dcm" ? DicomReader< Image, RescalFCT >::importDicom( inputFilename,
223 GenericReader<Image>::import( inputFilename );
225 Image image = GenericReader<Image>::import (inputFilename );
228 trace.info() <<
"Image loaded: "<<image<< std::endl;
229 Domain domain = image.domain();
230 GradientColorMap<long> gradient( thresholdMin, thresholdMax);
231 gradient.addColor(Color::Blue);
232 gradient.addColor(Color::Green);
233 gradient.addColor(Color::Yellow);
234 gradient.addColor(Color::Red);
235 for(Domain::ConstIterator it = domain.begin(), itend=domain.end(); it!=itend; ++it){
236 unsigned char val= image( (*it) );
237 if(limitDisplay && numDisplayed > numDisplayedMax)
239 Color c= gradient(val);
240 if(val<=thresholdMax && val >=thresholdMin){
241 viewer << CustomColors3D(Color((
float)(c.red()), (
float)(c.green()),(
float)(c.blue()), transp),
242 Color((
float)(c.red()), (
float)(c.green()),(
float)(c.blue()), transp));
247 }
else if(extension==
"sdp"){
248 vector<Z3i::RealPoint> vectVoxels = PointListReader<Z3i::RealPoint>::getPointsFromFile(inputFilename);
249 for(
unsigned int i=0;i< vectVoxels.size(); i++){
250 viewer << vectVoxels.at(i);
253 if(vm.count(
"displayMesh")){
254 if(vm.count(
"colorMesh")){
255 std::vector<int> vcol= vm[
"colorMesh"].as<std::vector<int > >();
257 trace.error() <<
"Not enough parameter: color specification should contains four elements: red, green, blue and alpha values." << std::endl;
260 Color c(vcol[0], vcol[1], vcol[2], vcol[3]);
261 viewer.setFillColor(c);
264 DGtal::Mesh<Z3i::RealPoint> aMesh(!vm.count(
"colorMesh"));
265 MeshReader<Z3i::RealPoint>::importOFFFile(vm[
"displayMesh"].as<std::string>(), aMesh);
269 viewer << Viewer3D<>::updateDisplay;
270 if(vm.count(
"doSnapShotAndExit")){
272 if(!viewer.restoreStateFromFile())
276 std::string name = vm[
"doSnapShotAndExit"].as<std::string>();
277 std::string extension = name.substr(name.find_last_of(
".") + 1);
278 std::string basename = name.substr(0, name.find_last_of(
"."));
279 for(
int i=0; i< viewer.snapshotCounter()-1; i++){
281 s << basename <<
"-"<< setfill(
'0') << setw(4)<< i <<
"." << extension;
282 trace.info() <<
"erase temp file: " << s.str() << std::endl;
283 remove(s.str().c_str());
286 s << basename <<
"-"<< setfill(
'0') << setw(4)<< viewer.snapshotCounter()-1 <<
"." << extension;
287 rename(s.str().c_str(), name.c_str());
291 return application.exec();