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"
39 #include "DGtal/io/Color.h"
40 #include "DGtal/io/colormaps/GradientColorMap.h"
41 #include "DGtal/images/ImageSelector.h"
46 using namespace DGtal;
103 template <
typename Space = DGtal::Z3i::Space,
typename KSpace = DGtal::Z3i::KSpace>
104 struct ViewerSnap: DGtal::Viewer3D <Space, KSpace>
107 ViewerSnap(
bool saveSnap): Viewer3D<Space, KSpace>(), mySaveSnap(saveSnap){
112 DGtal::Viewer3D<>::init();
114 QObject::connect(
this, SIGNAL(drawFinished(
bool)),
this, SLOT(saveSnapshot(
bool)));
120 typedef ViewerSnap<> Viewer;
125 template<
typename TImage>
127 displayCoordsCallBack(
void* viewer,
int name,
void* data )
129 TImage *image = (TImage *) data;
130 std::stringstream ss;
131 Z3i::Point p = DGtal::Linearizer<typename TImage::Domain>::getPoint(name, image->domain());
133 if (image->domain().isInside(p)){
134 ss <<
"Selected intensity: " << (*image)(p) <<
"p " << p[0] <<
" "<< p[1] <<
" " << p[2] ;
135 ((Viewer *) viewer)->displayMessage(QString(ss.str().c_str()), 100000);
141 template <
typename TImage>
143 processDisplay(ViewerSnap<> &viewer, TImage &image,
144 const typename TImage::Value &thresholdMin,
145 const typename TImage::Value &thresholdMax,
146 unsigned int numDisplayedMax,
147 unsigned int transparency,
148 bool interDisplay=
false)
150 Domain domain = image.domain();
151 GradientColorMap<typename TImage::Value> gradient( thresholdMin, thresholdMax);
152 unsigned int numDisplayed = 0;
153 gradient.addColor(Color::Blue);
154 gradient.addColor(Color::Green);
155 gradient.addColor(Color::Yellow);
156 gradient.addColor(Color::Red);
157 for(Domain::ConstIterator it = domain.begin(), itend=domain.end(); it!=itend; ++it){
158 typename TImage::Value val= image( (*it) );
159 if(numDisplayed > numDisplayedMax)
161 Color c= gradient(val);
162 if(val<=thresholdMax && val >=thresholdMin)
164 viewer << CustomColors3D(Color((
float)(c.red()), (
float)(c.green()),(
float)(c.blue()), transparency),
165 Color((
float)(c.red()), (
float)(c.green()),(
float)(c.blue()), transparency));
169 auto index = DGtal::Linearizer<typename TImage::Domain>::getIndex( p, domain);
170 viewer << SetName3D( index ) ;
177 viewer << SetSelectCallback3D(displayCoordsCallBack<TImage>,
185 int main(
int argc,
char** argv )
189 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");
190 std::string inputFileName;
191 DGtal::int64_t rescaleInputMin {0};
192 DGtal::int64_t rescaleInputMax {255};
193 double thresholdMin {0};
194 double thresholdMax {255};
195 unsigned int transparency {255};
196 unsigned int numDisplayedMax {500000};
197 std::string displayMesh;
198 std::string snapShotFile;
199 std::vector<unsigned int> colorMesh;
200 string inputType {
""};
201 bool interactiveDisplayVoxCoords {
false};
203 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." )
205 ->check(CLI::ExistingFile);
207 app.add_option(
"--inputType", inputType,
"to specify the input image type (int or double).")
208 -> check(CLI::IsMember({
"int",
"double"}));
210 app.add_option(
"--thresholdMin,-m", thresholdMin,
"threshold min (excluded) to define binary shape.",
true);
211 app.add_option(
"--thresholdMax,-M", thresholdMax,
"threshold max (included) to define binary shape.",
true);
212 app.add_option(
"--rescaleInputMin", rescaleInputMin,
"min value used to rescale the input intensity (to avoid basic cast into 8 bits image).",
true);
213 app.add_option(
"--rescaleInputMax", rescaleInputMax,
"max value used to rescale the input intensity (to avoid basic cast into 8 bits image).",
true);
214 app.add_option(
"--numMaxVoxel,-n", numDisplayedMax,
"set the maximal voxel number to be displayed.");
215 app.add_option(
"--displayMesh", displayMesh,
"display a Mesh given in OFF or OFS format.");
216 app.add_option(
"--colorMesh", colorMesh,
"set the color of Mesh (given from displayMesh option) : r g b a ")
218 app.add_flag(
"--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." );
219 app.add_option(
"--transparency,-t", transparency,
"change the defaukt transparency",
true);
220 app.add_flag(
"--interactiveDisplayVoxCoords,-c", interactiveDisplayVoxCoords,
" by using this option the coordinates can be displayed after selection (shift+left click on voxel).");
221 app.get_formatter()->column_width(40);
222 CLI11_PARSE(app, argc, argv);
225 QApplication application(argc,argv);
227 Viewer viewer(snapShotFile !=
"");
228 if(snapShotFile !=
""){
229 viewer.setSnapshotFileName(QString(snapShotFile.c_str()));
231 viewer.setWindowTitle(
"simple Volume Viewer");
233 typedef ImageContainerBySTLVector < Z3i::Domain, double > Image3D_D;
234 typedef ImageContainerBySTLVector < Z3i::Domain, int > Image3D_I;
235 typedef ImageSelector<Domain, unsigned char>::Type Image;
237 string extension = inputFileName.substr(inputFileName.find_last_of(
".") + 1);
239 std::vector<double> vectValD;
240 std::vector<int> vectValI;
241 std::vector<unsigned char> vectValUC;
245 Image3D_D imageD = Image3D_D(d);
246 Image3D_I imageI = Image3D_I(d);
247 Image image = Image(d);
249 if(extension !=
"sdp")
251 unsigned int numDisplayed=0;
254 if (inputType==
"double")
256 imageD = DGtal::GenericReader<Image3D_D>::import(inputFileName);
257 trace.info() <<
"[done]"<< std::endl;
258 trace.info() <<
"Image loaded: D "<<imageD<< std::endl;
259 processDisplay(viewer, imageD, thresholdMin, thresholdMax, numDisplayedMax, transparency,
260 interactiveDisplayVoxCoords);
262 else if (inputType==
"int")
264 imageI= DGtal::GenericReader<Image3D_I>::import(inputFileName);
265 trace.info() <<
"Image loaded: "<<image<< std::endl;
266 processDisplay(viewer, imageI, (
int)thresholdMin, (
int)thresholdMax, numDisplayedMax, transparency,
267 interactiveDisplayVoxCoords);
269 typedef DGtal::functors::Rescaling<DGtal::int64_t ,unsigned char > RescalFCT;
270 image = GenericReader< Image >::importWithValueFunctor( inputFileName,RescalFCT(rescaleInputMin,
273 trace.info() <<
"Image loaded: "<<image<< std::endl;
274 processDisplay(viewer, image, thresholdMin, thresholdMax, numDisplayedMax, transparency,
275 interactiveDisplayVoxCoords);
278 typedef DGtal::functors::Rescaling<DGtal::int64_t ,unsigned char > RescalFCT;
279 image = GenericReader< Image >::importWithValueFunctor( inputFileName,RescalFCT(rescaleInputMin,
282 trace.info() <<
"Image loaded: "<<image<< std::endl;
283 processDisplay(viewer, image, thresholdMin, thresholdMax, numDisplayedMax, transparency,
284 interactiveDisplayVoxCoords);
287 else if(extension==
"sdp")
289 vector<Z3i::RealPoint> vectVoxels = PointListReader<Z3i::RealPoint>::getPointsFromFile(inputFileName);
290 for(
unsigned int i=0;i< vectVoxels.size(); i++){
291 viewer << Z3i::Point(vectVoxels.at(i), functors::Round<>());
294 if(displayMesh !=
"")
296 if(colorMesh.size() != 0)
298 Color c(colorMesh[0], colorMesh[1], colorMesh[2], colorMesh[3]);
299 viewer.setFillColor(c);
302 DGtal::Mesh<Z3i::RealPoint> aMesh(colorMesh.size() == 0);
303 MeshReader<Z3i::RealPoint>::importOFFFile(displayMesh, aMesh);
307 viewer << Viewer3D<>::updateDisplay;
308 if(snapShotFile !=
"")
311 if(!viewer.restoreStateFromFile())
315 std::string extension = snapShotFile.substr(snapShotFile.find_last_of(
".") + 1);
316 std::string basename = snapShotFile.substr(0, snapShotFile.find_last_of(
"."));
317 for(
int i=0; i< viewer.snapshotCounter()-1; i++){
319 s << basename <<
"-"<< setfill(
'0') << setw(4)<< i <<
"." << extension;
320 trace.info() <<
"erase temp file: " << s.str() << std::endl;
321 remove(s.str().c_str());
324 s << basename <<
"-"<< setfill(
'0') << setw(4)<< viewer.snapshotCounter()-1 <<
"." << extension;
325 rename(s.str().c_str(), snapShotFile.c_str());
328 return application.exec();