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

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

Large commit, but mostly documentation-oriented.

Only non-doc-related changes are:

  • To remove two deprecated files and any declarations of the functions in them
  • To move drawBlankEdges to the Cubes/ directory
  • Some small changes to the implementation of the StatsContainer? functions.
  • Creation of Utils/devel.hh to hide functions not used in Duchamp
  • To move the trimmedHist stats functions to their own file, again to hide them.
File size: 7.9 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   *  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   *  \param xdim The length of the x-axis.
23   *  \param ydim The length of the y-axis.
24   *  \param zdim The length of the z-axis.
25   *  \param input The input spectrum.
26   *  \param output The returned reconstructed spectrum. This array needs to be declared beforehand.
27   *  \param par The Param set.
28   */
29
30  extern Filter reconFilter;
31  long size = xdim * ydim * zdim;
32  long spatialSize = xdim * ydim;
33  long mindim = xdim;
34  if (ydim<mindim) mindim = ydim;
35  if (zdim<mindim) mindim = zdim;
36  int numScales = reconFilter.getNumScales(mindim);
37
38  double *sigmaFactors = new double[numScales+1];
39  for(int i=0;i<=numScales;i++){
40    if(i<=reconFilter.maxFactor(3))
41      sigmaFactors[i] = reconFilter.sigmaFactor(3,i);
42    else sigmaFactors[i] = sigmaFactors[i-1] / sqrt(8.);
43  }
44
45  float mean,sigma,originalSigma,originalMean,oldsigma,newsigma;
46  bool *isGood = new bool[size];
47  float blankPixValue = par.getBlankPixVal();
48  for(int pos=0;pos<size;pos++){
49    isGood[pos] = !par.isBlank(input[pos]);
50  }
51
52  float *array = new float[size];
53  int goodSize=0;
54  for(int i=0;i<size;i++) if(isGood[i]) array[goodSize++] = input[i];
55  findMedianStats(array,goodSize,originalMean,originalSigma);
56  originalSigma = madfmToSigma(originalSigma);
57  delete [] array;
58
59  float *coeffs = new float[size];
60  float *wavelet = new float[size];
61
62  for(int pos=0;pos<size;pos++) output[pos]=0.;
63
64  // Define the 3-D (separable) filter, using info from reconFilter
65  int filterwidth = reconFilter.width();
66  int filterHW = filterwidth/2;
67  int fsize = filterwidth*filterwidth*filterwidth;
68  double *filter = new double[fsize];
69  for(int i=0;i<filterwidth;i++){
70    for(int j=0;j<filterwidth;j++){
71      for(int k=0;k<filterwidth;k++){
72      filter[i +j*filterwidth + k*filterwidth*filterwidth] =
73        reconFilter.coeff(i) * reconFilter.coeff(j) * reconFilter.coeff(k);
74      }
75    }
76  }
77
78  // Locating the borders of the image -- ignoring BLANK pixels
79  //  Only do this if flagBlankPix is true.
80  //  Otherwise use the full range of x and y.
81  //  No trimming is done in the z-direction at this point.
82  int *xLim1 = new int[ydim];
83  for(int i=0;i<ydim;i++) xLim1[i] = 0;
84  int *xLim2 = new int[ydim];
85  for(int i=0;i<ydim;i++) xLim2[i] = xdim-1;
86  int *yLim1 = new int[xdim];
87  for(int i=0;i<xdim;i++) yLim1[i] = 0;
88  int *yLim2 = new int[xdim];
89  for(int i=0;i<xdim;i++) yLim2[i] = ydim-1;
90
91  if(par.getFlagBlankPix()){
92    float avGapX = 0, avGapY = 0;
93    for(int row=0;row<ydim;row++){
94      int ct1 = 0;
95      int ct2 = xdim - 1;
96      while((ct1<ct2)&&(par.isBlank(input[row*xdim+ct1]))) ct1++;
97      while((ct2>ct1)&&(par.isBlank(input[row*xdim+ct2]))) ct2--;
98      xLim1[row] = ct1;
99      xLim2[row] = ct2;
100      avGapX += ct2 - ct1 + 1;
101    }
102    avGapX /= float(ydim);
103
104    for(int col=0;col<xdim;col++){
105      int ct1=0;
106      int ct2=ydim-1;
107      while((ct1<ct2)&&(par.isBlank(input[col+xdim*ct1]))) ct1++;
108      while((ct2>ct1)&&(par.isBlank(input[col+xdim*ct2]))) ct2--;
109      yLim1[col] = ct1;
110      yLim2[col] = ct2;
111      avGapY += ct2 - ct1 + 1;
112    }
113    avGapY /= float(xdim);
114 
115    mindim = int(avGapX);
116    if(avGapY < avGapX) mindim = int(avGapY);
117    numScales = reconFilter.getNumScales(mindim);
118  }
119
120  float threshold;
121  int iteration=0;
122  newsigma = 1.e9;
123  for(int i=0;i<size;i++) output[i] = 0;
124  do{
125    if(par.isVerbose()) std::cout << "Iteration #"<<setw(2)<<++iteration<<": ";
126    // first, get the value of oldsigma, set it to the previous newsigma value
127    oldsigma = newsigma;
128    // we are transforming the residual array (input array first time around)
129    for(int i=0;i<size;i++)  coeffs[i] = input[i] - output[i];
130
131    int spacing = 1;
132    for(int scale = 1; scale<=numScales; scale++){
133
134      if(par.isVerbose()){
135        std::cout << "Scale ";
136        std::cout << setw(2)<<scale<<" / "<<setw(2)<<numScales;
137        printBackSpace(13);
138        std::cout << std::flush;
139      }
140
141      int pos = -1;
142      for(int zpos = 0; zpos<zdim; zpos++){
143        for(int ypos = 0; ypos<ydim; ypos++){
144          for(int xpos = 0; xpos<xdim; xpos++){
145            // loops over each pixel in the image
146            pos++;
147
148            wavelet[pos] = coeffs[pos];
149           
150            if(!isGood[pos] )  wavelet[pos] = 0.;
151            else{
152
153              int filterpos = -1;
154              for(int zoffset=-filterHW; zoffset<=filterHW; zoffset++){
155                int z = zpos + spacing*zoffset;
156                if(z<0) z = -z;                 // boundary conditions are
157                if(z>=zdim) z = 2*(zdim-1) - z; //    reflection.
158               
159                int oldchan = z * spatialSize;
160               
161                for(int yoffset=-filterHW; yoffset<=filterHW; yoffset++){
162                  int y = ypos + spacing*yoffset;
163
164                  // Boundary conditions -- assume reflection at boundaries.
165                  // Use limits as calculated above
166                  if(yLim1[xpos]!=yLim2[xpos]){
167                    // if these are equal we will get into an infinite loop
168                    while((y<yLim1[xpos])||(y>yLim2[xpos])){
169                      if(y<yLim1[xpos]) y = 2*yLim1[xpos] - y;     
170                      else if(y>yLim2[xpos]) y = 2*yLim2[xpos] - y;     
171                    }
172                  }
173                  int oldrow = y * xdim;
174         
175                  for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
176                    int x = xpos + spacing*xoffset;
177
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
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 = oldchan + oldrow + x;
189
190                    filterpos++;
191                   
192                    if(isGood[oldpos])
193                      wavelet[pos] -= filter[filterpos]*coeffs[oldpos];
194                     
195                  } //-> end of xoffset loop
196                } //-> end of yoffset loop
197              } //-> end of zoffset loop
198            } //-> end of else{ ( from if(!isGood[pos])  )
199           
200          } //-> end of xpos loop
201        } //-> end of ypos loop
202      } //-> end of zpos loop
203
204      // Need to do this after we've done *all* the convolving
205      for(int pos=0;pos<size;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
206
207      // Have found wavelet coeffs for this scale -- now threshold
208      if(scale>=par.getMinScale()){
209        array = new float[size];
210        goodSize=0;
211        for(int pos=0;pos<size;pos++)
212          if(isGood[pos]) array[goodSize++] = wavelet[pos];
213        findMedianStats(array,goodSize,mean,sigma);
214        delete [] array;
215       
216        threshold = mean +
217          par.getAtrousCut()*originalSigma*sigmaFactors[scale];
218        for(int pos=0;pos<size;pos++){
219          if(!isGood[pos]){
220            output[pos] = blankPixValue;
221            // this preserves the Blank pixel values in the output.
222          }
223          else if( fabs(wavelet[pos]) > threshold ){
224            output[pos] += wavelet[pos];
225            // only add to the output if the wavelet coefficient is significant
226          }
227        }
228      }
229 
230      spacing *= 2;  // double the scale of the filter.
231
232    } //-> end of scale loop
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 [] coeffs;
257  delete [] wavelet;
258  delete [] isGood;
259  delete [] filter;
260  delete [] sigmaFactors;
261}
Note: See TracBrowser for help on using the repository browser.