source: tags/release-1.1.2/src/ATrous/atrous_2d_reconstruct.cc @ 1441

Last change on this file since 1441 was 393, checked in by MatthewWhiting, 17 years ago

Fixed up headers for trunk as well.

File size: 9.4 KB
Line 
1// -----------------------------------------------------------------------
2// atrous_2d_reconstruct.cc: 2-dimensional wavelet reconstruction.
3// -----------------------------------------------------------------------
4// Copyright (C) 2006, Matthew Whiting, ATNF
5//
6// This program is free software; you can redistribute it and/or modify it
7// under the terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 2 of the License, or (at your
9// option) any later version.
10//
11// Duchamp is distributed in the hope that it will be useful, but WITHOUT
12// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14// for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with Duchamp; if not, write to the Free Software Foundation,
18// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
19//
20// Correspondence concerning Duchamp may be directed to:
21//    Internet email: Matthew.Whiting [at] atnf.csiro.au
22//    Postal address: Dr. Matthew Whiting
23//                    Australia Telescope National Facility, CSIRO
24//                    PO Box 76
25//                    Epping NSW 1710
26//                    AUSTRALIA
27// -----------------------------------------------------------------------
28#include <iostream>
29#include <iomanip>
30#include <math.h>
31#include <duchamp/duchamp.hh>
32#include <duchamp/param.hh>
33#include <duchamp/ATrous/atrous.hh>
34#include <duchamp/ATrous/filter.hh>
35#include <duchamp/Utils/utils.hh>
36#include <duchamp/Utils/feedback.hh>
37#include <duchamp/Utils/Statistics.hh>
38using Statistics::madfmToSigma;
39
40namespace duchamp
41{
42
43  void atrous2DReconstruct(long &xdim, long &ydim, float *&input, float *&output, Param &par)
44  {
45    /**
46     *  A routine that uses the a trous wavelet method to reconstruct a
47     *   2-dimensional image.
48     *
49     *  If there are no non-BLANK pixels (and we are testing for
50     *  BLANKs), the reconstruction cannot be done, so we return the
51     *  input array as the output array and give a warning message.
52     *
53     *  \param xdim The length of the x-axis of the image.
54     *  \param ydim The length of the y-axis of the image.
55     *  \param input The input spectrum.
56     *  \param output The returned reconstructed spectrum. This array
57     *  needs to be declared beforehand.
58     *  \param par The Param set:contains all necessary info about the
59     *  filter and reconstruction parameters.
60     */
61
62    long size = xdim * ydim;
63    long mindim = xdim;
64    if (ydim<mindim) mindim = ydim;
65    int numScales = par.filter().getNumScales(mindim);
66    double *sigmaFactors = new double[numScales+1];
67    for(int i=0;i<=numScales;i++){
68      if(i<=par.filter().maxFactor(2))
69        sigmaFactors[i] = par.filter().sigmaFactor(2,i);
70      else sigmaFactors[i] = sigmaFactors[i-1] / 2.;
71    }
72
73    float mean,sigma,originalSigma,originalMean,oldsigma,newsigma;
74    int goodSize=0;
75    bool *isGood = new bool[size];
76    for(int pos=0;pos<size;pos++){
77      isGood[pos] = !par.isBlank(input[pos]);
78      if(isGood[pos]) goodSize++;
79    }
80
81    if(goodSize == 0){
82      // There are no good pixels -- everything is BLANK for some reason.
83      // Return the input array as the output, and give a warning message.
84
85      for(int pos=0;pos<size; pos++) output[pos] = input[pos];
86
87      duchampWarning("2D Reconstruction","\
88There are no good pixels to be reconstructed -- all are BLANK.\n\
89Returning input array.\n");
90    }
91    else{
92      // Otherwise, all is good, and we continue.
93
94      float *array = new float[size];
95      goodSize=0;
96      for(int i=0;i<size;i++) if(isGood[i]) array[goodSize++] = input[i];
97      findMedianStats(array,goodSize,originalMean,originalSigma);
98      originalSigma = madfmToSigma(originalSigma);
99      delete [] array;
100 
101      float *coeffs    = new float[size];
102      float *wavelet   = new float[size];
103
104      for(int pos=0;pos<size;pos++) output[pos]=0.;
105
106      int filterwidth = par.filter().width();
107      int filterHW = filterwidth/2;
108      double *filter = new double[filterwidth*filterwidth];
109      for(int i=0;i<filterwidth;i++){
110        for(int j=0;j<filterwidth;j++){
111          filter[i*filterwidth+j] = par.filter().coeff(i) * par.filter().coeff(j);
112        }
113      }
114
115      int *xLim1 = new int[ydim];
116      for(int i=0;i<ydim;i++) xLim1[i] = 0;
117      int *yLim1 = new int[xdim];
118      for(int i=0;i<xdim;i++) yLim1[i] = 0;
119      int *xLim2 = new int[ydim];
120      for(int i=0;i<ydim;i++) xLim2[i] = xdim-1;
121      int *yLim2 = new int[xdim];
122      for(int i=0;i<xdim;i++) yLim2[i] = ydim-1;
123
124      if(par.getFlagBlankPix()){
125        float avGapX = 0, avGapY = 0;
126        for(int row=0;row<ydim;row++){
127          int ct1 = 0;
128          int ct2 = xdim - 1;
129          while((ct1<ct2)&&(par.isBlank(input[row*xdim+ct1]))) ct1++;
130          while((ct2>ct1)&&(par.isBlank(input[row*xdim+ct2]))) ct2--;
131          xLim1[row] = ct1;
132          xLim2[row] = ct2;
133          avGapX += ct2 - ct1;
134        }
135        avGapX /= float(ydim);
136   
137        for(int col=0;col<xdim;col++){
138          int ct1=0;
139          int ct2=ydim-1;
140          while((ct1<ct2)&&(par.isBlank(input[col+xdim*ct1]))) ct1++;
141          while((ct2>ct1)&&(par.isBlank(input[col+xdim*ct2]))) ct2--;
142          yLim1[col] = ct1;
143          yLim2[col] = ct2;
144          avGapY += ct2 - ct1;
145        }
146        avGapY /= float(xdim);
147   
148        mindim = int(avGapX);
149        if(avGapY < avGapX) mindim = int(avGapY);
150        numScales = par.filter().getNumScales(mindim);
151      }
152
153      float threshold;
154      int iteration=0;
155      newsigma = 1.e9;
156      for(int i=0;i<size;i++) output[i] = 0;
157      do{
158        if(par.isVerbose()) {
159          std::cout << "Iteration #"<<std::setw(2)<<++iteration<<":";
160          printBackSpace(13);
161        }
162
163        // first, get the value of oldsigma and set it to the previous
164        //   newsigma value
165        oldsigma = newsigma;
166        // we are transforming the residual array
167        for(int i=0;i<size;i++)  coeffs[i] = input[i] - output[i]; 
168
169        int spacing = 1;
170        for(int scale = 1; scale<numScales; scale++){
171
172          if(par.isVerbose()){
173            std::cout << "Scale ";
174            std::cout << std::setw(2)<<scale<<" / "<<std::setw(2)<<numScales;
175            printBackSpace(13);
176            std::cout <<std::flush;
177          }
178
179          for(int ypos = 0; ypos<ydim; ypos++){
180            for(int xpos = 0; xpos<xdim; xpos++){
181              // loops over each pixel in the image
182              int pos = ypos*xdim + xpos;
183         
184              wavelet[pos] = coeffs[pos];
185
186              if(!isGood[pos]) wavelet[pos] = 0.;
187              else{
188
189                int filterpos = -1;
190                for(int yoffset=-filterHW; yoffset<=filterHW; yoffset++){
191                  int y = ypos + spacing*yoffset;
192                  // Boundary conditions -- assume reflection at boundaries.
193                  // Use limits as calculated above
194                  //          if(yLim1[xpos]!=yLim2[xpos]){
195                  //            // if these are equal we will get into an infinite loop here
196                  //            while((y<yLim1[xpos])||(y>yLim2[xpos])){
197                  //              if(y<yLim1[xpos]) y = 2*yLim1[xpos] - y;     
198                  //              else if(y>yLim2[xpos]) y = 2*yLim2[xpos] - y;     
199                  //            }
200                  //          }
201                  int oldrow = y * xdim;
202         
203                  for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
204                    int x = xpos + spacing*xoffset;
205                    // Boundary conditions -- assume reflection at boundaries.
206                    // Use limits as calculated above
207                    //          if(xLim1[ypos]!=xLim2[ypos]){
208                    //            // if these are equal we will get into an infinite loop here
209                    //            while((x<xLim1[ypos])||(x>xLim2[ypos])){
210                    //              if(x<xLim1[ypos]) x = 2*xLim1[ypos] - x;     
211                    //              else if(x>xLim2[ypos]) x = 2*xLim2[ypos] - x;     
212                    //            }
213                    //          }
214
215                    int oldpos = oldrow + x;
216
217                    float oldCoeff;
218                    if((y>=yLim1[xpos])&&(y<=yLim2[xpos])&&
219                       (x>=xLim1[ypos])&&(x<=xLim2[ypos])  )
220                      oldCoeff = coeffs[oldpos];
221                    else oldCoeff = 0.;
222
223                    filterpos++;
224
225                    if(isGood[pos]) wavelet[pos] -= filter[filterpos] * oldCoeff;
226                    //            wavelet[pos] -= filter[filterpos] * coeffs[oldpos];
227
228                  } //-> end of xoffset loop
229                } //-> end of yoffset loop
230              } //-> end of else{ ( from if(!isGood[pos])  )
231       
232            } //-> end of xpos loop
233          } //-> end of ypos loop
234
235          // Need to do this after we've done *all* the convolving
236          for(int pos=0;pos<size;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
237
238          // Have found wavelet coeffs for this scale -- now threshold   
239          if(scale>=par.getMinScale()){
240            array = new float[size];
241            goodSize=0;
242            for(int pos=0;pos<size;pos++){
243              if(isGood[pos]) array[goodSize++] = wavelet[pos];
244            }
245            findMedianStats(array,goodSize,mean,sigma);
246            delete [] array;
247
248            threshold = mean +
249              par.getAtrousCut() * originalSigma * sigmaFactors[scale];
250            for(int pos=0;pos<size;pos++){
251              if(!isGood[pos]) output[pos] = input[pos];
252              // preserve the Blank pixel values in the output.
253              else if( fabs(wavelet[pos]) > threshold )
254                output[pos] += wavelet[pos];
255            }
256          }
257          spacing *= 2;
258
259        } // END OF LOOP OVER SCALES
260
261        for(int pos=0;pos<size;pos++) if(isGood[pos]) output[pos] += coeffs[pos];
262
263        array = new float[size];
264        goodSize=0;
265        for(int i=0;i<size;i++){
266          if(isGood[i]) array[goodSize++] = input[i] - output[i];
267        }
268        findMedianStats(array,goodSize,mean,newsigma);
269        newsigma = madfmToSigma(newsigma);
270        delete [] array;
271   
272        if(par.isVerbose()) printBackSpace(15);
273
274      } while( (iteration==1) ||
275               (fabs(oldsigma-newsigma)/newsigma > reconTolerance) );
276
277      if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
278
279      delete [] xLim1;
280      delete [] xLim2;
281      delete [] yLim1;
282      delete [] yLim2;
283      delete [] filter;
284      delete [] coeffs;
285      delete [] wavelet;
286
287    }
288
289    delete [] isGood;
290    delete [] sigmaFactors;
291  }
292   
293}
Note: See TracBrowser for help on using the repository browser.