source: tags/release-1.0.7/src/ATrous/atrous_3d_reconstruct.cc

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

Summary:

  • Fixed the scale bar plotting for the spectral output, so that it can deal properly with very fine angular scales.
    • Improved the loop in Cube::drawScale
    • Included code in angularSeparation to deal with finely-separated positions.
  • Moved the ProgressBar? class to a new header file Utils/feedback.hh from duchamp.hh
    • Updated #include statements in many files
  • Fixed allocation bug in param copy constructor (related to offsets array).
File size: 7.8 KB
Line 
1#include <iostream>
2#include <iomanip>
3#include <math.h>
4#include <ATrous/atrous.hh>
5#include <Utils/utils.hh>
6#include <Utils/feedback.hh>
7#include <Utils/Statistics.hh>
8using Statistics::madfmToSigma;
9
10using std::endl;
11using std::setw;
12
13void atrous3DReconstruct(long &xdim, long &ydim, long &zdim, float *&input,
14                         float *&output, Param &par)
15{
16  /**
17   *  atrous3DReconstruct(xdim, ydim, zdim, input, output, par)
18   *
19   *  A routine that uses the a trous wavelet method to reconstruct a
20   *   3-dimensional image cube.
21   *  The Param object "par" contains all necessary info about the filter and
22   *   reconstruction parameters, although a Filter object has to be declared
23   *   elsewhere previously.
24   *  The input array is in "input", of dimensions "xdim"x"ydim"x"zdim", and
25   *   the reconstructed array is in "output".
26   */
27
28  extern Filter reconFilter;
29  long size = xdim * ydim * zdim;
30  long spatialSize = xdim * ydim;
31  long mindim = xdim;
32  if (ydim<mindim) mindim = ydim;
33  if (zdim<mindim) mindim = zdim;
34  int numScales = reconFilter.getNumScales(mindim);
35
36  double *sigmaFactors = new double[numScales+1];
37  for(int i=0;i<=numScales;i++){
38    if(i<=reconFilter.maxFactor(3))
39      sigmaFactors[i] = reconFilter.sigmaFactor(3,i);
40    else sigmaFactors[i] = sigmaFactors[i-1] / sqrt(8.);
41  }
42
43  float mean,sigma,originalSigma,originalMean,oldsigma,newsigma;
44  bool *isGood = new bool[size];
45  float blankPixValue = par.getBlankPixVal();
46  for(int pos=0;pos<size;pos++){
47    isGood[pos] = !par.isBlank(input[pos]);
48  }
49
50  float *array = new float[size];
51  int goodSize=0;
52  for(int i=0;i<size;i++) if(isGood[i]) array[goodSize++] = input[i];
53  findMedianStats(array,goodSize,originalMean,originalSigma);
54  originalSigma = madfmToSigma(originalSigma);
55  delete [] array;
56
57  float *coeffs = new float[size];
58  float *wavelet = new float[size];
59
60  for(int pos=0;pos<size;pos++) output[pos]=0.;
61
62  // Define the 3-D (separable) filter, using info from reconFilter
63  int filterwidth = reconFilter.width();
64  int filterHW = filterwidth/2;
65  int fsize = filterwidth*filterwidth*filterwidth;
66  double *filter = new double[fsize];
67  for(int i=0;i<filterwidth;i++){
68    for(int j=0;j<filterwidth;j++){
69      for(int k=0;k<filterwidth;k++){
70      filter[i +j*filterwidth + k*filterwidth*filterwidth] =
71        reconFilter.coeff(i) * reconFilter.coeff(j) * reconFilter.coeff(k);
72      }
73    }
74  }
75
76  // Locating the borders of the image -- ignoring BLANK pixels
77  //  Only do this if flagBlankPix is true.
78  //  Otherwise use the full range of x and y.
79  //  No trimming is done in the z-direction at this point.
80  int *xLim1 = new int[ydim];
81  for(int i=0;i<ydim;i++) xLim1[i] = 0;
82  int *xLim2 = new int[ydim];
83  for(int i=0;i<ydim;i++) xLim2[i] = xdim-1;
84  int *yLim1 = new int[xdim];
85  for(int i=0;i<xdim;i++) yLim1[i] = 0;
86  int *yLim2 = new int[xdim];
87  for(int i=0;i<xdim;i++) yLim2[i] = ydim-1;
88
89  if(par.getFlagBlankPix()){
90    float avGapX = 0, avGapY = 0;
91    for(int row=0;row<ydim;row++){
92      int ct1 = 0;
93      int ct2 = xdim - 1;
94      while((ct1<ct2)&&(par.isBlank(input[row*xdim+ct1]))) ct1++;
95      while((ct2>ct1)&&(par.isBlank(input[row*xdim+ct2]))) ct2--;
96      xLim1[row] = ct1;
97      xLim2[row] = ct2;
98      avGapX += ct2 - ct1 + 1;
99    }
100    avGapX /= float(ydim);
101
102    for(int col=0;col<xdim;col++){
103      int ct1=0;
104      int ct2=ydim-1;
105      while((ct1<ct2)&&(par.isBlank(input[col+xdim*ct1]))) ct1++;
106      while((ct2>ct1)&&(par.isBlank(input[col+xdim*ct2]))) ct2--;
107      yLim1[col] = ct1;
108      yLim2[col] = ct2;
109      avGapY += ct2 - ct1 + 1;
110    }
111    avGapY /= float(xdim);
112 
113    mindim = int(avGapX);
114    if(avGapY < avGapX) mindim = int(avGapY);
115    numScales = reconFilter.getNumScales(mindim);
116  }
117
118  float threshold;
119  int iteration=0;
120  newsigma = 1.e9;
121  for(int i=0;i<size;i++) output[i] = 0;
122  do{
123    if(par.isVerbose()) std::cout << "Iteration #"<<setw(2)<<++iteration<<": ";
124    // first, get the value of oldsigma, set it to the previous newsigma value
125    oldsigma = newsigma;
126    // we are transforming the residual array (input array first time around)
127    for(int i=0;i<size;i++)  coeffs[i] = input[i] - output[i];
128
129    int spacing = 1;
130    for(int scale = 1; scale<=numScales; scale++){
131
132      if(par.isVerbose()){
133        std::cout << "Scale ";
134        std::cout << setw(2)<<scale<<" / "<<setw(2)<<numScales;
135        printBackSpace(13);
136        std::cout << std::flush;
137      }
138
139      int pos = -1;
140      for(int zpos = 0; zpos<zdim; zpos++){
141        for(int ypos = 0; ypos<ydim; ypos++){
142          for(int xpos = 0; xpos<xdim; xpos++){
143            // loops over each pixel in the image
144            pos++;
145
146            wavelet[pos] = coeffs[pos];
147           
148            if(!isGood[pos] )  wavelet[pos] = 0.;
149            else{
150
151              int filterpos = -1;
152              for(int zoffset=-filterHW; zoffset<=filterHW; zoffset++){
153                int z = zpos + spacing*zoffset;
154                if(z<0) z = -z;                 // boundary conditions are
155                if(z>=zdim) z = 2*(zdim-1) - z; //    reflection.
156               
157                int oldchan = z * spatialSize;
158               
159                for(int yoffset=-filterHW; yoffset<=filterHW; yoffset++){
160                  int y = ypos + spacing*yoffset;
161
162                  // Boundary conditions -- assume reflection at boundaries.
163                  // Use limits as calculated above
164                  if(yLim1[xpos]!=yLim2[xpos]){
165                    // if these are equal we will get into an infinite loop
166                    while((y<yLim1[xpos])||(y>yLim2[xpos])){
167                      if(y<yLim1[xpos]) y = 2*yLim1[xpos] - y;     
168                      else if(y>yLim2[xpos]) y = 2*yLim2[xpos] - y;     
169                    }
170                  }
171                  int oldrow = y * xdim;
172         
173                  for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
174                    int x = xpos + spacing*xoffset;
175
176                    // Boundary conditions -- assume reflection at boundaries.
177                    // Use limits as calculated above
178                    if(xLim1[ypos]!=xLim2[ypos]){
179                      // if these are equal we will get into an infinite loop
180                      while((x<xLim1[ypos])||(x>xLim2[ypos])){
181                        if(x<xLim1[ypos]) x = 2*xLim1[ypos] - x;     
182                        else if(x>xLim2[ypos]) x = 2*xLim2[ypos] - x;     
183                      }
184                    }
185
186                    int oldpos = oldchan + oldrow + x;
187
188                    filterpos++;
189                   
190                    if(isGood[oldpos])
191                      wavelet[pos] -= filter[filterpos]*coeffs[oldpos];
192                     
193                  } //-> end of xoffset loop
194                } //-> end of yoffset loop
195              } //-> end of zoffset loop
196            } //-> end of else{ ( from if(!isGood[pos])  )
197           
198          } //-> end of xpos loop
199        } //-> end of ypos loop
200      } //-> end of zpos loop
201
202      // Need to do this after we've done *all* the convolving
203      for(int pos=0;pos<size;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
204
205      // Have found wavelet coeffs for this scale -- now threshold
206      if(scale>=par.getMinScale()){
207        array = new float[size];
208        goodSize=0;
209        for(int pos=0;pos<size;pos++)
210          if(isGood[pos]) array[goodSize++] = wavelet[pos];
211        findMedianStats(array,goodSize,mean,sigma);
212        delete [] array;
213       
214        threshold = mean +
215          par.getAtrousCut()*originalSigma*sigmaFactors[scale];
216        for(int pos=0;pos<size;pos++){
217          if(!isGood[pos]){
218            output[pos] = blankPixValue;
219            // this preserves the Blank pixel values in the output.
220          }
221          else if( fabs(wavelet[pos]) > threshold ){
222            output[pos] += wavelet[pos];
223            // only add to the output if the wavelet coefficient is significant
224          }
225        }
226      }
227 
228      spacing *= 2;  // double the scale of the filter.
229
230    } //-> end of scale loop
231
232    for(int pos=0;pos<size;pos++) if(isGood[pos]) output[pos] += coeffs[pos];
233
234    array = new float[size];
235    goodSize=0;
236    for(int i=0;i<size;i++) {
237      if(isGood[i]) array[goodSize++] = input[i] - output[i];
238    }
239    findMedianStats(array,goodSize,mean,newsigma);
240    newsigma = madfmToSigma(newsigma);
241    delete [] array;
242
243    if(par.isVerbose()) printBackSpace(15);
244
245  } while( (iteration==1) ||
246           (fabs(oldsigma-newsigma)/newsigma > reconTolerance) );
247
248  if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
249
250  delete [] xLim1;
251  delete [] xLim2;
252  delete [] yLim1;
253  delete [] yLim2;
254  delete [] coeffs;
255  delete [] wavelet;
256  delete [] isGood;
257  delete [] filter;
258  delete [] sigmaFactors;
259}
Note: See TracBrowser for help on using the repository browser.