source: branches/pixel-map-branch/src/ATrous/atrous_2d_reconstruct.cc

Last change on this file was 232, checked in by Matthew Whiting, 17 years ago

Large raft of changes. Most are minor ones related to fixing up the use of std::string and std::vector (whether they are declared as using, or not...). Other changes include:

  • Moving the reconstruction filter class Filter into its own header/implementation files filter.{hh,cc}. As a result, the atrous.cc file is removed, but atrous.hh remains with just the function prototypes.
  • Incorporating a Filter object into the Param set, so that the reconstruction routines can see it without the messy "extern" call. The define() function is now called in both the Param() and Param::readParams() functions, and no longer in the main body.
  • Col functions in columns.cc moved into the Column namespace, while the template function printEntry is moved into the columns.hh file -- it would not compile on delphinus with it in the columns.cc, even though all the implementations were present.
  • Improved the introductory section of the Guide, with a bit more detail about each of the execution steps. This way the reader can read this section and have a reasonably good idea about what is happening.
  • Other minor changes to the Guide.
File size: 8.0 KB
Line 
1#include <iostream>
2#include <iomanip>
3#include <math.h>
4#include <duchamp.hh>
5#include <ATrous/atrous.hh>
6#include <ATrous/filter.hh>
7#include <Utils/utils.hh>
8#include <Utils/feedback.hh>
9#include <Utils/Statistics.hh>
10using Statistics::madfmToSigma;
11
12using std::endl;
13using std::setw;
14
15void atrous2DReconstruct(long &xdim, long &ydim, float *&input, float *&output, Param &par)
16{
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.
22   *
23   *  If there are no non-BLANK pixels (and we are testing for
24   *  BLANKs), the reconstruction cannot be done, so we return the
25   *  input array as the output array and give a warning message.
26   *
27   *  \param xdim The length of the x-axis of the image.
28   *  \param ydim The length of the y-axis of the image.
29   *  \param input The input spectrum.
30   *  \param output The returned reconstructed spectrum. This array needs to be declared beforehand.
31   *  \param par The Param set.
32   */
33
34  bool flagBlank=par.getFlagBlankPix();
35  float blankPixValue = par.getBlankPixVal();
36  long size = xdim * ydim;
37  long mindim = xdim;
38  if (ydim<mindim) mindim = ydim;
39  int numScales = par.filter().getNumScales(mindim);
40  double *sigmaFactors = new double[numScales+1];
41  for(int i=0;i<=numScales;i++){
42    if(i<=par.filter().maxFactor(2))
43      sigmaFactors[i] = par.filter().sigmaFactor(2,i);
44    else sigmaFactors[i] = sigmaFactors[i-1] / 2.;
45  }
46
47  float mean,sigma,originalSigma,originalMean,oldsigma,newsigma;
48  int goodSize=0;
49  bool *isGood = new bool[size];
50  for(int pos=0;pos<size;pos++){
51    isGood[pos] = !par.isBlank(input[pos]);
52    if(isGood[pos]) goodSize++;
53  }
54
55  if(goodSize == 0){
56    // There are no good pixels -- everything is BLANK for some reason.
57    // Return the input array as the output, and give a warning message.
58
59    for(int pos=0;pos<size; pos++) output[pos] = input[pos];
60
61    duchampWarning("atrous2DReconstruct",
62                   "There are no good pixels to be reconstructed -- all are BLANK.\nPerhaps you need to try this with flagBlankPix=false.\nReturning input array.\n");
63  }
64  else{
65    // Otherwise, all is good, and we continue.
66
67    float *array = new float[size];
68    goodSize=0;
69    for(int i=0;i<size;i++) if(isGood[i]) array[goodSize++] = input[i];
70    findMedianStats(array,goodSize,originalMean,originalSigma);
71    originalSigma = madfmToSigma(originalSigma);
72    delete [] array;
73 
74    float *coeffs    = new float[size];
75    float *wavelet   = new float[size];
76
77    for(int pos=0;pos<size;pos++) output[pos]=0.;
78
79    int filterwidth = par.filter().width();
80    int filterHW = filterwidth/2;
81    double *filter = new double[filterwidth*filterwidth];
82    for(int i=0;i<filterwidth;i++){
83      for(int j=0;j<filterwidth;j++){
84        filter[i*filterwidth+j] = par.filter().coeff(i) * par.filter().coeff(j);
85      }
86    }
87
88    int *xLim1 = new int[ydim];
89    for(int i=0;i<ydim;i++) xLim1[i] = 0;
90    int *yLim1 = new int[xdim];
91    for(int i=0;i<xdim;i++) yLim1[i] = 0;
92    int *xLim2 = new int[ydim];
93    for(int i=0;i<ydim;i++) xLim2[i] = xdim-1;
94    int *yLim2 = new int[xdim];
95    for(int i=0;i<xdim;i++) yLim2[i] = ydim-1;
96
97    if(par.getFlagBlankPix()){
98      float avGapX = 0, avGapY = 0;
99      for(int row=0;row<ydim;row++){
100        int ct1 = 0;
101        int ct2 = xdim - 1;
102        while((ct1<ct2)&&(par.isBlank(input[row*xdim+ct1]))) ct1++;
103        while((ct2>ct1)&&(par.isBlank(input[row*xdim+ct2]))) ct2--;
104        xLim1[row] = ct1;
105        xLim2[row] = ct2;
106        avGapX += ct2 - ct1;
107      }
108      avGapX /= float(ydim);
109   
110      for(int col=0;col<xdim;col++){
111        int ct1=0;
112        int ct2=ydim-1;
113        while((ct1<ct2)&&(par.isBlank(input[col+xdim*ct1]))) ct1++;
114        while((ct2>ct1)&&(par.isBlank(input[col+xdim*ct2]))) ct2--;
115        yLim1[col] = ct1;
116        yLim2[col] = ct2;
117        avGapY += ct2 - ct1;
118      }
119      avGapY /= float(xdim);
120   
121      mindim = int(avGapX);
122      if(avGapY < avGapX) mindim = int(avGapY);
123      numScales = par.filter().getNumScales(mindim);
124    }
125
126    float threshold;
127    int iteration=0;
128    newsigma = 1.e9;
129    for(int i=0;i<size;i++) output[i] = 0;
130    do{
131      if(par.isVerbose()) {
132        std::cout << "Iteration #"<<setw(2)<<++iteration<<":";
133        printBackSpace(13);
134      }
135
136      // first, get the value of oldsigma and set it to the previous
137      //   newsigma value
138      oldsigma = newsigma;
139      // we are transforming the residual array
140      for(int i=0;i<size;i++)  coeffs[i] = input[i] - output[i]; 
141
142      int spacing = 1;
143      for(int scale = 1; scale<numScales; scale++){
144
145        if(par.isVerbose()){
146          std::cout << "Scale ";
147          std::cout << setw(2)<<scale<<" / "<<setw(2)<<numScales;
148          printBackSpace(13);
149          std::cout <<std::flush;
150        }
151
152        for(int ypos = 0; ypos<ydim; ypos++){
153          for(int xpos = 0; xpos<xdim; xpos++){
154            // loops over each pixel in the image
155            int pos = ypos*xdim + xpos;
156         
157            wavelet[pos] = coeffs[pos];
158
159            if(!isGood[pos]) wavelet[pos] = 0.;
160            else{
161
162              int filterpos = -1;
163              for(int yoffset=-filterHW; yoffset<=filterHW; yoffset++){
164                int y = ypos + spacing*yoffset;
165                // Boundary conditions -- assume reflection at boundaries.
166                // Use limits as calculated above
167                //            if(yLim1[xpos]!=yLim2[xpos]){
168                //              // if these are equal we will get into an infinite loop here
169                //              while((y<yLim1[xpos])||(y>yLim2[xpos])){
170                //                if(y<yLim1[xpos]) y = 2*yLim1[xpos] - y;     
171                //                else if(y>yLim2[xpos]) y = 2*yLim2[xpos] - y;     
172                //              }
173                //            }
174                int oldrow = y * xdim;
175         
176                for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
177                  int x = xpos + spacing*xoffset;
178                  // Boundary conditions -- assume reflection at boundaries.
179                  // Use limits as calculated above
180                  //            if(xLim1[ypos]!=xLim2[ypos]){
181                  //              // if these are equal we will get into an infinite loop here
182                  //              while((x<xLim1[ypos])||(x>xLim2[ypos])){
183                  //                if(x<xLim1[ypos]) x = 2*xLim1[ypos] - x;     
184                  //                else if(x>xLim2[ypos]) x = 2*xLim2[ypos] - x;     
185                  //              }
186                  //            }
187
188                  int oldpos = oldrow + x;
189
190                  float oldCoeff;
191                  if((y>=yLim1[xpos])&&(y<=yLim2[xpos])&&
192                     (x>=xLim1[ypos])&&(x<=xLim2[ypos])  )
193                    oldCoeff = coeffs[oldpos];
194                  else oldCoeff = 0.;
195
196                  filterpos++;
197
198                  if(isGood[pos]) wavelet[pos] -= filter[filterpos] * oldCoeff;
199                  //              wavelet[pos] -= filter[filterpos] * coeffs[oldpos];
200
201                } //-> end of xoffset loop
202              } //-> end of yoffset loop
203            } //-> end of else{ ( from if(!isGood[pos])  )
204       
205          } //-> end of xpos loop
206        } //-> end of ypos loop
207
208        // Need to do this after we've done *all* the convolving
209        for(int pos=0;pos<size;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
210
211        // Have found wavelet coeffs for this scale -- now threshold   
212        if(scale>=par.getMinScale()){
213          array = new float[size];
214          goodSize=0;
215          for(int pos=0;pos<size;pos++){
216            if(isGood[pos]) array[goodSize++] = wavelet[pos];
217          }
218          findMedianStats(array,goodSize,mean,sigma);
219          delete [] array;
220
221          threshold = mean +
222            par.getAtrousCut() * originalSigma * sigmaFactors[scale];
223          for(int pos=0;pos<size;pos++){
224            if(!isGood[pos]) output[pos] = blankPixValue;
225            // preserve the Blank pixel values in the output.
226            else if( fabs(wavelet[pos]) > threshold )
227              output[pos] += wavelet[pos];
228          }
229        }
230        spacing *= 2;
231
232      } // END OF LOOP OVER SCALES
233
234      for(int pos=0;pos<size;pos++) if(isGood[pos]) output[pos] += coeffs[pos];
235
236      array = new float[size];
237      goodSize=0;
238      for(int i=0;i<size;i++){
239        if(isGood[i]) array[goodSize++] = input[i] - output[i];
240      }
241      findMedianStats(array,goodSize,mean,newsigma);
242      newsigma = madfmToSigma(newsigma);
243      delete [] array;
244   
245      if(par.isVerbose()) printBackSpace(15);
246
247    } while( (iteration==1) ||
248             (fabs(oldsigma-newsigma)/newsigma > reconTolerance) );
249
250    if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
251
252    delete [] xLim1;
253    delete [] xLim2;
254    delete [] yLim1;
255    delete [] yLim2;
256    delete [] filter;
257    delete [] coeffs;
258    delete [] wavelet;
259
260  }
261
262  delete [] isGood;
263  delete [] sigmaFactors;
264}
265   
266   
Note: See TracBrowser for help on using the repository browser.