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

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

Changed all instances of fabsf to fabs so that compilation on venice works.

File size: 8.1 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      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)&&(input[col+xdim*ct1]==blankPixValue) ) ct1++;
103//       while((ct2>ct1)&&(input[col+xdim*ct2]==blankPixValue) ) ct2--;
104      while((ct1<ct2)&&(par.isBlank(input[col+xdim*ct1]))) ct1++;
105      while((ct2>ct1)&&(par.isBlank(input[col+xdim*ct2]))) ct2--;
106      yLim1[col] = ct1;
107      yLim2[col] = ct2;
108      avGapY += ct2 - ct1 + 1;
109    }
110    avGapY /= float(xdim);
111 
112    mindim = int(avGapX);
113    if(avGapY < avGapX) mindim = int(avGapY);
114    numScales = reconFilter.getNumScales(mindim);
115  }
116
117  float threshold;
118  int iteration=0;
119  newsigma = 1.e9;
120  for(int i=0;i<size;i++) output[i] = 0;
121  do{
122    if(par.isVerbose())  std::cout << "Iteration #"<<setw(2)<<++iteration<<": ";
123    // first, get the value of oldsigma, set it to the previous newsigma value
124    oldsigma = newsigma;
125    // we are transforming the residual array (input array first time around)
126    for(int i=0;i<size;i++)  coeffs[i] = input[i] - output[i];
127
128    int spacing = 1;
129    for(int scale = 1; scale<=numScales; scale++){
130
131      if(par.isVerbose()){
132        std::cout << "Scale ";
133        std::cout << setw(2)<<scale<<" / "<<setw(2)<<numScales
134                  << "\b\b\b\b\b\b\b\b\b\b\b\b\b"<<std::flush;
135      }
136
137      int pos = -1;
138      for(int zpos = 0; zpos<zdim; zpos++){
139        for(int ypos = 0; ypos<ydim; ypos++){
140          for(int xpos = 0; xpos<xdim; xpos++){
141            // loops over each pixel in the image
142            pos++;
143
144            wavelet[pos] = coeffs[pos];
145           
146            if(!isGood[pos] )  wavelet[pos] = 0.;
147            else{
148
149              int filterpos = -1;
150              for(int zoffset=-filterHW; zoffset<=filterHW; zoffset++){
151                int z = zpos + spacing*zoffset;
152                if(z<0) z = -z;                 // boundary conditions are
153                if(z>=zdim) z = 2*(zdim-1) - z; //    reflection.
154               
155                int oldchan = z * spatialSize;
156               
157                for(int yoffset=-filterHW; yoffset<=filterHW; yoffset++){
158                  int y = ypos + spacing*yoffset;
159
160                  // Boundary conditions -- assume reflection at boundaries.
161                  // Use limits as calculated above
162                  if(yLim1[xpos]!=yLim2[xpos]){
163                    // if these are equal we will get into an infinite loop here
164                    while((y<yLim1[xpos])||(y>yLim2[xpos])){
165                      if(y<yLim1[xpos]) y = 2*yLim1[xpos] - y;     
166                      else if(y>yLim2[xpos]) y = 2*yLim2[xpos] - y;     
167                    }
168                  }
169                  int oldrow = y * xdim;
170         
171                  for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
172                    int x = xpos + spacing*xoffset;
173
174                    // Boundary conditions -- assume reflection at boundaries.
175                    // Use limits as calculated above
176                    if(xLim1[ypos]!=xLim2[ypos]){
177                      // if these are equal we will get into an infinite loop here
178                      while((x<xLim1[ypos])||(x>xLim2[ypos])){
179                        if(x<xLim1[ypos]) x = 2*xLim1[ypos] - x;     
180                        else if(x>xLim2[ypos]) x = 2*xLim2[ypos] - x;     
181                      }
182                    }
183
184//                  int oldpos = z*spatialSize + y*xdim + x;
185                    int oldpos = oldchan + oldrow + x;
186
187                    filterpos++;
188                   
189                    if(isGood[oldpos])
190                      wavelet[pos] -= filter[filterpos]*coeffs[oldpos];
191                     
192                  } //-> end of xoffset loop
193                } //-> end of yoffset loop
194              } //-> end of zoffset loop
195            } //-> end of else{ ( from if(!isGood[pos])  )
196           
197          } //-> end of xpos loop
198        } //-> end of ypos loop
199      } //-> end of zpos loop
200
201      // Need to do this after we've done *all* the convolving
202      for(int pos=0;pos<size;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
203
204      // Have found wavelet coeffs for this scale -- now threshold
205      if(scale>=par.getMinScale()){
206        array = new float[size];
207        goodSize=0;
208        for(int pos=0;pos<size;pos++) if(isGood[pos]) array[goodSize++] = wavelet[pos];
209        findMedianStats(array,goodSize,mean,sigma);
210        delete [] array;
211       
212        threshold = mean + par.getAtrousCut() * originalSigma * sigmaFactors[scale];
213        for(int pos=0;pos<size;pos++){
214          if(!isGood[pos]){
215            output[pos] = blankPixValue;
216            // this preserves the Blank pixel values in the output.
217          }
218          else if( fabs(wavelet[pos]) > threshold ){
219            output[pos] += wavelet[pos];
220            // only add to the output if the wavelet coefficient is significant
221          }
222        }
223      }
224 
225      spacing *= 2;  // double the scale of the filter.
226
227    } //-> end of scale loop
228
229    for(int pos=0;pos<size;pos++) if(isGood[pos]) output[pos] += coeffs[pos];
230
231    array = new float[size];
232    goodSize=0;
233    for(int i=0;i<size;i++) if(isGood[i]) array[goodSize++] = input[i] - output[i];
234    findMedianStats(array,goodSize,mean,newsigma);
235    newsigma /= correctionFactor; // correct from MADFM to sigma estimator.
236    delete [] array;
237
238    if(par.isVerbose()) std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
239
240  } while( (iteration==1) ||
241           (fabs(oldsigma-newsigma)/newsigma > reconTolerance) );
242
243  if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
244
245  delete [] xLim1,xLim2,yLim1,yLim2;
246  delete [] coeffs;
247  delete [] wavelet;
248  delete [] isGood;
249  delete [] filter;
250  delete [] sigmaFactors;
251}
Note: See TracBrowser for help on using the repository browser.