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

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

Introduced some simple inline functions to duchamp.hh to make the printing of progress bars simpler and of a more unified fashion.

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