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

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

Largely just cleaning up #include and "using namespace" statements to prevent unnecessary declarations.

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