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

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

Mostly improvements to the Guide, with better formatting and descriptions of one of the changes below. The changes to the code are:

  • Addition of the option of specifying in the subsection string a number of pixels to be chopped from either end of an axis (as requested in #5).
  • Addition of a test in the reconstruction functions to see whether the number of non-BLANK pixels is zero. If so, the input array is returned as the output without having to do the reconstruction (and avoiding problems with the stats functions).
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 <Utils/utils.hh>
7#include <Utils/feedback.hh>
8#include <Utils/Statistics.hh>
9using Statistics::madfmToSigma;
10
11using std::endl;
12using std::setw;
13
14void atrous2DReconstruct(long &xdim, long &ydim, float *&input, float *&output, Param &par)
15{
16  /**
17   *  A routine that uses the a trous wavelet method to reconstruct a
18   *   2-dimensional image.
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   *
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  extern Filter reconFilter;
35  bool flagBlank=par.getFlagBlankPix();
36  float blankPixValue = par.getBlankPixVal();
37  long size = xdim * ydim;
38  long mindim = xdim;
39  if (ydim<mindim) mindim = ydim;
40  int numScales = reconFilter.getNumScales(mindim);
41  double *sigmaFactors = new double[numScales+1];
42  for(int i=0;i<=numScales;i++){
43    if(i<=reconFilter.maxFactor(2))
44      sigmaFactors[i] = reconFilter.sigmaFactor(2,i);
45    else sigmaFactors[i] = sigmaFactors[i-1] / 2.;
46  }
47
48  float mean,sigma,originalSigma,originalMean,oldsigma,newsigma;
49  int goodSize=0;
50  bool *isGood = new bool[size];
51  for(int pos=0;pos<size;pos++){
52    isGood[pos] = !par.isBlank(input[pos]);
53    if(isGood[pos]) goodSize++;
54  }
55
56  if(goodSize == 0){
57    // There are no good pixels -- everything is BLANK for some reason.
58    // Return the input array as the output, and give a warning message.
59
60    for(int pos=0;pos<size; pos++) output[pos] = input[pos];
61
62    duchampWarning("atrous2DReconstruct",
63                   "There are no good pixels to be reconstructed -- all are BLANK.\nPerhaps you need to try this with flagBlankPix=false.\nReturning input array.\n");
64  }
65  else{
66    // Otherwise, all is good, and we continue.
67
68    float *array = new float[size];
69    goodSize=0;
70    for(int i=0;i<size;i++) if(isGood[i]) array[goodSize++] = input[i];
71    findMedianStats(array,goodSize,originalMean,originalSigma);
72    originalSigma = madfmToSigma(originalSigma);
73    delete [] array;
74 
75    float *coeffs    = new float[size];
76    float *wavelet   = new float[size];
77
78    for(int pos=0;pos<size;pos++) output[pos]=0.;
79
80    int filterwidth = reconFilter.width();
81    int filterHW = filterwidth/2;
82    double *filter = new double[filterwidth*filterwidth];
83    for(int i=0;i<filterwidth;i++){
84      for(int j=0;j<filterwidth;j++){
85        filter[i*filterwidth+j] = reconFilter.coeff(i) * reconFilter.coeff(j);
86      }
87    }
88
89    int *xLim1 = new int[ydim];
90    for(int i=0;i<ydim;i++) xLim1[i] = 0;
91    int *yLim1 = new int[xdim];
92    for(int i=0;i<xdim;i++) yLim1[i] = 0;
93    int *xLim2 = new int[ydim];
94    for(int i=0;i<ydim;i++) xLim2[i] = xdim-1;
95    int *yLim2 = new int[xdim];
96    for(int i=0;i<xdim;i++) yLim2[i] = ydim-1;
97
98    if(par.getFlagBlankPix()){
99      float avGapX = 0, avGapY = 0;
100      for(int row=0;row<ydim;row++){
101        int ct1 = 0;
102        int ct2 = xdim - 1;
103        while((ct1<ct2)&&(par.isBlank(input[row*xdim+ct1]))) ct1++;
104        while((ct2>ct1)&&(par.isBlank(input[row*xdim+ct2]))) ct2--;
105        xLim1[row] = ct1;
106        xLim2[row] = ct2;
107        avGapX += ct2 - ct1;
108      }
109      avGapX /= float(ydim);
110   
111      for(int col=0;col<xdim;col++){
112        int ct1=0;
113        int ct2=ydim-1;
114        while((ct1<ct2)&&(par.isBlank(input[col+xdim*ct1]))) ct1++;
115        while((ct2>ct1)&&(par.isBlank(input[col+xdim*ct2]))) ct2--;
116        yLim1[col] = ct1;
117        yLim2[col] = ct2;
118        avGapY += ct2 - ct1;
119      }
120      avGapY /= float(xdim);
121   
122      mindim = int(avGapX);
123      if(avGapY < avGapX) mindim = int(avGapY);
124      numScales = reconFilter.getNumScales(mindim);
125    }
126
127    float threshold;
128    int iteration=0;
129    newsigma = 1.e9;
130    for(int i=0;i<size;i++) output[i] = 0;
131    do{
132      if(par.isVerbose()) {
133        std::cout << "Iteration #"<<setw(2)<<++iteration<<":";
134        printBackSpace(13);
135      }
136
137      // first, get the value of oldsigma and set it to the previous
138      //   newsigma value
139      oldsigma = newsigma;
140      // we are transforming the residual array
141      for(int i=0;i<size;i++)  coeffs[i] = input[i] - output[i]; 
142
143      int spacing = 1;
144      for(int scale = 1; scale<numScales; scale++){
145
146        if(par.isVerbose()){
147          std::cout << "Scale ";
148          std::cout << setw(2)<<scale<<" / "<<setw(2)<<numScales;
149          printBackSpace(13);
150          std::cout <<std::flush;
151        }
152
153        for(int ypos = 0; ypos<ydim; ypos++){
154          for(int xpos = 0; xpos<xdim; xpos++){
155            // loops over each pixel in the image
156            int pos = ypos*xdim + xpos;
157         
158            wavelet[pos] = coeffs[pos];
159
160            if(!isGood[pos]) wavelet[pos] = 0.;
161            else{
162
163              int filterpos = -1;
164              for(int yoffset=-filterHW; yoffset<=filterHW; yoffset++){
165                int y = ypos + spacing*yoffset;
166                // Boundary conditions -- assume reflection at boundaries.
167                // Use limits as calculated above
168                //            if(yLim1[xpos]!=yLim2[xpos]){
169                //              // if these are equal we will get into an infinite loop here
170                //              while((y<yLim1[xpos])||(y>yLim2[xpos])){
171                //                if(y<yLim1[xpos]) y = 2*yLim1[xpos] - y;     
172                //                else if(y>yLim2[xpos]) y = 2*yLim2[xpos] - y;     
173                //              }
174                //            }
175                int oldrow = y * xdim;
176         
177                for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
178                  int x = xpos + spacing*xoffset;
179                  // Boundary conditions -- assume reflection at boundaries.
180                  // Use limits as calculated above
181                  //            if(xLim1[ypos]!=xLim2[ypos]){
182                  //              // if these are equal we will get into an infinite loop here
183                  //              while((x<xLim1[ypos])||(x>xLim2[ypos])){
184                  //                if(x<xLim1[ypos]) x = 2*xLim1[ypos] - x;     
185                  //                else if(x>xLim2[ypos]) x = 2*xLim2[ypos] - x;     
186                  //              }
187                  //            }
188
189                  int oldpos = oldrow + x;
190
191                  float oldCoeff;
192                  if((y>=yLim1[xpos])&&(y<=yLim2[xpos])&&
193                     (x>=xLim1[ypos])&&(x<=xLim2[ypos])  )
194                    oldCoeff = coeffs[oldpos];
195                  else oldCoeff = 0.;
196
197                  filterpos++;
198
199                  if(isGood[pos]) wavelet[pos] -= filter[filterpos] * oldCoeff;
200                  //              wavelet[pos] -= filter[filterpos] * coeffs[oldpos];
201
202                } //-> end of xoffset loop
203              } //-> end of yoffset loop
204            } //-> end of else{ ( from if(!isGood[pos])  )
205       
206          } //-> end of xpos loop
207        } //-> end of ypos loop
208
209        // Need to do this after we've done *all* the convolving
210        for(int pos=0;pos<size;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
211
212        // Have found wavelet coeffs for this scale -- now threshold   
213        if(scale>=par.getMinScale()){
214          array = new float[size];
215          goodSize=0;
216          for(int pos=0;pos<size;pos++){
217            if(isGood[pos]) array[goodSize++] = wavelet[pos];
218          }
219          findMedianStats(array,goodSize,mean,sigma);
220          delete [] array;
221
222          threshold = mean +
223            par.getAtrousCut() * originalSigma * sigmaFactors[scale];
224          for(int pos=0;pos<size;pos++){
225            if(!isGood[pos]) output[pos] = blankPixValue;
226            // preserve the Blank pixel values in the output.
227            else if( fabs(wavelet[pos]) > threshold )
228              output[pos] += wavelet[pos];
229          }
230        }
231        spacing *= 2;
232
233      } // END OF LOOP OVER SCALES
234
235      for(int pos=0;pos<size;pos++) if(isGood[pos]) output[pos] += coeffs[pos];
236
237      array = new float[size];
238      goodSize=0;
239      for(int i=0;i<size;i++){
240        if(isGood[i]) array[goodSize++] = input[i] - output[i];
241      }
242      findMedianStats(array,goodSize,mean,newsigma);
243      newsigma = madfmToSigma(newsigma);
244      delete [] array;
245   
246      if(par.isVerbose()) printBackSpace(15);
247
248    } while( (iteration==1) ||
249             (fabs(oldsigma-newsigma)/newsigma > reconTolerance) );
250
251    if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
252
253    delete [] xLim1;
254    delete [] xLim2;
255    delete [] yLim1;
256    delete [] yLim2;
257    delete [] filter;
258    delete [] coeffs;
259    delete [] wavelet;
260
261  }
262
263  delete [] isGood;
264  delete [] sigmaFactors;
265}
266   
267   
Note: See TracBrowser for help on using the repository browser.