8 #include "gVariables.hh" 10 #include "sOutputManager.hh" 11 #include "sScannerManager.hh" 12 #include "oInterfileIO.hh" 31 cout <<
"Usage: castor-sumImages -img image1.hdr -img image2.hdr -(f/d)out output [settings]" << endl;
33 cout <<
"This program can be used to perform operations on a bunch of images of the same dimensions." << endl;
34 cout <<
"The sum or average image can be computed." << endl;
35 cout <<
"The variance or standard-deviation image can be computed (the biased one, i.e. divided by the number of images and not minus one)." << endl;
36 cout <<
"If a reference image is provided, the bias as well as the root mean square error images can also be computed." << endl;
37 cout <<
"All operations are performed independently voxel by voxel." << endl;
38 cout <<
"Important note: this program only works with 3D images (without time dimension)." << endl;
40 cout <<
"[Mandatory parameters]:" << endl;
41 cout <<
" -img imageX.hdr : Give an image (must give at least two images)" << endl;
42 cout <<
" -fout name : Give the root name for all output files (no default, alternative to -dout)" << endl;
43 cout <<
" -dout name : Give the name of the output directory where all output files will be written (no default, alternative to -fout)" << endl;
45 cout <<
"[Options]:" << endl;
46 cout <<
" -sum : Compute the sum image" << endl;
47 cout <<
" -avg : Compute the average image" << endl;
48 cout <<
" -var : Compute the variance image" << endl;
49 cout <<
" -stdv : Compute the standard-deviation image" << endl;
50 cout <<
" -ref imageRef.hdr : Provide a reference image (needed for bias and rmse options)" << endl;
51 cout <<
" -bias : Compute the bias image with respect to the provided reference image" << endl;
52 cout <<
" -mse : Compute the mean square error image with respect to the provided reference image" << endl;
53 cout <<
" -rmse : Compute the root mean square error image with respect to the provided reference image" << endl;
54 cout <<
" -norm : Compute normalized values:" << endl;
55 cout <<
" - with respect to the average for the standard-deviation" << endl;
56 cout <<
" - with respect to the reference for the bias and root mean square error" << endl;
57 cout <<
" - other computations are left unchanged" << endl;
58 cout <<
" -vb value : Give the verbosity level, from 0 (no verbose) to 2 (default: 1)" << endl;
59 cout <<
" --help,-h,-help : Print out this help page." << endl;
62 cout <<
" Compiled with OpenMP (will use as many cores as available)" << endl;
65 cout <<
" Build date: " << BUILD_DATE << endl;
69 cout <<
" This program is part of the CASToR release version " <<
CASTOR_VERSION <<
"." << endl;
82 int main(
int argc,
char** argv)
90 MPI_Init(&argc, &argv);
91 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
92 MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
93 if (mpi_rank!=0)
return 0;
112 uint32_t nb_images = 0;
114 vector<string> path_to_image_filename;
116 string path_to_reference_image_filename =
"";
123 string path_dout =
"";
125 string path_fout =
"";
132 bool flag_sum =
false;
134 bool flag_mean =
false;
136 bool flag_stdv =
false;
138 bool flag_var =
false;
140 bool flag_bias =
false;
142 bool flag_mse =
false;
144 bool flag_rmse =
false;
146 bool flag_norm =
false;
155 for (
int i=1; i<argc; i++)
158 string option = (string)argv[i];
165 if (option==
"-h" || option==
"--help" || option==
"-help")
171 else if (option==
"-vb")
175 Cerr(
"***** castor-sumImages() -> Argument missing for option: " << option << endl);
180 Cerr(
"***** castor-sumImages() -> Exception when trying to read provided verbosity level '" << verbose <<
" for option: " << option << endl);
186 else if (option==
"-sum") flag_sum =
true;
188 else if (option==
"-avg") flag_mean =
true;
190 else if (option==
"-var") flag_var =
true;
192 else if (option==
"-stdv") flag_stdv =
true;
194 else if (option==
"-bias") flag_bias =
true;
196 else if (option==
"-mse") flag_mse =
true;
198 else if (option==
"-rmse") flag_rmse =
true;
200 else if (option==
"-norm") flag_norm =
true;
207 else if (option==
"-img")
211 Cerr(
"***** castor-sumImages() -> Argument missing for option: " << option << endl);
214 string file_name = (string)argv[i+1];
215 path_to_image_filename.push_back(file_name);
220 else if (option==
"-ref")
224 Cerr(
"***** castor-sumImages() -> Argument missing for option: " << option << endl);
227 path_to_reference_image_filename = (string)argv[i+1];
236 else if (option==
"-dout")
240 Cerr(
"***** castor-sumImages() -> Argument missing for option: " << option << endl);
243 path_dout = argv[i+1];
247 else if (option==
"-fout")
251 Cerr(
"***** castor-sumImages() -> Argument missing for option: " << option << endl);
254 path_fout = argv[i+1];
264 Cerr(
"***** castor-sumImages() -> Unknown option '" << option <<
"' !" << endl);
276 Cerr(
"***** castor-sumImages() -> Please provide at least two image filenames !" << endl);
280 if (path_fout.empty() && path_dout.empty())
282 Cerr(
"***** castor-sumImages() -> Please provide an output option for output files (-fout or -dout) !" << endl);
286 if (!path_fout.empty() && !path_dout.empty())
288 Cerr(
"***** castor-sumImages() -> Please provide either output option -fout or -dout but not both !" << endl);
292 if (path_to_reference_image_filename==
"" && (flag_bias || flag_rmse || flag_mse))
294 Cerr(
"***** castor-sumImages() -> Please provide a reference image for bias or (root) mean square error computation !" << endl);
303 omp_set_num_threads(omp_get_max_threads());
317 Cerr(
"***** castor-sumImages() -> A problem occurred while initializing output directory !" << endl);
323 Cerr(
"***** castor-sumImages() -> A problem occurred while logging command line arguments !" << endl);
332 if (verbose>=
VERBOSE_LIGHT)
Cout(
"castor-sumImages() -> Load input images" << endl);
342 for (uint32_t img=0; img<nb_images; img++)
349 if (p_images[img]==NULL)
351 Cerr(
"***** castor-sumImages() -> A problem occurred while reading image number " << img+1 <<
" !" << endl);
357 for (uint32_t img=1; img<nb_images; img++)
361 Cerr(
"***** castor-sumImages() -> Inconsistency between image dimensions !" << endl);
369 Cout(
" --> Image dimensions: [ " << p_image_fields[0]->mtx_size[0] <<
" : " 370 << p_image_fields[0]->mtx_size[1] <<
" : " 371 << p_image_fields[0]->mtx_size[2] <<
" ]" << endl);
372 Cout(
" --> Voxel sizes: [ " << p_image_fields[0]->vox_size[0] <<
" : " 373 << p_image_fields[0]->vox_size[1] <<
" : " 374 << p_image_fields[0]->vox_size[2] <<
" ]" << endl);
378 uint32_t dim_x = p_image_fields[0]->
mtx_size[0];
379 uint32_t dim_y = p_image_fields[0]->
mtx_size[1];
380 uint32_t dim_z = p_image_fields[0]->
mtx_size[2];
381 uint32_t dim_xyz = dim_x * dim_y * dim_z;
388 FLTNB* p_reference = NULL;
391 if (path_to_reference_image_filename!=
"")
394 if (verbose>=1)
Cout(
"castor-sumImages() -> Load reference image" << endl);
400 if (p_reference==NULL)
402 Cerr(
"***** castor-sumImages() -> A problem occurred while reading reference image !" << endl);
408 Cerr(
"***** castor-sumImages() -> Inconsistency between input images and reference image !" << endl);
418 FLTNB* p_mean = NULL;
419 FLTNB* p_misc = NULL;
422 if (flag_sum || flag_mean || flag_bias || flag_stdv || flag_var)
423 p_mean = (
FLTNB*)malloc(dim_xyz*
sizeof(
FLTNB));
426 if (flag_bias || flag_mse || flag_rmse || flag_stdv || flag_var)
427 p_misc = (
FLTNB*)malloc(dim_xyz*
sizeof(
FLTNB));
434 if (flag_sum || flag_mean || flag_bias || flag_stdv || flag_var)
437 if (verbose>=1)
Cout(
"castor-sumImages() -> Compute sum/average image" << endl);
439 for (uint32_t v=0; v<dim_xyz; v++) p_mean[v] = 0.;
442 #pragma omp parallel for private(v) schedule(guided) 443 for (v=0; v<dim_xyz; v++)
448 for (uint32_t img=0; img<nb_images; img++)
451 sum += ((
HPFLTNB)(p_images[img][v]));
460 if (verbose>=1)
Cout(
"castor-sumImages() -> Write sum image" << endl);
466 Cerr(
"***** castor-sumImages() -> A problem occurred while writing sum image !" << endl);
471 #pragma omp parallel for private(v) schedule(guided) 472 for (v=0; v<dim_xyz; v++)
474 p_mean[v] /= ((
FLTNB)nb_images);
480 if (verbose>=1)
Cout(
"castor-sumImages() -> Write average image" << endl);
486 Cerr(
"***** castor-sumImages() -> A problem occurred while writing average image !" << endl);
496 if (flag_var || flag_stdv)
499 if (verbose>=1)
Cout(
"castor-sumImages() -> Compute variance image" << endl);
501 for (uint32_t v=0; v<dim_xyz; v++) p_misc[v] = 0.;
504 #pragma omp parallel for private(v) schedule(guided) 505 for (v=0; v<dim_xyz; v++)
510 for (uint32_t img=0; img<nb_images; img++)
514 sum_square += diff * diff;
517 p_misc[v] = (sum_square / ((
HPFLTNB)nb_images));
523 if (verbose>=1)
Cout(
"castor-sumImages() -> Write variance image" << endl);
529 Cerr(
"***** castor-sumImages() -> A problem occurred while writing variance image !" << endl);
539 if (flag_norm)
Cout(
"castor-sumImages() -> Compute normalized standard-deviation image" << endl);
540 else Cout(
"castor-sumImages() -> Compute standard-deviation image" << endl);
543 #pragma omp parallel for private(v) schedule(guided) 544 for (v=0; v<dim_xyz; v++)
547 p_misc[v] = sqrt(p_misc[v]);
549 if (flag_norm) p_misc[v] /= p_mean[v];
552 if (verbose>=1)
Cout(
"castor-sumImages() -> Write standard deviation image" << endl);
558 Cerr(
"***** castor-sumImages() -> A problem occurred while writing standard deviation image !" << endl);
573 if (flag_norm)
Cout(
"castor-sumImages() -> Compute normalized bias image" << endl);
574 else Cout(
"castor-sumImages() -> Compute bias image" << endl);
577 for (uint32_t v=0; v<dim_xyz; v++) p_misc[v] = 0.;
580 #pragma omp parallel for private(v) schedule(guided) 581 for (v=0; v<dim_xyz; v++)
584 p_misc[v] = p_mean[v] - p_reference[v];
586 if (flag_norm) p_misc[v] /= p_reference[v];
589 if (verbose>=1)
Cout(
"castor-sumImages() -> Write bias image" << endl);
595 Cerr(
"***** castor-sumImages() -> A problem occurred while writing bias image !" << endl);
604 if (flag_rmse || flag_mse)
607 if (verbose>=1)
Cout(
"castor-sumImages() -> Compute mean square error image" << endl);
609 for (uint32_t v=0; v<dim_xyz; v++) p_misc[v] = 0.;
612 #pragma omp parallel for private(v) schedule(guided) 613 for (v=0; v<dim_xyz; v++)
618 for (uint32_t img=0; img<nb_images; img++)
622 sum_square += diff * diff;
625 p_misc[v] = (sum_square / ((
HPFLTNB)nb_images));
631 if (verbose>=1)
Cout(
"castor-sumImages() -> Write mean square error image" << endl);
637 Cerr(
"***** castor-sumImages() -> A problem occurred while writing mean square error image !" << endl);
647 if (flag_norm)
Cout(
"castor-sumImages() -> Compute normalized root mean square error image" << endl);
648 else Cout(
"castor-sumImages() -> Compute root mean square error image" << endl);
651 #pragma omp parallel for private(v) schedule(guided) 652 for (v=0; v<dim_xyz; v++)
655 p_misc[v] = sqrt(p_misc[v]);
657 if (flag_norm) p_misc[v] /= p_reference[v];
660 if (verbose>=1)
Cout(
"castor-sumImages() -> Write root mean square error image" << endl);
666 Cerr(
"***** castor-sumImages() -> A problem occurred while writing root mean square error image !" << endl);
679 for (uint32_t img=0; img<nb_images; img++)
if (p_images[img]) free(p_images[img]);
683 if (p_reference) free(p_reference);
685 if (p_mean) free(p_mean);
687 if (p_misc) free(p_misc);
void SetVerbose(int a_verbose)
static sOutputManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
int LogCommandLine(int argc, char **argv)
const string & GetPathName()
int IntfWriteImageFromIntfFields(const string &a_pathToImg, FLTNB *ap_ImgMatrix, Intf_fields Img_fields, int vb)
Singleton class that manages output writing on disk (images, sinograms, etc). It also manages loggi...
int IntfCheckDimensionsConsistency(Intf_fields ImgFields1, Intf_fields ImgFields2)
void SetMPIRank(int a_mpiRank)
const string & GetBaseName()
Interfile fields. This structure contains all the Interfile keys currently managed by CASToR Decl...
void GetUserEndianness()
Check user/host computer endianness and write it to the global variable User_Endianness.
FLTNB * IntfLoadImageFromScratch(const string &a_pathToHeaderFile, Intf_fields *ap_ImgFields, int vb)
int InitOutputDirectory(const string &a_pathFout, const string &a_pathDout)
int ConvertFromString(const string &a_str, string *a_result)
Copy the 'a_str' string in the position pointed by 'a_result'.