source: tags/release-0.9.2/ATrous/atrous_3d_reconstruct.cc @ 1455

Last change on this file since 1455 was 86, checked in by Matthew Whiting, 18 years ago

Large commit, mostly removing dud commented code, and adding comments and
documentation to the existing code. No new features.

File size: 7.6 KB
Line 
1#include <iostream>
2#include <iomanip>
3#include <math.h>
4#include <ATrous/atrous.hh>
5#include <Utils/utils.hh>
6
7using std::endl;
8using std::setw;
9
10void atrous3DReconstruct(long &xdim, long &ydim, long &zdim, float *&input,
11                         float *&output, Param &par)
12{
13  /**
14   *  atrous3DReconstruct(xdim, ydim, zdim, input, output, par)
15   *
16   *  A routine that uses the a trous wavelet method to reconstruct a
17   *   3-dimensional image cube.
18   *  The Param object "par" contains all necessary info about the filter and
19   *   reconstruction parameters, although a Filter object has to be declared
20   *   elsewhere previously.
21   *  The input array is in "input", of dimensions "xdim"x"ydim"x"zdim", and
22   *   the reconstructed array is in "output".
23   */
24
25  extern Filter reconFilter;
26  long size = xdim * ydim * zdim;
27  long spatialSize = xdim * ydim;
28  long mindim = xdim;
29  if (ydim<mindim) mindim = ydim;
30  if (zdim<mindim) mindim = zdim;
31  int numScales = reconFilter.getNumScales(mindim);
32
33  double *sigmaFactors = new double[numScales+1];
34  for(int i=0;i<=numScales;i++){
35    if(i<=reconFilter.maxFactor(3)) sigmaFactors[i] = reconFilter.sigmaFactor(3,i);
36    else sigmaFactors[i] = sigmaFactors[i-1] / sqrt(8.);
37  }
38
39  float mean,sigma,originalSigma,originalMean,oldsigma,newsigma;
40  bool *isGood = new bool[size];
41  float blankPixValue = par.getBlankPixVal();
42  for(int pos=0;pos<size;pos++){
43    isGood[pos] = !par.isBlank(input[pos]);
44  }
45
46  float *array = new float[size];
47  int goodSize=0;
48  for(int i=0;i<size;i++) if(isGood[i]) array[goodSize++] = input[i];
49  findMedianStats(array,goodSize,originalMean,originalSigma);
50  originalSigma /= correctionFactor; // correct from MADFM to sigma estimator.
51  delete [] array;
52
53  float *coeffs = new float[size];
54  float *wavelet = new float[size];
55
56  for(int pos=0;pos<size;pos++) output[pos]=0.;
57
58  // Define the 3-D (separable) filter, using info from reconFilter
59  int filterwidth = reconFilter.width();
60  int filterHW = filterwidth/2;
61  int fsize = filterwidth*filterwidth*filterwidth;
62  double *filter = new double[fsize];
63  for(int i=0;i<filterwidth;i++){
64    for(int j=0;j<filterwidth;j++){
65      for(int k=0;k<filterwidth;k++){
66      filter[i +j*filterwidth + k*filterwidth*filterwidth] =
67        reconFilter.coeff(i) * reconFilter.coeff(j) * reconFilter.coeff(k);
68      }
69    }
70  }
71
72  // locating the borders of the image -- ignoring BLANK pixels
73  //  Only do this if flagBlankPix is true. Otherwise use the full range of x and y.
74  //  No trimming is done in the z-direction at this point.
75  int *xLim1 = new int[ydim];
76  for(int i=0;i<ydim;i++) xLim1[i] = 0;
77  int *xLim2 = new int[ydim];
78  for(int i=0;i<ydim;i++) xLim2[i] = xdim-1;
79  int *yLim1 = new int[xdim];
80  for(int i=0;i<xdim;i++) yLim1[i] = 0;
81  int *yLim2 = new int[xdim];
82  for(int i=0;i<xdim;i++) yLim2[i] = ydim-1;
83
84  if(par.getFlagBlankPix()){
85    float avGapX = 0, avGapY = 0;
86    for(int row=0;row<ydim;row++){
87      int ct1 = 0;
88      int ct2 = xdim - 1;
89      while((ct1<ct2)&&(input[row*xdim+ct1]==blankPixValue) ) ct1++;
90      while((ct2>ct1)&&(input[row*xdim+ct2]==blankPixValue) ) ct2--;
91      xLim1[row] = ct1;
92      xLim2[row] = ct2;
93      avGapX += ct2 - ct1 + 1;
94    }
95    avGapX /= float(ydim);
96
97    for(int col=0;col<xdim;col++){
98      int ct1=0;
99      int ct2=ydim-1;
100      while((ct1<ct2)&&(input[col+xdim*ct1]==blankPixValue) ) ct1++;
101      while((ct2>ct1)&&(input[col+xdim*ct2]==blankPixValue) ) ct2--;
102      yLim1[col] = ct1;
103      yLim2[col] = ct2;
104      avGapY += ct2 - ct1 + 1;
105    }
106    avGapY /= float(ydim);
107 
108    mindim = int(avGapX);
109    if(avGapY < avGapX) mindim = int(avGapY);
110    numScales = reconFilter.getNumScales(mindim);
111  }
112
113  float threshold;
114  int iteration=0;
115  newsigma = 1.e9;
116  for(int i=0;i<size;i++) output[i] = 0;
117  do{
118    if(par.isVerbose())  std::cout << "Iteration #"<<setw(2)<<++iteration<<": ";
119    // first, get the value of oldsigma, set it to the previous newsigma value
120    oldsigma = newsigma;
121    // we are transforming the residual array (input array first time around)
122    for(int i=0;i<size;i++)  coeffs[i] = input[i] - output[i];
123
124    int spacing = 1;
125    for(int scale = 1; scale<=numScales; scale++){
126
127      if(par.isVerbose()){
128        std::cout << "Scale ";
129        std::cout << setw(2)<<scale<<" / "<<setw(2)<<numScales
130                  << "\b\b\b\b\b\b\b\b\b\b\b\b\b"<<std::flush;
131      }
132
133      int pos = -1;
134      for(int zpos = 0; zpos<zdim; zpos++){
135        for(int ypos = 0; ypos<ydim; ypos++){
136          for(int xpos = 0; xpos<xdim; xpos++){
137            // loops over each pixel in the image
138            pos++;
139
140            wavelet[pos] = coeffs[pos];
141           
142            if(!isGood[pos] )  wavelet[pos] = 0.;
143            else{
144
145              int filterpos = -1;
146              for(int zoffset=-filterHW; zoffset<=filterHW; zoffset++){
147                int z = zpos + spacing*zoffset;
148                if(z<0) z = -z;                 // boundary conditions are
149                if(z>=zdim) z = 2*(zdim-1) - z; //    reflection.
150         
151                for(int yoffset=-filterHW; yoffset<=filterHW; yoffset++){
152                  int y = ypos + spacing*yoffset;
153         
154                  for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
155                    int x = xpos + spacing*xoffset;
156
157                    filterpos++;
158                   
159                    // Boundary conditions -- assume reflection at boundaries.
160                    // Use limits as calculated above
161                    if(yLim1[xpos]!=yLim2[xpos]){
162                      // if these are equal we will get into an infinite loop here
163                      while((y<yLim1[xpos])||(y>yLim2[xpos])){
164                        if(y<yLim1[xpos]) y = 2*yLim1[xpos] - y;     
165                        else if(y>yLim2[xpos]) y = 2*yLim2[xpos] - y;     
166                      }
167                    }
168
169                    if(xLim1[ypos]!=xLim2[ypos]){
170                      // if these are equal we will get into an infinite loop here
171                      while((x<xLim1[ypos])||(x>xLim2[ypos])){
172                        if(x<xLim1[ypos]) x = 2*xLim1[ypos] - x;     
173                        else if(x>xLim2[ypos]) x = 2*xLim2[ypos] - x;     
174                      }
175                    }
176
177                    int oldpos = z*spatialSize + y*xdim + x;
178                   
179                    if(isGood[oldpos])
180                      wavelet[pos] -= filter[filterpos]*coeffs[oldpos];
181                     
182                  } //-> end of xoffset loop
183                } //-> end of yoffset loop
184              } //-> end of zoffset loop
185            } //-> end of else{ ( from if(!isGood[pos])  )
186           
187          } //-> end of xpos loop
188        } //-> end of ypos loop
189      } //-> end of zpos loop
190
191      // Need to do this after we've done *all* the convolving
192      for(int pos=0;pos<size;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
193
194      // Have found wavelet coeffs for this scale -- now threshold
195      if(scale>=par.getMinScale()){
196        array = new float[size];
197        goodSize=0;
198        for(int pos=0;pos<size;pos++) if(isGood[pos]) array[goodSize++] = wavelet[pos];
199        findMedianStats(array,goodSize,mean,sigma);
200        delete [] array;
201       
202        threshold = mean + par.getAtrousCut() * originalSigma * sigmaFactors[scale];
203        for(int pos=0;pos<size;pos++){
204          if(!isGood[pos]){
205            output[pos] = blankPixValue;
206            // this preserves the Blank pixel values in the output.
207          }
208          else if( fabs(wavelet[pos]) > threshold ){
209            output[pos] += wavelet[pos];
210            // only add to the output if the wavelet coefficient is significant
211          }
212        }
213      }
214 
215      spacing *= 2;  // double the scale of the filter.
216
217    } //-> end of scale loop
218
219    for(int pos=0;pos<size;pos++) if(isGood[pos]) output[pos] += coeffs[pos];
220
221    array = new float[size];
222    goodSize=0;
223    for(int i=0;i<size;i++) if(isGood[i]) array[goodSize++] = input[i] - output[i];
224    findNormalStats(array,goodSize,mean,newsigma);
225    delete [] array;
226
227    if(par.isVerbose()) std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
228
229  } while( (iteration==1) ||
230           (fabsf(oldsigma-newsigma)/newsigma > reconTolerance) );
231
232  if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
233
234  delete [] xLim1,xLim2,yLim1,yLim2;
235  delete [] coeffs;
236  delete [] wavelet;
237  delete [] isGood;
238  delete [] filter;
239  delete [] sigmaFactors;
240}
Note: See TracBrowser for help on using the repository browser.