![]() |
CASToR
1.0
Tomographic Reconstruction (PET/SPECT)
|
00001 00002 /* 00003 Implementation of class oImageConvolverManager 00004 00005 - separators: done 00006 - doxygen: done 00007 - default initialization: done 00008 - CASTOR_DEBUG: 00009 - CASTOR_VERBOSE: 00010 */ 00011 00018 #include "oImageConvolverManager.hh" 00019 #include "sAddonManager.hh" 00020 00021 // ===================================================================== 00022 // --------------------------------------------------------------------- 00023 // --------------------------------------------------------------------- 00024 // ===================================================================== 00025 00026 oImageConvolverManager::oImageConvolverManager() 00027 { 00028 // Image dimensions 00029 mp_ImageDimensionsAndQuantification = NULL; 00030 // Options 00031 m_options = {}; 00032 // Image convolver objects and associated bool 00033 m_nbImageConvolvers = 0; 00034 m2p_ImageConvolvers = NULL; 00035 mp_applyForward = NULL; 00036 mp_applyBackward = NULL; 00037 mp_applyIntra = NULL; 00038 mp_applyPost = NULL; 00039 // Booleans 00040 m_checked = false; 00041 m_initialized = false; 00042 // Verbosity 00043 m_verbose = -1; 00044 } 00045 00046 // ===================================================================== 00047 // --------------------------------------------------------------------- 00048 // --------------------------------------------------------------------- 00049 // ===================================================================== 00050 00051 oImageConvolverManager::~oImageConvolverManager() 00052 { 00053 // Delete object 00054 if (m2p_ImageConvolvers) 00055 { 00056 for (int c=0; c<m_nbImageConvolvers; c++) if (m2p_ImageConvolvers[c]) delete m2p_ImageConvolvers[c]; 00057 free(m2p_ImageConvolvers); 00058 } 00059 } 00060 00061 // ===================================================================== 00062 // --------------------------------------------------------------------- 00063 // --------------------------------------------------------------------- 00064 // ===================================================================== 00065 00066 int oImageConvolverManager::CheckParameters() 00067 { 00068 // Check image dimensions 00069 if (mp_ImageDimensionsAndQuantification==NULL) 00070 { 00071 Cerr("***** oImageConvolverManager::CheckParameters() -> No image dimensions provided !" << endl); 00072 return 1; 00073 } 00074 // Check verbosity 00075 if (m_verbose<0) 00076 { 00077 Cerr("***** oImageConvolverManager::CheckParameters() -> Wrong verbosity level provided !" << endl); 00078 return 1; 00079 } 00080 // All set 00081 m_checked = true; 00082 // Normal end 00083 return 0; 00084 } 00085 00086 // ===================================================================== 00087 // --------------------------------------------------------------------- 00088 // --------------------------------------------------------------------- 00089 // ===================================================================== 00090 00091 void oImageConvolverManager::ShowCommonHelp() 00092 { 00093 // Return when using MPI and mpi_rank is not 0 00094 #ifdef CASTOR_MPI 00095 int mpi_rank = 0; 00096 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); 00097 if (mpi_rank!=0) return; 00098 #endif 00099 // Show help 00100 cout << "------------------------------------------------------------------" << endl; 00101 cout << "----- How to use an image convolver" << endl; 00102 cout << "------------------------------------------------------------------" << endl; 00103 cout << endl; 00104 cout << "An image convolver is called through the -conv option. The provided argument describes the convolver to be used, its options," << endl; 00105 cout << "and when to include it within the algorithm. The syntax of the argument must obey one of the three following options:" << endl; 00106 cout << " conv::when (in this case, the default configuration file of the convolver is used to set the options values)" << endl; 00107 cout << " conv:file.conf::when (in this case, the provided configuration is used)" << endl; 00108 cout << " conv,param1,param2,...::when (in this case, the options values are directly provided in the argument)" << endl; 00109 cout << "In any case, the description of the options specific to each convolver, their order in the list and their configuration" << endl; 00110 cout << "files syntax are provided in the specific help of each convolver." << endl; 00111 cout << "The 'when' parameter is an argument describing when to include the convolver within the algorithm. It is a list of keywords" << endl; 00112 cout << "separating by commas. The following keywords can be used:" << endl; 00113 cout << " forward (include convolver into forward model; a convolution of the current estimate is forward-projected)" << endl; 00114 cout << " backward (include convolver into backward model; a convolution of the correction terms is used for the update)" << endl; 00115 cout << " post (apply convolver before saving the image; the convolved image is not put back as the estimate for the next update)" << endl; 00116 cout << " psf (include both 'forward' and 'backward'; the standard image-based PSF modelling)" << endl; 00117 cout << " sieve (include both 'psf' and 'post'; the standard method of sieve)" << endl; 00118 cout << " intra (apply convolver to the updated image and use it as the current estimate for the next update)" << endl; 00119 cout << endl; 00120 } 00121 00122 // ===================================================================== 00123 // --------------------------------------------------------------------- 00124 // --------------------------------------------------------------------- 00125 // ===================================================================== 00126 00127 int oImageConvolverManager::Initialize() 00128 { 00129 // Check if parameters have been checked 00130 if (!m_checked) 00131 { 00132 Cerr("***** oImageConvolverManager::Initialize() -> Parameters have not been checked ! Please call CheckParameters() before." << endl); 00133 return 1; 00134 } 00135 // Case with no options (no convolver) 00136 if (m_options.size()==0) 00137 { 00138 m_initialized = true; 00139 return 0; 00140 } 00141 // Verbose 00142 if (m_verbose>=1) Cout("oImageConvolverManager::Initialize() -> Initialize image convolvers" << endl); 00143 // Parse image convolver options and initialize them 00144 if (ParseOptionsAndInitializeImageConvolvers()) 00145 { 00146 Cerr("***** oImageConvolverManager::Initialize() -> A problem occured while parsing image convolvers options and initializing them !" << endl); 00147 return 1; 00148 } 00149 // All set 00150 m_initialized = true; 00151 // Normal end 00152 return 0; 00153 } 00154 00155 // ===================================================================== 00156 // --------------------------------------------------------------------- 00157 // --------------------------------------------------------------------- 00158 // ===================================================================== 00159 00160 int oImageConvolverManager::ParseOptionsAndInitializeImageConvolvers() 00161 { 00162 // ============================================================== 00163 // First get the number of convolvers from the list of options 00164 // ============================================================== 00165 00166 m_nbImageConvolvers = m_options.size(); 00167 00168 // Allocate the tables 00169 m2p_ImageConvolvers = (vImageConvolver**)malloc(m_nbImageConvolvers*sizeof(vImageConvolver*)); 00170 mp_applyForward = (bool*)malloc(m_nbImageConvolvers*sizeof(bool)); 00171 mp_applyBackward = (bool*)malloc(m_nbImageConvolvers*sizeof(bool)); 00172 mp_applyIntra = (bool*)malloc(m_nbImageConvolvers*sizeof(bool)); 00173 mp_applyPost = (bool*)malloc(m_nbImageConvolvers*sizeof(bool)); 00174 00175 // ============================================================== 00176 // Then we loop over all convolvers, read options and initialize 00177 // ============================================================== 00178 00179 // This is for the automatic initialization of the convolvers 00180 typedef vImageConvolver *(*maker_image_convolver) (); 00181 // Get image convolver's list from addon manager 00182 std::map <string,maker_image_convolver> list = sAddonManager::GetInstance()->mp_listOfImageConvolvers; 00183 00184 // Start the loop 00185 for (int c=0; c<m_nbImageConvolvers; c++) 00186 { 00187 // Default initializations 00188 m2p_ImageConvolvers[c] = NULL; 00189 mp_applyForward[c] = false; 00190 mp_applyBackward[c] = false; 00191 mp_applyIntra[c] = false; 00192 mp_applyPost[c] = false; 00193 00194 // ___________________________________________________________________________________ 00195 // Search for a double-colon and isolate the convolver's options from the 'when' actions 00196 00197 size_t double_colon = m_options[c].find_first_of("::"); 00198 00199 // Send an error if no double-colon 00200 if (double_colon==string::npos) 00201 { 00202 Cerr("***** oImageConvolverManager::ParseOptionsAndInitializeImageConvolvers() -> Wrong syntax in the " << c+1 << "th image convolver !" << endl); 00203 Cerr(" No double-colon \"::\" found." << endl); 00204 ShowCommonHelp(); 00205 return 1; 00206 } 00207 00208 // Separate the two arguments 00209 string conv_part_options = m_options[c].substr(0,double_colon); 00210 string when_part_options = m_options[c].substr(double_colon+2); 00211 00212 // ___________________________________________________________________________________ 00213 // Get the image convolver name in the options and isolate the actual image convolver's options 00214 00215 // Useful strings 00216 string convolver = ""; 00217 string list_options = ""; 00218 string file_options = ""; 00219 00220 // Search for a colon ":", this indicates that a configuration file is provided after the image convolver name 00221 size_t colon = conv_part_options.find_first_of(":"); 00222 size_t comma = conv_part_options.find_first_of(","); 00223 00224 // Case 1: we have a colon 00225 if (colon!=string::npos) 00226 { 00227 // Get the image convolver name before the colon 00228 convolver = conv_part_options.substr(0,colon); 00229 // Get the configuration file after the colon 00230 file_options = conv_part_options.substr(colon+1); 00231 // List of options is empty 00232 list_options = ""; 00233 } 00234 // Case 2: we have a comma 00235 else if (comma!=string::npos) 00236 { 00237 // Get the image convolver name before the first comma 00238 convolver = conv_part_options.substr(0,comma); 00239 // Get the list of options after the first comma 00240 list_options = conv_part_options.substr(comma+1); 00241 // Configuration file is empty 00242 file_options = ""; 00243 } 00244 // Case 3: no colon and no comma (a single image convolver name) 00245 else 00246 { 00247 // Get the image convolver name 00248 convolver = conv_part_options; 00249 // List of options is empty 00250 list_options = ""; 00251 // Build the default configuration file 00252 file_options = sOutputManager::GetInstance()->GetPathToConfigDir() + "/convolver/" + convolver + ".conf"; 00253 } 00254 00255 // ___________________________________________________________________________________ 00256 // Read the 'when' actions 00257 00258 // Loop while commas are found 00259 while ((comma=when_part_options.find_first_of(",")) != string::npos) 00260 { 00261 // Extract the first option 00262 string option = when_part_options.substr(0,comma); 00263 // Extract the rest 00264 when_part_options = when_part_options.substr(comma+1); 00265 // Check the meaning of the option 00266 if (option=="forward") {mp_applyForward[c] = true;} 00267 else if (option=="backward") {mp_applyBackward[c] = true;} 00268 else if (option=="post") {mp_applyPost[c] = true;} 00269 else if (option=="psf") {mp_applyForward[c] = true; mp_applyBackward[c] = true;} 00270 else if (option=="sieve") {mp_applyForward[c] = true; mp_applyBackward[c] = true; mp_applyPost[c] = true;} 00271 else if (option=="intra") {mp_applyIntra[c] = true;} 00272 else 00273 { 00274 Cerr("***** oImageConvolverManager::ParseOptionsAndInitializeImageConvolvers() -> Unknown keyword '" << option << "' provided in options list !" << endl); 00275 ShowCommonHelp(); 00276 return 1; 00277 } 00278 } 00279 // Last option 00280 if (when_part_options=="forward") {mp_applyForward[c] = true;} 00281 else if (when_part_options=="backward") {mp_applyBackward[c] = true;} 00282 else if (when_part_options=="post") {mp_applyPost[c] = true;} 00283 else if (when_part_options=="psf") {mp_applyForward[c] = true; mp_applyBackward[c] = true;} 00284 else if (when_part_options=="sieve") {mp_applyForward[c] = true; mp_applyBackward[c] = true; mp_applyPost[c] = true;} 00285 else if (when_part_options=="intra") {mp_applyIntra[c] = true;} 00286 else 00287 { 00288 Cerr("***** oImageConvolverManager::ParseOptionsAndInitializeImageConvolvers() -> Unknown keyword '" << when_part_options << "' provided in options list !" << endl); 00289 ShowCommonHelp(); 00290 return 1; 00291 } 00292 00293 // ______________________________________________________________________________ 00294 // Create convolver and call associated functions 00295 00296 // Create the image convolver 00297 if (list[convolver]) m2p_ImageConvolvers[c] = list[convolver](); 00298 else 00299 { 00300 Cerr("***** oImageConvolverManager::ParseOptionsAndInitializeImageConvolvers() -> Image convolver '" << convolver << "' does not exist !" << endl); 00301 sAddonManager::GetInstance()->ShowHelpImageConvolver(); 00302 return 1; 00303 } 00304 // Set parameters 00305 m2p_ImageConvolvers[c]->SetImageDimensionsAndQuantification(mp_ImageDimensionsAndQuantification); 00306 m2p_ImageConvolvers[c]->SetVerbose(m_verbose); 00307 // Provide configuration file if any 00308 if (file_options!="" && m2p_ImageConvolvers[c]->ReadConfigurationFile(file_options)) 00309 { 00310 Cerr("***** oImageConvolverManager::ParseOptionsAndInitializeImageConvolvers() -> A problem occured while reading and checking configuration file for image convolver '" << convolver << "' !" << endl); 00311 return 1; 00312 } 00313 // Provide options if any 00314 if (list_options!="" && m2p_ImageConvolvers[c]->ReadOptionsList(list_options)) 00315 { 00316 Cerr("***** oImageConvolverManager::ParseOptionsAndInitializeImageConvolvers() -> A problem occured while parsing and reading options list for image convolver '" << convolver << "' !" << endl); 00317 return 1; 00318 } 00319 // Check parameters 00320 if (m2p_ImageConvolvers[c]->CheckParameters()) 00321 { 00322 Cerr("***** oImageConvolverManager::ParseOptionsAndInitializeImageConvolvers() -> A problem occured while checking parameters for image convolver '" << convolver << "' !" << endl); 00323 return 1; 00324 } 00325 // Initialize the image convolver 00326 if (m2p_ImageConvolvers[c]->Initialize()) 00327 { 00328 Cerr("***** oImageConvolverManager::ParseOptionsAndInitializeImageConvolvers() -> A problem occured while initializing image convolver '" << convolver << "' !" << endl); 00329 return 1; 00330 } 00331 } 00332 00333 // Normal end 00334 return 0; 00335 } 00336 00337 // ===================================================================== 00338 // --------------------------------------------------------------------- 00339 // --------------------------------------------------------------------- 00340 // ===================================================================== 00341 00342 int oImageConvolverManager::ConvolveForward(oImageSpace* ap_ImageSpace) 00343 { 00344 #ifdef CASTOR_DEBUG 00345 // Check if initialized 00346 if (!m_initialized) 00347 { 00348 Cerr("***** oImageConvolverManager::ConvolveForward() -> Called while not initialized !" << endl); 00349 return 1; 00350 } 00351 #endif 00352 // Loop on convolvers 00353 for (int c=0; c<m_nbImageConvolvers; c++) 00354 { 00355 // Apply it only if asked for 00356 if (mp_applyForward[c]) 00357 { 00358 // Verbose 00359 if (m_verbose>=2) 00360 { 00361 if (m_nbImageConvolvers>1) Cout("oImageConvolverManager::ConvolveForward() -> Apply convolution " << c+1 << " to forward image" << endl); 00362 else Cout("oImageConvolverManager::ConvolveForward() -> Apply convolution to forward image" << endl); 00363 } 00364 // Loop on basis functions 00365 for (int tb=0; tb<mp_ImageDimensionsAndQuantification->GetNbTimeBasisFunctions(); tb++) 00366 { 00367 for (int rb=0; rb<mp_ImageDimensionsAndQuantification->GetNbRespBasisFunctions(); rb++) 00368 { 00369 for (int cb=0; cb<mp_ImageDimensionsAndQuantification->GetNbCardBasisFunctions(); cb++) 00370 { 00371 // Get the pointer to the image 00372 FLTNB* image = ap_ImageSpace->m4p_forwardImage[tb][rb][cb]; 00373 // Apply convolution 00374 m2p_ImageConvolvers[c]->ApplyConvolution(image); 00375 } 00376 } 00377 } 00378 } 00379 } 00380 // Normal end 00381 return 0; 00382 } 00383 00384 // ===================================================================== 00385 // --------------------------------------------------------------------- 00386 // --------------------------------------------------------------------- 00387 // ===================================================================== 00388 00389 int oImageConvolverManager::ConvolveBackward(oImageSpace* ap_ImageSpace) 00390 { 00391 #ifdef CASTOR_DEBUG 00392 // Check if initialized 00393 if (!m_initialized) 00394 { 00395 Cerr("***** oImageConvolverManager::ConvolveBackward() -> Called while not initialized !" << endl); 00396 return 1; 00397 } 00398 #endif 00399 // Loop on convolvers 00400 for (int c=0; c<m_nbImageConvolvers; c++) 00401 { 00402 // Apply it only if asked for 00403 if (mp_applyBackward[c]) 00404 { 00405 // Verbose 00406 if (m_verbose>=2) 00407 { 00408 if (m_nbImageConvolvers>1) 00409 { 00410 if (ap_ImageSpace->IsLoadedSensitivity()) Cout("oImageConvolverManager::ConvolveBackward() -> Apply convolution " << c+1 << " to backward image" << endl); 00411 else Cout("oImageConvolverManager::ConvolveBackward() -> Apply convolution " << c+1 << " to backward and sensitivity images" << endl); 00412 } 00413 else 00414 { 00415 if (ap_ImageSpace->IsLoadedSensitivity()) Cout("oImageConvolverManager::ConvolveBackward() -> Apply convolution to backward image" << endl); 00416 else Cout("oImageConvolverManager::ConvolveBackward() -> Apply convolution to backward and sensitivity images" << endl); 00417 } 00418 } 00419 // Deal with backward images, loop on number of images 00420 for (int img=0; img<ap_ImageSpace->GetNbBackwardImages(); img++) 00421 { 00422 // Loop on basis functions 00423 for (int tb=0; tb<mp_ImageDimensionsAndQuantification->GetNbTimeBasisFunctions(); tb++) 00424 { 00425 for (int rb=0; rb<mp_ImageDimensionsAndQuantification->GetNbRespBasisFunctions(); rb++) 00426 { 00427 for (int cb=0; cb<mp_ImageDimensionsAndQuantification->GetNbCardBasisFunctions(); cb++) 00428 { 00429 // Get the pointer to the image 00430 int thread_0 = 0; 00431 FLTNB* image = ap_ImageSpace->m6p_backwardImage[img][thread_0][tb][rb][cb]; 00432 // Apply convolution 00433 m2p_ImageConvolvers[c]->ApplyConvolutionTranspose(image); 00434 } 00435 } 00436 } 00437 } 00438 // Deal with sensitivity images for histogram reconstructions 00439 if (!ap_ImageSpace->IsLoadedSensitivity()) 00440 { 00441 // Loop on frames and gates 00442 for (int fr=0; fr<mp_ImageDimensionsAndQuantification->GetNbTimeFrames(); fr++) 00443 { 00444 for (int rg=0; rg<mp_ImageDimensionsAndQuantification->GetSensNbRespGates(); rg++) 00445 { 00446 for (int cg=0; cg<mp_ImageDimensionsAndQuantification->GetSensNbCardGates(); cg++) 00447 { 00448 // Get the pointer to the image 00449 int thread_0 = 0; 00450 FLTNB* image = ap_ImageSpace->m5p_sensitivity[thread_0][fr][rg][cg]; 00451 // Apply convolution 00452 m2p_ImageConvolvers[c]->ApplyConvolutionTranspose(image); 00453 } 00454 } 00455 } 00456 } 00457 } 00458 } 00459 // Normal end 00460 return 0; 00461 } 00462 00463 // ===================================================================== 00464 // --------------------------------------------------------------------- 00465 // --------------------------------------------------------------------- 00466 // ===================================================================== 00467 00468 int oImageConvolverManager::ConvolveIntra(oImageSpace* ap_ImageSpace) 00469 { 00470 #ifdef CASTOR_DEBUG 00471 // Check if initialized 00472 if (!m_initialized) 00473 { 00474 Cerr("***** oImageConvolverManager::ConvolveIntra() -> Called while not initialized !" << endl); 00475 return 1; 00476 } 00477 #endif 00478 // Loop on convolvers 00479 for (int c=0; c<m_nbImageConvolvers; c++) 00480 { 00481 // Apply it only if asked for 00482 if (mp_applyIntra[c]) 00483 { 00484 // Verbose 00485 if (m_verbose>=2) 00486 { 00487 if (m_nbImageConvolvers>1) Cout("oImageConvolverManager::ConvolveIntra() -> Apply convolution " << c+1 << " to current image" << endl); 00488 else Cout("oImageConvolverManager::ConvolveIntra() -> Apply convolution to current image" << endl); 00489 } 00490 // Loop on basis functions 00491 for (int tb=0; tb<mp_ImageDimensionsAndQuantification->GetNbTimeBasisFunctions(); tb++) 00492 { 00493 for (int rb=0; rb<mp_ImageDimensionsAndQuantification->GetNbRespBasisFunctions(); rb++) 00494 { 00495 for (int cb=0; cb<mp_ImageDimensionsAndQuantification->GetNbCardBasisFunctions(); cb++) 00496 { 00497 // Get the pointer to the image 00498 FLTNB* image = ap_ImageSpace->m4p_image[tb][rb][cb]; 00499 // Apply convolution 00500 m2p_ImageConvolvers[c]->ApplyConvolution(image); 00501 } 00502 } 00503 } 00504 } 00505 } 00506 // Normal end 00507 return 0; 00508 } 00509 00510 // ===================================================================== 00511 // --------------------------------------------------------------------- 00512 // --------------------------------------------------------------------- 00513 // ===================================================================== 00514 00515 int oImageConvolverManager::ConvolveSensitivity(oImageSpace* ap_ImageSpace) 00516 { 00517 #ifdef CASTOR_DEBUG 00518 // Check if initialized 00519 if (!m_initialized) 00520 { 00521 Cerr("***** oImageConvolverManager::ConvolveSensitivity() -> Called while not initialized !" << endl); 00522 return 1; 00523 } 00524 #endif 00525 // Loop on convolvers 00526 for (int c=0; c<m_nbImageConvolvers; c++) 00527 { 00528 // Apply it only if asked for 00529 if (mp_applyBackward[c]) 00530 { 00531 // Verbose 00532 if (m_verbose>=2) 00533 { 00534 if (m_nbImageConvolvers>1) Cout("oImageConvolverManager::ConvolveSensitivity() -> Apply convolution " << c+1 << " to sensitivity image" << endl); 00535 else Cout("oImageConvolverManager::ConvolveSensitivity() -> Apply convolution to sensitivity image" << endl); 00536 } 00537 // Loop on frames and gates 00538 for (int fr=0; fr<mp_ImageDimensionsAndQuantification->GetNbTimeFrames(); fr++) 00539 { 00540 for (int rg=0; rg<mp_ImageDimensionsAndQuantification->GetSensNbRespGates(); rg++) 00541 { 00542 for (int cg=0; cg<mp_ImageDimensionsAndQuantification->GetSensNbCardGates(); cg++) 00543 { 00544 // Get the pointer to the image 00545 int thread_0 = 0; 00546 FLTNB* image = ap_ImageSpace->m5p_sensitivity[thread_0][fr][rg][cg]; 00547 // Apply convolution 00548 m2p_ImageConvolvers[c]->ApplyConvolutionTranspose(image); 00549 } 00550 } 00551 } 00552 } 00553 } 00554 // Normal end 00555 return 0; 00556 } 00557 00558 // ===================================================================== 00559 // --------------------------------------------------------------------- 00560 // --------------------------------------------------------------------- 00561 // ===================================================================== 00562 00563 int oImageConvolverManager::ConvolvePost(oImageSpace* ap_ImageSpace) 00564 { 00565 #ifdef CASTOR_DEBUG 00566 // Check if initialized 00567 if (!m_initialized) 00568 { 00569 Cerr("***** oImageConvolverManager::ConvolvePost() -> Called while not initialized !" << endl); 00570 return 1; 00571 } 00572 #endif 00573 // Loop on convolvers 00574 for (int c=0; c<m_nbImageConvolvers; c++) 00575 { 00576 // Apply it only if asked for 00577 if (mp_applyPost[c]) 00578 { 00579 // Verbose 00580 if (m_verbose>=2) 00581 { 00582 if (m_nbImageConvolvers>1) Cout("oImageConvolverManager::ConvolvePost() -> Apply convolution " << c+1 << " to output image" << endl); 00583 else Cout("oImageConvolverManager::ConvolvePost() -> Apply convolution to output image" << endl); 00584 } 00585 00586 // Loop on frames and respiratory/cardiac gates 00587 for (int fr=0; fr<mp_ImageDimensionsAndQuantification->GetNbTimeFrames(); fr++) 00588 { 00589 for (int rg=0; rg<mp_ImageDimensionsAndQuantification->GetNbRespGates(); rg++) 00590 { 00591 for (int cg=0; cg<mp_ImageDimensionsAndQuantification->GetNbCardGates(); cg++) 00592 { 00593 // Get the pointer to the output image 00594 FLTNB* image = ap_ImageSpace->m4p_outputImage[fr][rg][cg]; 00595 // Apply convolution 00596 m2p_ImageConvolvers[c]->ApplyConvolution(image); 00597 } 00598 } 00599 } 00600 } 00601 } 00602 // Normal end 00603 return 0; 00604 } 00605 00606 // ===================================================================== 00607 // --------------------------------------------------------------------- 00608 // --------------------------------------------------------------------- 00609 // =====================================================================