source: trunk/src/ATrous/atrous_2d_reconstruct.cc @ 201

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

Large commit. The addition of a new Statistics namespace & class, plus a number of changes to the code to make the cube-wide statistics calculation work. The FDR calculations are incorporated into the new class, and a number of functions have been made into templates to ease the calculations. Details follow:

  • New namespace and class (StatsContainer? -- templated) in Statistics.hh, that holds mean,median,stddev & madfm, and provide accessor and calculator functions for these. It also holds the threshold values for sigma-clipping and FDR methods, as well as the PValue evaluation functions
  • The correctionFactor incorporated into the namespace, and given a conversion function that other functions can call (eg. the atrous_Xd_reconstruct functions).
  • Templated the statistics functions in getStats.cc.
  • Templated the sort functions, and made swap an inline one defined in utils.hh.
  • A number of changes to cubes.cc and cubes.hh:
    • DataArray? gains a StatsContainer? object, to store stats info.
    • Image has lost its pValue array (not needed as we calculate on the fly) and mask array (not used).
    • Image has also lost all its stats members, but keeps minPix.
    • Functions to go are Image::maskObject, Image::findStats. Removed calls to the former. Latter never used.
    • Cube::setCubeStats does the cube-wide stats calculations, including setupFDR (now a Cube function).
    • Cube loses the specMean etc arrays.
  • The Search functions (ReconSearch? and CubicSearch?) changed to accommodate the exchange of StatsContainer? objects. This changed the prototypes as well.
  • The growObject function incorporates the new StatsContainer? object.
  • Minor change to Merger, in the preparation for calling growObject.
  • A new par introduced: flagUserThreshold -- set to true when the user enters a value for the threshold.
  • Removed thresholding_functions.cc and incorporated its functions into cubes.cc and cubes.hh.
File size: 7.1 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#include <Utils/Statistics.hh>
8using Statistics::madfmToSigma;
9
10using std::endl;
11using std::setw;
12
13void atrous2DReconstruct(long &xdim, long &ydim, float *&input, float *&output, Param &par)
14{
15  /**
16   *  atrous2DReconstruct(xdim, ydim, input, output, par)
17   *
18   *  A routine that uses the a trous wavelet method to reconstruct a
19   *   2-dimensional image.
20   *  The Param object "par" contains all necessary info about the filter and
21   *   reconstruction parameters, although a Filter object has to be declared
22   *   elsewhere previously.
23   *  The input array is in "input", of dimensions "xdim"x"ydim", and the
24   *   reconstructed array is in "output".
25   */
26
27  extern Filter reconFilter;
28  bool flagBlank=par.getFlagBlankPix();
29  float blankPixValue = par.getBlankPixVal();
30  long size = xdim * ydim;
31  long mindim = xdim;
32  if (ydim<mindim) mindim = ydim;
33  int numScales = reconFilter.getNumScales(mindim);
34  double *sigmaFactors = new double[numScales+1];
35  for(int i=0;i<=numScales;i++){
36    if(i<=reconFilter.maxFactor(2))
37      sigmaFactors[i] = reconFilter.sigmaFactor(2,i);
38    else sigmaFactors[i] = sigmaFactors[i-1] / 2.;
39  }
40
41  float mean,sigma,originalSigma,originalMean,oldsigma,newsigma;
42  bool *isGood = new bool[size];
43  for(int pos=0;pos<size;pos++) isGood[pos] = !par.isBlank(input[pos]);
44 
45  float *array = new float[size];
46  int goodSize=0;
47  for(int i=0;i<size;i++) if(isGood[i]) array[goodSize++] = input[i];
48  findMedianStats(array,goodSize,originalMean,originalSigma);
49  originalSigma = madfmToSigma(originalSigma);
50  delete [] array;
51 
52  float *coeffs    = new float[size];
53  float *wavelet   = new float[size];
54
55  for(int pos=0;pos<size;pos++) output[pos]=0.;
56
57  int filterwidth = reconFilter.width();
58  int filterHW = filterwidth/2;
59  double *filter = new double[filterwidth*filterwidth];
60  for(int i=0;i<filterwidth;i++){
61    for(int j=0;j<filterwidth;j++){
62      filter[i*filterwidth+j] = reconFilter.coeff(i) * reconFilter.coeff(j);
63    }
64  }
65
66  int *xLim1 = new int[ydim];
67  for(int i=0;i<ydim;i++) xLim1[i] = 0;
68  int *yLim1 = new int[xdim];
69  for(int i=0;i<xdim;i++) yLim1[i] = 0;
70  int *xLim2 = new int[ydim];
71  for(int i=0;i<ydim;i++) xLim2[i] = xdim-1;
72  int *yLim2 = new int[xdim];
73  for(int i=0;i<xdim;i++) yLim2[i] = ydim-1;
74
75  if(par.getFlagBlankPix()){
76    float avGapX = 0, avGapY = 0;
77    for(int row=0;row<ydim;row++){
78      int ct1 = 0;
79      int ct2 = xdim - 1;
80      while((ct1<ct2)&&(par.isBlank(input[row*xdim+ct1]))) ct1++;
81      while((ct2>ct1)&&(par.isBlank(input[row*xdim+ct2]))) ct2--;
82      xLim1[row] = ct1;
83      xLim2[row] = ct2;
84      avGapX += ct2 - ct1;
85    }
86    avGapX /= float(ydim);
87   
88    for(int col=0;col<xdim;col++){
89      int ct1=0;
90      int ct2=ydim-1;
91      while((ct1<ct2)&&(par.isBlank(input[col+xdim*ct1]))) ct1++;
92      while((ct2>ct1)&&(par.isBlank(input[col+xdim*ct2]))) ct2--;
93      yLim1[col] = ct1;
94      yLim2[col] = ct2;
95      avGapY += ct2 - ct1;
96    }
97    avGapY /= float(xdim);
98   
99    mindim = int(avGapX);
100    if(avGapY < avGapX) mindim = int(avGapY);
101    numScales = reconFilter.getNumScales(mindim);
102  }
103
104  float threshold;
105  int iteration=0;
106  newsigma = 1.e9;
107  for(int i=0;i<size;i++) output[i] = 0;
108  do{
109    if(par.isVerbose()) {
110      std::cout << "Iteration #"<<setw(2)<<++iteration<<":";
111      printBackSpace(13);
112    }
113
114    // first, get the value of oldsigma and set it to the previous
115    //   newsigma value
116    oldsigma = newsigma;
117    // we are transforming the residual array
118    for(int i=0;i<size;i++)  coeffs[i] = input[i] - output[i]; 
119
120    int spacing = 1;
121    for(int scale = 1; scale<numScales; scale++){
122
123      if(par.isVerbose()){
124        std::cout << "Scale ";
125        std::cout << setw(2)<<scale<<" / "<<setw(2)<<numScales;
126        printBackSpace(13);
127        std::cout <<std::flush;
128      }
129
130      for(int ypos = 0; ypos<ydim; ypos++){
131        for(int xpos = 0; xpos<xdim; xpos++){
132          // loops over each pixel in the image
133          int pos = ypos*xdim + xpos;
134         
135          wavelet[pos] = coeffs[pos];
136
137          if(!isGood[pos]) wavelet[pos] = 0.;
138          else{
139
140            int filterpos = -1;
141            for(int yoffset=-filterHW; yoffset<=filterHW; yoffset++){
142              int y = ypos + spacing*yoffset;
143              // Boundary conditions -- assume reflection at boundaries.
144              // Use limits as calculated above
145//            if(yLim1[xpos]!=yLim2[xpos]){
146//              // if these are equal we will get into an infinite loop here
147//              while((y<yLim1[xpos])||(y>yLim2[xpos])){
148//                if(y<yLim1[xpos]) y = 2*yLim1[xpos] - y;     
149//                else if(y>yLim2[xpos]) y = 2*yLim2[xpos] - y;     
150//              }
151//            }
152              int oldrow = y * xdim;
153         
154              for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
155                int x = xpos + spacing*xoffset;
156                // Boundary conditions -- assume reflection at boundaries.
157                // Use limits as calculated above
158//              if(xLim1[ypos]!=xLim2[ypos]){
159//                // if these are equal we will get into an infinite loop here
160//                while((x<xLim1[ypos])||(x>xLim2[ypos])){
161//                  if(x<xLim1[ypos]) x = 2*xLim1[ypos] - x;     
162//                  else if(x>xLim2[ypos]) x = 2*xLim2[ypos] - x;     
163//                }
164//              }
165
166                int oldpos = oldrow + x;
167
168                float oldCoeff;
169                if((y>=yLim1[xpos])&&(y<=yLim2[xpos])&&
170                   (x>=xLim1[ypos])&&(x<=xLim2[ypos])  )
171                  oldCoeff = coeffs[oldpos];
172                else oldCoeff = 0.;
173
174                filterpos++;
175
176                if(isGood[pos]) wavelet[pos] -= filter[filterpos] * oldCoeff;
177//                wavelet[pos] -= filter[filterpos] * coeffs[oldpos];
178
179              } //-> end of xoffset loop
180            } //-> end of yoffset loop
181          } //-> end of else{ ( from if(!isGood[pos])  )
182       
183        } //-> end of xpos loop
184      } //-> end of ypos loop
185
186      // Need to do this after we've done *all* the convolving
187      for(int pos=0;pos<size;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
188
189      // Have found wavelet coeffs for this scale -- now threshold   
190      if(scale>=par.getMinScale()){
191        array = new float[size];
192        goodSize=0;
193        for(int pos=0;pos<size;pos++){
194          if(isGood[pos]) array[goodSize++] = wavelet[pos];
195        }
196        findMedianStats(array,goodSize,mean,sigma);
197        delete [] array;
198
199        threshold = mean +
200          par.getAtrousCut() * originalSigma * sigmaFactors[scale];
201        for(int pos=0;pos<size;pos++){
202          if(!isGood[pos]) output[pos] = blankPixValue;
203          // preserve the Blank pixel values in the output.
204          else if( fabs(wavelet[pos]) > threshold )
205            output[pos] += wavelet[pos];
206        }
207      }
208      spacing *= 2;
209
210    } // END OF LOOP OVER SCALES
211
212    for(int pos=0;pos<size;pos++) if(isGood[pos]) output[pos] += coeffs[pos];
213
214    array = new float[size];
215    goodSize=0;
216    for(int i=0;i<size;i++){
217      if(isGood[i]) array[goodSize++] = input[i] - output[i];
218    }
219    findMedianStats(array,goodSize,mean,newsigma);
220    newsigma = madfmToSigma(newsigma);
221    delete [] array;
222   
223    if(par.isVerbose()) printBackSpace(15);
224
225  } while( (iteration==1) ||
226           (fabs(oldsigma-newsigma)/newsigma > reconTolerance) );
227
228  if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
229
230  delete [] xLim1,xLim2,yLim1,yLim2;
231  delete [] coeffs;
232  delete [] wavelet;
233  delete [] isGood;
234  delete [] filter;
235  delete [] sigmaFactors;
236}
237   
238   
Note: See TracBrowser for help on using the repository browser.