source: trunk/src/ATrous/atrous_3d_reconstruct.cc @ 174

Last change on this file since 174 was 174, checked in by Matthew Whiting, 18 years ago
  • Minor fixes to the code in the three atrous reconstruct functions, to make them a bit more readable.
  • Deleted the old functions in the ATrous directory (that have not been touched for ages and not used by anything).
File size: 7.8 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))
36      sigmaFactors[i] = reconFilter.sigmaFactor(3,i);
37    else sigmaFactors[i] = sigmaFactors[i-1] / sqrt(8.);
38  }
39
40  float mean,sigma,originalSigma,originalMean,oldsigma,newsigma;
41  bool *isGood = new bool[size];
42  float blankPixValue = par.getBlankPixVal();
43  for(int pos=0;pos<size;pos++){
44    isGood[pos] = !par.isBlank(input[pos]);
45  }
46
47  float *array = new float[size];
48  int goodSize=0;
49  for(int i=0;i<size;i++) if(isGood[i]) array[goodSize++] = input[i];
50  findMedianStats(array,goodSize,originalMean,originalSigma);
51  originalSigma /= correctionFactor; // correct from MADFM to sigma estimator.
52  delete [] array;
53
54  float *coeffs = new float[size];
55  float *wavelet = new float[size];
56
57  for(int pos=0;pos<size;pos++) output[pos]=0.;
58
59  // Define the 3-D (separable) filter, using info from reconFilter
60  int filterwidth = reconFilter.width();
61  int filterHW = filterwidth/2;
62  int fsize = filterwidth*filterwidth*filterwidth;
63  double *filter = new double[fsize];
64  for(int i=0;i<filterwidth;i++){
65    for(int j=0;j<filterwidth;j++){
66      for(int k=0;k<filterwidth;k++){
67      filter[i +j*filterwidth + k*filterwidth*filterwidth] =
68        reconFilter.coeff(i) * reconFilter.coeff(j) * reconFilter.coeff(k);
69      }
70    }
71  }
72
73  // Locating the borders of the image -- ignoring BLANK pixels
74  //  Only do this if flagBlankPix is true.
75  //  Otherwise use the full range of x and y.
76  //  No trimming is done in the z-direction at this point.
77  int *xLim1 = new int[ydim];
78  for(int i=0;i<ydim;i++) xLim1[i] = 0;
79  int *xLim2 = new int[ydim];
80  for(int i=0;i<ydim;i++) xLim2[i] = xdim-1;
81  int *yLim1 = new int[xdim];
82  for(int i=0;i<xdim;i++) yLim1[i] = 0;
83  int *yLim2 = new int[xdim];
84  for(int i=0;i<xdim;i++) yLim2[i] = ydim-1;
85
86  if(par.getFlagBlankPix()){
87    float avGapX = 0, avGapY = 0;
88    for(int row=0;row<ydim;row++){
89      int ct1 = 0;
90      int ct2 = xdim - 1;
91      while((ct1<ct2)&&(par.isBlank(input[row*xdim+ct1]))) ct1++;
92      while((ct2>ct1)&&(par.isBlank(input[row*xdim+ct2]))) ct2--;
93      xLim1[row] = ct1;
94      xLim2[row] = ct2;
95      avGapX += ct2 - ct1 + 1;
96    }
97    avGapX /= float(ydim);
98
99    for(int col=0;col<xdim;col++){
100      int ct1=0;
101      int ct2=ydim-1;
102      while((ct1<ct2)&&(par.isBlank(input[col+xdim*ct1]))) ct1++;
103      while((ct2>ct1)&&(par.isBlank(input[col+xdim*ct2]))) ct2--;
104      yLim1[col] = ct1;
105      yLim2[col] = ct2;
106      avGapY += ct2 - ct1 + 1;
107    }
108    avGapY /= float(xdim);
109 
110    mindim = int(avGapX);
111    if(avGapY < avGapX) mindim = int(avGapY);
112    numScales = reconFilter.getNumScales(mindim);
113  }
114
115  float threshold;
116  int iteration=0;
117  newsigma = 1.e9;
118  for(int i=0;i<size;i++) output[i] = 0;
119  do{
120    if(par.isVerbose()) std::cout << "Iteration #"<<setw(2)<<++iteration<<": ";
121    // first, get the value of oldsigma, set it to the previous newsigma value
122    oldsigma = newsigma;
123    // we are transforming the residual array (input array first time around)
124    for(int i=0;i<size;i++)  coeffs[i] = input[i] - output[i];
125
126    int spacing = 1;
127    for(int scale = 1; scale<=numScales; scale++){
128
129      if(par.isVerbose()){
130        std::cout << "Scale ";
131        std::cout << setw(2)<<scale<<" / "<<setw(2)<<numScales
132                  << "\b\b\b\b\b\b\b\b\b\b\b\b\b"<<std::flush;
133      }
134
135      int pos = -1;
136      for(int zpos = 0; zpos<zdim; zpos++){
137        for(int ypos = 0; ypos<ydim; ypos++){
138          for(int xpos = 0; xpos<xdim; xpos++){
139            // loops over each pixel in the image
140            pos++;
141
142            wavelet[pos] = coeffs[pos];
143           
144            if(!isGood[pos] )  wavelet[pos] = 0.;
145            else{
146
147              int filterpos = -1;
148              for(int zoffset=-filterHW; zoffset<=filterHW; zoffset++){
149                int z = zpos + spacing*zoffset;
150                if(z<0) z = -z;                 // boundary conditions are
151                if(z>=zdim) z = 2*(zdim-1) - z; //    reflection.
152               
153                int oldchan = z * spatialSize;
154               
155                for(int yoffset=-filterHW; yoffset<=filterHW; yoffset++){
156                  int y = ypos + spacing*yoffset;
157
158                  // Boundary conditions -- assume reflection at boundaries.
159                  // Use limits as calculated above
160                  if(yLim1[xpos]!=yLim2[xpos]){
161                    // if these are equal we will get into an infinite loop
162                    while((y<yLim1[xpos])||(y>yLim2[xpos])){
163                      if(y<yLim1[xpos]) y = 2*yLim1[xpos] - y;     
164                      else if(y>yLim2[xpos]) y = 2*yLim2[xpos] - y;     
165                    }
166                  }
167                  int oldrow = y * xdim;
168         
169                  for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
170                    int x = xpos + spacing*xoffset;
171
172                    // Boundary conditions -- assume reflection at boundaries.
173                    // Use limits as calculated above
174                    if(xLim1[ypos]!=xLim2[ypos]){
175                      // if these are equal we will get into an infinite loop
176                      while((x<xLim1[ypos])||(x>xLim2[ypos])){
177                        if(x<xLim1[ypos]) x = 2*xLim1[ypos] - x;     
178                        else if(x>xLim2[ypos]) x = 2*xLim2[ypos] - x;     
179                      }
180                    }
181
182                    int oldpos = oldchan + oldrow + x;
183
184                    filterpos++;
185                   
186                    if(isGood[oldpos])
187                      wavelet[pos] -= filter[filterpos]*coeffs[oldpos];
188                     
189                  } //-> end of xoffset loop
190                } //-> end of yoffset loop
191              } //-> end of zoffset loop
192            } //-> end of else{ ( from if(!isGood[pos])  )
193           
194          } //-> end of xpos loop
195        } //-> end of ypos loop
196      } //-> end of zpos loop
197
198      // Need to do this after we've done *all* the convolving
199      for(int pos=0;pos<size;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
200
201      // Have found wavelet coeffs for this scale -- now threshold
202      if(scale>=par.getMinScale()){
203        array = new float[size];
204        goodSize=0;
205        for(int pos=0;pos<size;pos++)
206          if(isGood[pos]) array[goodSize++] = wavelet[pos];
207        findMedianStats(array,goodSize,mean,sigma);
208        delete [] array;
209       
210        threshold = mean +
211          par.getAtrousCut()*originalSigma*sigmaFactors[scale];
212        for(int pos=0;pos<size;pos++){
213          if(!isGood[pos]){
214            output[pos] = blankPixValue;
215            // this preserves the Blank pixel values in the output.
216          }
217          else if( fabs(wavelet[pos]) > threshold ){
218            output[pos] += wavelet[pos];
219            // only add to the output if the wavelet coefficient is significant
220          }
221        }
222      }
223 
224      spacing *= 2;  // double the scale of the filter.
225
226    } //-> end of scale loop
227
228    for(int pos=0;pos<size;pos++) if(isGood[pos]) output[pos] += coeffs[pos];
229
230    array = new float[size];
231    goodSize=0;
232    for(int i=0;i<size;i++) {
233      if(isGood[i]) array[goodSize++] = input[i] - output[i];
234    }
235    findMedianStats(array,goodSize,mean,newsigma);
236    newsigma /= correctionFactor; // correct from MADFM to sigma estimator.
237    delete [] array;
238
239    if(par.isVerbose()) std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
240
241  } while( (iteration==1) ||
242           (fabs(oldsigma-newsigma)/newsigma > reconTolerance) );
243
244  if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
245
246  delete [] xLim1,xLim2,yLim1,yLim2;
247  delete [] coeffs;
248  delete [] wavelet;
249  delete [] isGood;
250  delete [] filter;
251  delete [] sigmaFactors;
252}
Note: See TracBrowser for help on using the repository browser.