CASToR  3.2
Tomographic Reconstruction (PET/SPECT/CT)
src/optimizer/iPenaltyMedianRootPrior.cc
Go to the documentation of this file.
1 
8 #include "iPenaltyMedianRootPrior.hh"
9 
10 // =====================================================================
11 // ---------------------------------------------------------------------
12 // ---------------------------------------------------------------------
13 // =====================================================================
14 
16 {
17  // --------------------------
18  // Specific member parameters
19  // --------------------------
24  m_neighborhoodBoxExcludeCorners = 0; // Keep them by default
28  mp_medianValue = NULL;
29  // Derivative order is infinite
30  m_penaltyDerivativesOrder = INT_MAX;
31 }
32 
33 // =====================================================================
34 // ---------------------------------------------------------------------
35 // ---------------------------------------------------------------------
36 // =====================================================================
37 
39 {
40  // Destroy mp_neighborhoodNbVoxels
42  {
44  }
45  // Destroy m2p_neighborhoodIndices
47  {
49  {
51  }
53  }
54  // Destroy m2p_neighborhoodKernel
56  {
57  for (INTNB v=0; v<m_neighborhoodMaxNbVoxels; v++)
58  {
60  }
62  }
63  // Destroy mp_medianValue
64  if (mp_medianValue) free(mp_medianValue);
65 }
66 
67 // =====================================================================
68 // ---------------------------------------------------------------------
69 // ---------------------------------------------------------------------
70 // =====================================================================
71 
73 {
74  cout << "The Median Root Prior (MRP) is implemented for several types of neighborhood. The parameters are described below, and a" << endl;
75  cout << "template configuration file for parameters selection can be found in the configuration folder (config/optimizer/MRP.conf)." << endl;
76  cout << "The configuration of this penalty can only be done through a configuration file. It is not possible to parameterize it" << endl;
77  cout << "directly from the command line. The current implementation is the simplest one, based on the following reference:" << endl;
78  cout << "S. Alenius and U Ruotsalainen, \"Bayesian image reconstruction for emission tomography based on the median root prior\"," << endl;
79  cout << "European Journal of Nuclear Medicine, vol. 24, pp. 258-265, 1997." << endl;
80  cout << "------------" << endl;
81  cout << "Neighborhood" << endl;
82  cout << "------------" << endl;
83  cout << "The neighborhood is set by the 'neighborhood shape' keyword and can be described using one of the following setting:" << endl;
84  cout << "[6-nearest]: Consider the 6 nearest neighbors, i.e. 2 along each dimension. In 2D, only 4 in the plane are used." << endl;
85  cout << "[box]: Consider all voxels included in a box centered on the voxel of interest. The size of the box is parameterized" << endl;
86  cout << " using the 'box neighborhood order' keyword. The side of the box is equal to '2*order+1'. The 8 corner voxels" << endl;
87  cout << " can also be excluded from the neighborhood by setting the 'exclude box neighborhood corners' keyword to 1." << endl;
88  cout << "[sphere]: Consider all voxels whose center is included in a sphere centered on the voxel of interest and of radius" << endl;
89  cout << " provided by the 'sphere neighborhood radius (mm)' keyword." << endl;
90 }
91 
92 // =====================================================================
93 // ---------------------------------------------------------------------
94 // ---------------------------------------------------------------------
95 // =====================================================================
96 
97 int iPenaltyMedianRootPrior::ReadConfigurationFile(const string& a_configurationFile)
98 {
99  string buffer = "";
100  string key_word = "";
101 
102  // -------------------------------------------------------------------
103  // Read the type of neighborhood
104  // -------------------------------------------------------------------
105  key_word = "neighborhood shape";
106  if (ReadDataASCIIFile(a_configurationFile, key_word, &buffer, 1, KEYWORD_MANDATORY))
107  {
108  Cerr("***** iPenaltyMedianRootPrior::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
109  return 1;
110  }
111  // Sphere neighborhood
112  if (buffer == "sphere")
113  {
115  // Radius of the sphere
116  key_word = "sphere neighborhood radius (mm)";
117  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_neighborhoodSphereRadius, 1, KEYWORD_MANDATORY))
118  {
119  Cerr("***** iPenaltyMedianRootPrior::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
120  return 1;
121  }
122  }
123  // Box neighborhood
124  else if (buffer == "box")
125  {
127  // Order of the box (number of voxels which will be included in each direction)
128  key_word = "box neighborhood order";
129  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_neighborhoodBoxOrder, 1, KEYWORD_MANDATORY))
130  {
131  Cerr("***** iPenaltyMedianRootPrior::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
132  return 1;
133  }
134  // Include corners of the box or not (some people do that) (not mandatory as we keep them by default)
135  key_word = "exclude box neighborhood corners";
137  {
138  Cerr("***** iPenaltyMedianRootPrior::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
139  return 1;
140  }
141  }
142  // 6-nearest
143  else if (buffer == "6-nearest")
144  {
146  }
147  // Unknown
148  else
149  {
150  Cerr("***** iPenaltyMedianRootPrior::ReadConfigurationFile() -> Unknown neighborhood type '" << buffer << "' !" << endl);
151  return 1;
152  }
153 
154  // Normal end
155  return 0;
156 }
157 
158 // =====================================================================
159 // ---------------------------------------------------------------------
160 // ---------------------------------------------------------------------
161 // =====================================================================
162 
163 int iPenaltyMedianRootPrior::ReadOptionsList(const string& a_optionsList)
164 {
165  // To complicated to do it that way
166  Cerr("***** iPenaltyMedianRootPrior::ReadOptionsList() -> Options can be specified only using a configuration file !" << endl);
167  return 1;
168 }
169 
170 // =====================================================================
171 // ---------------------------------------------------------------------
172 // ---------------------------------------------------------------------
173 // =====================================================================
174 
176 {
177  // Check neighborhood type
179  {
180  Cerr("***** iPenaltyMarkovRandomField::CheckSpecificParameters() -> Should provide a neighborhood type !" << endl);
181  return 1;
182  }
183  // Check some parameters of the neighborhood
185  {
186  Cerr("***** iPenaltyMarkovRandomField::CheckSpecificParameters() -> Provided radius of the sphere neighborhood (" << m_neighborhoodSphereRadius << ") is negative" << endl);
187  return 1;
188  }
190  {
191  Cerr("***** iPenaltyMarkovRandomField::CheckSpecificParameters() -> Provided order of the box neighborhood (" << m_neighborhoodBoxOrder << ") is negative" << endl);
192  return 1;
193  }
194  // Normal end
195  return 0;
196 }
197 
198 // =====================================================================
199 // ---------------------------------------------------------------------
200 // ---------------------------------------------------------------------
201 // =====================================================================
202 
204 {
205  // Build the neighborhood kernel that will be used to facilitate the computation of the neighborhood of each voxel later on
207  {
208  Cerr("***** iPenaltyMedianRootPrior::InitializeSpecific() -> Failed to build the neighborhood !" << endl);
209  return 1;
210  }
211  // Some allocations for the specific neighborhood of each voxel used during computations
215  {
216  m2p_neighborhoodIndices[th]=(INTNB*)malloc((m_neighborhoodMaxNbVoxels)*sizeof(INTNB));
217  }
218  // Allocate the table to store median values for each thread
220  // Verbose
222  {
223  Cout("iPenaltyMedianRootPrior::InitializeSpecific() -> Use the Median Root Prior" << endl);
225  {
226  // Type of neighborhood
228  {
229  Cout(" --> shape of neighborhood: sphere" << endl);
230  Cout(" --> radius of the sphere neighborhood: " << m_neighborhoodSphereRadius << " mm " << endl);
231  }
233  {
234  Cout(" --> shape of neighborhood: box" << endl);
235  Cout(" --> order of the box (number of voxels in each direction): " << m_neighborhoodBoxOrder << endl);
236  if (m_neighborhoodBoxExcludeCorners) Cout(" --> exclude corner voxels" << endl);
237  }
239  {
240  Cout(" --> shape of neighborhood: 6-nearest" << endl);
241  }
242  Cout(" --> Max number of voxels in the neighborhood: " << m_neighborhoodMaxNbVoxels << endl);
243  Cout(" --> penalty energy function derivatives order: " << m_penaltyDerivativesOrder << endl);
244  }
245  }
246  // Normal end
247  return 0;
248 }
249 
250 // =====================================================================
251 // ---------------------------------------------------------------------
252 // ---------------------------------------------------------------------
253 // =====================================================================
254 
256 {
257  // Check if the neighborhood has already been created
259  {
260  Cerr("***** iPenaltyMedianRootPrior::BuildNeighborhoodKernel() -> Neighborhood kernel has already been created !" << endl);
261  return 1;
262  }
263  // Get voxel sizes locally
267  // ========================================================================================================
268  // Note
269  // ========================================================================================================
270  // As opposed to the markov random fields in which we discard the voxel itself from its neighborhood,
271  // when computing the median in MRP, the voxel itself is included in the neighborhood.
272  // ========================================================================================================
273  // Case where the neighborhood is defined by a sphere with radius provided in mm
274  // ========================================================================================================
276  {
277  // Compute the size of the box including the sphere (minimum of 1 voxel radius)
278  INTNB radius_vox_x = max( (INTNB)1 , ((INTNB)(m_neighborhoodSphereRadius/vox_size_x)) );
279  INTNB radius_vox_y = max( (INTNB)1 , ((INTNB)(m_neighborhoodSphereRadius/vox_size_y)) );
280  INTNB radius_vox_z = max( (INTNB)1 , ((INTNB)(m_neighborhoodSphereRadius/vox_size_z)) );
281  // Particular case for 2D reconstruction
282  if (mp_ImageDimensionsAndQuantification->GetNbVoxZ()==1) radius_vox_z = 0;
283  // Precompute the maximum number of voxels in the neighborhood as the box including the sphere
284  m_neighborhoodMaxNbVoxels = (radius_vox_x*2+1) * (radius_vox_y*2+1) * (radius_vox_z*2+1);
285  // Allocate the neighborhood kernel
286  m2p_neighborhoodKernel = (INTNB**)malloc(m_neighborhoodMaxNbVoxels*sizeof(INTNB*));
287  for (INTNB v = 0; v<m_neighborhoodMaxNbVoxels; v++) m2p_neighborhoodKernel[v] = (INTNB*)malloc(3*sizeof(INTNB));
288  // Counter for the number of voxels in the neighborhood
289  INTNB nb_voxels_in_neighborhood = 0;
290  // Loop on increments of voxels indices in box neighborhood
291  for (INTNB vox_z = -radius_vox_z; vox_z<=radius_vox_z; vox_z++)
292  for (INTNB vox_y = -radius_vox_y; vox_y<=radius_vox_y; vox_y++)
293  for (INTNB vox_x = -radius_vox_x; vox_x<=radius_vox_x; vox_x++)
294  {
295  // Compute the square distance between the two voxels
296  FLTNB squareDistance = ((FLTNB)(vox_x*vox_x))*vox_size_x*vox_size_x
297  + ((FLTNB)(vox_y*vox_y))*vox_size_y*vox_size_y
298  + ((FLTNB)(vox_z*vox_z))*vox_size_z*vox_size_z;
299  // Include voxel if the distance from the central voxel is less than the radius
301  {
302  m2p_neighborhoodKernel[nb_voxels_in_neighborhood][MRF_NEIGHBOR_X] = vox_x;
303  m2p_neighborhoodKernel[nb_voxels_in_neighborhood][MRF_NEIGHBOR_Y] = vox_y;
304  m2p_neighborhoodKernel[nb_voxels_in_neighborhood][MRF_NEIGHBOR_Z] = vox_z;
305  nb_voxels_in_neighborhood++;
306  }
307  }
308  // Update the maximum number of voxels in the neighborhood by the exact value
309  m_neighborhoodMaxNbVoxels = nb_voxels_in_neighborhood;
310  m2p_neighborhoodKernel = (INTNB**)realloc(m2p_neighborhoodKernel,m_neighborhoodMaxNbVoxels*sizeof(INTNB*));
311  }
312  // ========================================================================================================
313  // Case where the neighborhood is defined by a box as described in many papers
314  // ========================================================================================================
316  {
317  // Particular case for 2D reconstruction
318  INTNB neighborhood_box_order_z = m_neighborhoodBoxOrder;
319  if (mp_ImageDimensionsAndQuantification->GetNbVoxZ()==1) neighborhood_box_order_z = 0;
320  // Maximum number of voxels in the neighborhood of a voxel with no image boundary constraints
321  m_neighborhoodMaxNbVoxels = (m_neighborhoodBoxOrder*2+1)*(m_neighborhoodBoxOrder*2+1)*(m_neighborhoodBoxOrder*2+1);
322  // Allocate the neighborhood kernel
323  m2p_neighborhoodKernel = (INTNB**)malloc(m_neighborhoodMaxNbVoxels*sizeof(INTNB*));
324  for (INTNB v = 0; v<m_neighborhoodMaxNbVoxels; v++) m2p_neighborhoodKernel[v] = (INTNB*)malloc(3*sizeof(INTNB));
325  // Counter for the number of voxels in the neighborhood
326  INTNB nb_voxels_in_neighborhood = 0;
327  // Loop on increments of voxels indices in the box neighborhood
328  for (INTNB vox_z = -neighborhood_box_order_z; vox_z<=neighborhood_box_order_z; vox_z++)
329  for (INTNB vox_y = -m_neighborhoodBoxOrder; vox_y<=m_neighborhoodBoxOrder; vox_y++)
330  for (INTNB vox_x = -m_neighborhoodBoxOrder; vox_x<=m_neighborhoodBoxOrder; vox_x++)
331  {
332  // Exclude corner voxels if requested
334  || (vox_y!=-m_neighborhoodBoxOrder && vox_y!=m_neighborhoodBoxOrder)
335  || (vox_z!=-m_neighborhoodBoxOrder && vox_z!=m_neighborhoodBoxOrder))
336  {
337  m2p_neighborhoodKernel[nb_voxels_in_neighborhood][MRF_NEIGHBOR_X] = vox_x;
338  m2p_neighborhoodKernel[nb_voxels_in_neighborhood][MRF_NEIGHBOR_Y] = vox_y;
339  m2p_neighborhoodKernel[nb_voxels_in_neighborhood][MRF_NEIGHBOR_Z] = vox_z;
340  nb_voxels_in_neighborhood++;
341  }
342  }
343  // Update the maximum number of voxels in the neighborhood by the exact value
344  m_neighborhoodMaxNbVoxels = nb_voxels_in_neighborhood;
345  m2p_neighborhoodKernel = (INTNB**)realloc(m2p_neighborhoodKernel,m_neighborhoodMaxNbVoxels*sizeof(INTNB*));
346  }
347  // ========================================================================================================
348  // Case where the neighborhood is defined simply by the 6-nearest neighbors
349  // ========================================================================================================
351  {
352  // Maximum number of voxels in the neighborhood is 6 + 1 (the voxel itself)
353  m_neighborhoodMaxNbVoxels = 7;
354  // Particular case for 2D reconstruction
355  if (mp_ImageDimensionsAndQuantification->GetNbVoxZ()==1) m_neighborhoodMaxNbVoxels = 5;
356  // Allocate the neighborhood kernel
357  m2p_neighborhoodKernel = (INTNB**)malloc(m_neighborhoodMaxNbVoxels*sizeof(INTNB*));
358  for (INTNB v = 0; v<m_neighborhoodMaxNbVoxels; v++) m2p_neighborhoodKernel[v] = (INTNB*)malloc(3*sizeof(INTNB));
359  // The 7 voxels
360  for (INTNB v=0; v<m_neighborhoodMaxNbVoxels; v++) for (INTNB dim=0; dim<3; dim++) m2p_neighborhoodKernel[v][dim] = 0;
366  {
369  }
370  }
371  // ========================================================================================================
372  // Unknown neighborhood type
373  // ========================================================================================================
374  else
375  {
376  Cerr("***** iPenaltyMedianRootPrior::BuildNeighborhoodKernel() -> The provided shape of neighborhood (" << m_neighborhoodShape << ") is unknown !" << endl);
377  return 1;
378  }
379  // Normal end
380  return 0;
381 }
382 
383 // =====================================================================
384 // ---------------------------------------------------------------------
385 // ---------------------------------------------------------------------
386 // =====================================================================
387 
389 {
390  // Get number of voxels locally for code readability
395  // Compute the X, Y and Z components of the current voxel
396  INTNB index_x = a_voxel % nb_vox_x;
397  INTNB index_y = (a_voxel/nb_vox_x) % nb_vox_y;
398  INTNB index_z = a_voxel / nb_vox_xy;
399  // Count the number of valid neighbors
400  mp_neighborhoodNbVoxels[a_th] = 0;
401  // Loop on all possible neighbors in the kernel
402  for (INTNB neigh = 0; neigh<m_neighborhoodMaxNbVoxels; neigh++)
403  {
404  // Compute X, Y and Z indices of this potential neighbor
405  INTNB neighbor_x = index_x + m2p_neighborhoodKernel[neigh][MRF_NEIGHBOR_X];
406  INTNB neighbor_y = index_y + m2p_neighborhoodKernel[neigh][MRF_NEIGHBOR_Y];
407  INTNB neighbor_z = index_z + m2p_neighborhoodKernel[neigh][MRF_NEIGHBOR_Z];
408  INTNB neighbor_xyz = neighbor_x + neighbor_y*nb_vox_x + neighbor_z*nb_vox_xy;
409  // Check if the neighbour is inside the image
410  if ( neighbor_x>=0 && neighbor_x<nb_vox_x && neighbor_y>=0 && neighbor_y<nb_vox_y && neighbor_z>=0 && neighbor_z<nb_vox_z && !mp_ImageDimensionsAndQuantification->IsVoxelMasked(neighbor_xyz) )
411  {
412  // Add the global index of this neighbor to the neighborhood list
413  m2p_neighborhoodIndices[a_th][neigh] = neighbor_xyz;
414  // One more neighbor
415  mp_neighborhoodNbVoxels[a_th]++;
416  }
417  // Otherwise, discard it by setting -1
418  else
419  {
420  m2p_neighborhoodIndices[a_th][neigh] = -1;
421  }
422  }
423  // Normal end
424  return 0;
425 }
426 
427 // =====================================================================
428 // ---------------------------------------------------------------------
429 // ---------------------------------------------------------------------
430 // =====================================================================
431 
432 int iPenaltyMedianRootPrior::LocalPreProcessingStep(int a_tbf, int a_rbf, int a_cbf, INTNB a_voxel, int a_th)
433 {
434  // First build the list of neighbours of this voxel
435  if (BuildSpecificNeighborhood(a_voxel,a_th))
436  {
437  Cerr("***** iPenaltyMedianRootPrior::LocalPreProcessingStep() -> A problem occurred while building specific neighborhood of voxel " << a_voxel << " !" << endl);
438  return 1;
439  }
440  // Compute the median value in this neighborhood
441  if (ComputeMedianInNeighborhood(a_tbf,a_rbf,a_cbf,a_voxel,a_th))
442  {
443  Cerr("***** iPenaltyMedianRootPrior::LocalPreProcessingStep() -> A problem occurred while computing the median in neighborhood of voxel " << a_voxel << " !" << endl);
444  return 1;
445  }
446  // Normal end
447  return 0;
448 }
449 
450 // =====================================================================
451 // ---------------------------------------------------------------------
452 // ---------------------------------------------------------------------
453 // =====================================================================
454 
455 int iPenaltyMedianRootPrior::ComputeMedianInNeighborhood(int a_tbf, int a_rbf, int a_cbf, INTNB a_voxel, int a_th)
456 {
457  // Sort the neighborhood indices according to increasing intensity values
458  std::sort( &(m2p_neighborhoodIndices[a_th][0]), &(m2p_neighborhoodIndices[a_th][m_neighborhoodMaxNbVoxels]),
459  [a_voxel,a_tbf,a_rbf,a_cbf,a_th,this](INTNB i1, INTNB i2)
460  {
461  // This two lines pushes the -1 indices (voxels out of image) at the end
462  if (i1 == -1) return false;
463  if (i2 == -1) return true;
464  return mp_ImageSpace->m4p_image[a_tbf][a_rbf][a_cbf][i1] < mp_ImageSpace->m4p_image[a_tbf][a_rbf][a_cbf][i2];
465  });
466  // There can be an even number of voxels if we are near the border of the image (restrained neighborhood)
467  if (mp_neighborhoodNbVoxels[a_th]%2==0)
468  {
469  // In this case, we take the mean of the tow median voxels
470  mp_medianValue[a_th] = (mp_ImageSpace->m4p_image[a_tbf][a_rbf][a_cbf][m2p_neighborhoodIndices[a_th][mp_neighborhoodNbVoxels[a_th]/2]]
471  + mp_ImageSpace->m4p_image[a_tbf][a_rbf][a_cbf][m2p_neighborhoodIndices[a_th][mp_neighborhoodNbVoxels[a_th]/2-1]])
472  * 0.5;
473  }
474  // Even number of voxels
475  else
476  {
477  // The median is in the middle
478  mp_medianValue[a_th] = mp_ImageSpace->m4p_image[a_tbf][a_rbf][a_cbf][m2p_neighborhoodIndices[a_th][mp_neighborhoodNbVoxels[a_th]/2]];
479  }
480  // Normal end
481  return 0;
482 }
483 
484 // =====================================================================
485 // ---------------------------------------------------------------------
486 // ---------------------------------------------------------------------
487 // =====================================================================
488 
490 {
491  // Compute the value of the penalty
492  FLTNB penalty = 0.;
493  if (mp_medianValue[a_th]!=0.) penalty = m_penaltyStrength * 0.5
494  * (ap_image[a_voxel]-mp_medianValue[a_th])
495  * (ap_image[a_voxel]-mp_medianValue[a_th])
496  / mp_medianValue[a_th];
497  // Return result
498  return penalty;
499 }
500 
501 // =====================================================================
502 // ---------------------------------------------------------------------
503 // ---------------------------------------------------------------------
504 // =====================================================================
505 
507 {
508  // Compute the first derivative
509  FLTNB first_derivative = 0.;
510  if (mp_medianValue[a_th]!=0.) first_derivative = m_penaltyStrength * (ap_image[a_voxel]-mp_medianValue[a_th])
511  / mp_medianValue[a_th];
512  return first_derivative;
513 }
514 
515 
516 // =====================================================================
517 // ---------------------------------------------------------------------
518 // ---------------------------------------------------------------------
519 // =====================================================================
520 
522 {
523  // Compute the second derivative of the penalty
524  FLTNB second_derivative = 0.;
525  if (mp_medianValue[a_th]!=0.) second_derivative = m_penaltyStrength / mp_medianValue[a_th];
526  // Return result
527  return second_derivative;
528 }
FLTNB GetVoxSizeX()
Get the voxel&#39;s size along the X axis, in mm.
#define Cerr(MESSAGE)
FLTNB GetVoxSizeZ()
Get the voxel&#39;s size along the Z axis, in mm.
int BuildSpecificNeighborhood(INTNB a_voxel, int a_th)
FLTNB ComputePenaltyValue(int a_tbf, int a_rbf, int a_cbf, INTNB a_voxel, int a_th)
int ReadOptionsList(const string &a_optionsList)
void ShowHelpSpecific()
A function used to show help about the child penalty.
~iPenaltyMedianRootPrior()
The destructor of iPenaltyMedianRootPrior.
int InitializeSpecific()
This function is used to initialize specific stuff to the child penalty.
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child penalty.
int LocalPreProcessingStep(int a_tbf, int a_rbf, int a_cbf, INTNB a_voxel, int a_th)
FLTNB ComputeFirstDerivative(int a_tbf, int a_rbf, int a_cbf, INTNB a_voxel, int a_th)
FLTNB GetVoxSizeY()
Get the voxel&#39;s size along the Y axis, in mm.
int ReadConfigurationFile(const string &a_configurationFile)
FLTNB ComputeSecondDerivative(int a_tbf, int a_rbf, int a_cbf, INTNB a_voxel, int a_th)
This class is designed to generically described any penalty applied to MAP algorithms.
#define KEYWORD_MANDATORY
#define KEYWORD_OPTIONAL
int ComputeMedianInNeighborhood(int a_tbf, int a_rbf, int a_cbf, INTNB a_voxel, int a_th)
int GetNbThreadsForImageComputation()
Get the number of threads used for image operations.
iPenaltyMedianRootPrior()
The constructor of iPenaltyMedianRootPrior.
INTNB GetNbVoxX()
Get the number of voxels along the X axis.
INTNB GetNbVoxZ()
Get the number of voxels along the Z axis.
int ReadDataASCIIFile(const string &a_file, const string &a_keyword, T *ap_return, int a_nbElts, bool a_mandatoryFlag)
Look for "a_nbElts" elts in the "a_file" file matching the "a_keyword" string passed as parameter a...
#define Cout(MESSAGE)
oImageDimensionsAndQuantification * mp_ImageDimensionsAndQuantification
int BuildNeighborhoodKernel()
A function used to build the neighborhood kernel.
INTNB GetNbVoxY()
Get the number of voxels along the Y axis.
#define KEYWORD_OPTIONAL_ERROR