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

Last change on this file since 884 was 884, checked in by MatthewWhiting, 12 years ago

A large set of changes aimed at making the use of indexing variables consistent. We have moved to size_t as much as possible to represent the location in memory. This includes making the dimension array within DataArray? and derived classes an array of size_t variables. Still plenty of compilation warnings (principally comparing signed and unsigned variables) - these will need to be cleaned up.

File size: 9.8 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(unsigned long &xdim, unsigned long &ydim, float *&input, float *&output, Param &par)
44  {
45    ///  A routine that uses the a trous wavelet method to reconstruct a
46    ///   2-dimensional image.
47    ///
48    ///  If there are no non-BLANK pixels (and we are testing for
49    ///  BLANKs), the reconstruction cannot be done, so we return the
50    ///  input array as the output array and give a warning message.
51    ///
52    ///  \param xdim The length of the x-axis of the image.
53    ///  \param ydim The length of the y-axis of the image.
54    ///  \param input The input spectrum.
55    ///  \param output The returned reconstructed spectrum. This array
56    ///  needs to be declared beforehand.
57    ///  \param par The Param set:contains all necessary info about the
58    ///  filter and reconstruction parameters.
59
60    size_t size = xdim * ydim;
61    unsigned long mindim = xdim;
62    if (ydim<mindim) mindim = ydim;
63    unsigned int numScales = par.filter().getNumScales(mindim);
64    double *sigmaFactors = new double[numScales+1];
65    for(size_t i=0;i<=numScales;i++){
66      if(i<=par.filter().maxFactor(2))
67        sigmaFactors[i] = par.filter().sigmaFactor(2,i);
68      else sigmaFactors[i] = sigmaFactors[i-1] / 2.;
69    }
70
71    float mean,sigma,originalSigma,originalMean,oldsigma,newsigma;
72    size_t goodSize=0;
73    bool *isGood = new bool[size];
74    for(size_t pos=0;pos<size;pos++){
75      isGood[pos] = !par.isBlank(input[pos]);
76      if(isGood[pos]) goodSize++;
77    }
78
79    if(goodSize == 0){
80      // There are no good pixels -- everything is BLANK for some reason.
81      // Return the input array as the output, and give a warning message.
82
83      for(size_t pos=0;pos<size; pos++) output[pos] = input[pos];
84
85      duchampWarning("2D Reconstruction","\
86There are no good pixels to be reconstructed -- all are BLANK.\n\
87Returning input array.\n");
88    }
89    else{
90      // Otherwise, all is good, and we continue.
91
92      //      findMedianStats(input,goodSize,isGood,originalMean,originalSigma);
93      // originalSigma = madfmToSigma(originalSigma);
94      if(par.getFlagRobustStats())
95        originalSigma = madfmToSigma(findMADFM(input,isGood,size));
96      else
97        originalSigma = findStddev(input,isGood,size);
98 
99      float *coeffs    = new float[size];
100      float *wavelet   = new float[size];
101      // float *residual  = new float[size];
102
103      for(size_t pos=0;pos<size;pos++) output[pos]=0.;
104
105      unsigned int filterwidth = par.filter().width();
106      int filterHW = filterwidth/2;
107      double *filter = new double[filterwidth*filterwidth];
108      for(size_t i=0;i<filterwidth;i++){
109        for(size_t j=0;j<filterwidth;j++){
110          filter[i*filterwidth+j] = par.filter().coeff(i) * par.filter().coeff(j);
111        }
112      }
113
114      long *xLim1 = new long[ydim];
115      for(size_t i=0;i<ydim;i++) xLim1[i] = 0;
116      long *yLim1 = new long[xdim];
117      for(size_t i=0;i<xdim;i++) yLim1[i] = 0;
118      long *xLim2 = new long[ydim];
119      for(size_t i=0;i<ydim;i++) xLim2[i] = xdim-1;
120      long *yLim2 = new long[xdim];
121      for(size_t i=0;i<xdim;i++) yLim2[i] = ydim-1;
122
123      if(par.getFlagBlankPix()){
124        float avGapX = 0, avGapY = 0;
125        for(size_t row=0;row<ydim;row++){
126          size_t ct1 = 0;
127          size_t ct2 = xdim - 1;
128          while((ct1<ct2)&&(par.isBlank(input[row*xdim+ct1]))) ct1++;
129          while((ct2>ct1)&&(par.isBlank(input[row*xdim+ct2]))) ct2--;
130          xLim1[row] = ct1;
131          xLim2[row] = ct2;
132          avGapX += ct2 - ct1;
133        }
134        avGapX /= float(ydim);
135   
136        for(size_t col=0;col<xdim;col++){
137          size_t ct1=0;
138          size_t ct2=ydim-1;
139          while((ct1<ct2)&&(par.isBlank(input[col+xdim*ct1]))) ct1++;
140          while((ct2>ct1)&&(par.isBlank(input[col+xdim*ct2]))) ct2--;
141          yLim1[col] = ct1;
142          yLim2[col] = ct2;
143          avGapY += ct2 - ct1;
144        }
145        avGapY /= float(xdim);
146   
147        // if(avGapX < mindim) mindim = int(avGapX);
148        // if(avGapY < mindim) mindim = int(avGapY);
149        // numScales = par.filter().getNumScales(mindim);
150      }
151
152      float threshold;
153      int iteration=0;
154      newsigma = 1.e9;
155      for(size_t i=0;i<size;i++) output[i] = 0;
156      do{
157        if(par.isVerbose()) {
158          std::cout << "Iteration #"<<std::setw(2)<<++iteration<<":";
159          printBackSpace(13);
160        }
161
162        // first, get the value of oldsigma and set it to the previous
163        //   newsigma value
164        oldsigma = newsigma;
165        // we are transforming the residual array
166        for(size_t i=0;i<size;i++)  coeffs[i] = input[i] - output[i]; 
167
168        int spacing = 1;
169        for(unsigned int scale = 1; scale<numScales; scale++){
170
171          if(par.isVerbose()){
172            std::cout << "Scale ";
173            std::cout << std::setw(2)<<scale<<" / "<<std::setw(2)<<numScales;
174            printBackSpace(13);
175            std::cout <<std::flush;
176          }
177
178          for(unsigned long ypos = 0; ypos<ydim; ypos++){
179            for(unsigned long xpos = 0; xpos<xdim; xpos++){
180              // loops over each pixel in the image
181              size_t pos = ypos*xdim + xpos;
182         
183              wavelet[pos] = coeffs[pos];
184
185              if(!isGood[pos]) wavelet[pos] = 0.;
186              else{
187
188                size_t filterpos = -1;
189                for(int yoffset=-filterHW; yoffset<=filterHW; yoffset++){
190                  long y = long(ypos) + spacing*yoffset;
191                  // Boundary conditions -- assume reflection at boundaries.
192                  // Use limits as calculated above
193                  //          if(yLim1[xpos]!=yLim2[xpos]){
194                  //            // if these are equal we will get into an infinite loop here
195                  //            while((y<yLim1[xpos])||(y>yLim2[xpos])){
196                  //              if(y<yLim1[xpos]) y = 2*yLim1[xpos] - y;     
197                  //              else if(y>yLim2[xpos]) y = 2*yLim2[xpos] - y;     
198                  //            }
199                  //          }
200                  size_t oldrow = y * xdim;
201         
202                  for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
203                    long x = long(xpos) + spacing*xoffset;
204                    // Boundary conditions -- assume reflection at boundaries.
205                    // Use limits as calculated above
206                    //          if(xLim1[ypos]!=xLim2[ypos]){
207                    //            // if these are equal we will get into an infinite loop here
208                    //            while((x<xLim1[ypos])||(x>xLim2[ypos])){
209                    //              if(x<xLim1[ypos]) x = 2*xLim1[ypos] - x;     
210                    //              else if(x>xLim2[ypos]) x = 2*xLim2[ypos] - x;     
211                    //            }
212                    //          }
213
214                    size_t oldpos = oldrow + x;
215
216                    float oldCoeff;
217                    if((y>=yLim1[xpos])&&(y<=yLim2[xpos])&&
218                       (x>=xLim1[ypos])&&(x<=xLim2[ypos])  )
219                      oldCoeff = coeffs[oldpos];
220                    else oldCoeff = 0.;
221
222                    filterpos++;
223
224                    if(isGood[pos]) wavelet[pos] -= filter[filterpos] * oldCoeff;
225                    //            wavelet[pos] -= filter[filterpos] * coeffs[oldpos];
226
227                  } //-> end of xoffset loop
228                } //-> end of yoffset loop
229              } //-> end of else{ ( from if(!isGood[pos])  )
230       
231            } //-> end of xpos loop
232          } //-> end of ypos loop
233
234          // Need to do this after we've done *all* the convolving
235          for(size_t pos=0;pos<size;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
236
237          // Have found wavelet coeffs for this scale -- now threshold   
238          if(scale>=par.getMinScale()){
239            //      findMedianStats(wavelet,goodSize,isGood,mean,sigma);
240            if(par.getFlagRobustStats())
241              mean = findMedian(wavelet,isGood,size);
242            else
243              mean= findMean(wavelet,isGood,size);
244
245            threshold = mean +
246              par.getAtrousCut() * originalSigma * sigmaFactors[scale];
247            for(size_t pos=0;pos<size;pos++){
248              if(!isGood[pos]) output[pos] = input[pos];
249              // preserve the Blank pixel values in the output.
250              else if( fabs(wavelet[pos]) > threshold )
251                output[pos] += wavelet[pos];
252            }
253          }
254          spacing *= 2;
255
256        } // END OF LOOP OVER SCALES
257
258        for(size_t pos=0;pos<size;pos++) if(isGood[pos]) output[pos] += coeffs[pos];
259
260        // for(size_t i=0;i<size;i++) residual[i] = input[i] - output[i];
261        // findMedianStats(residual,goodSize,isGood,mean,newsigma);
262        // findMedianStatsDiff(input,output,size,isGood,mean,newsigma);
263        // newsigma = madfmToSigma(newsigma);
264        if(par.getFlagRobustStats())
265          newsigma = madfmToSigma(findMADFMDiff(input,output,isGood,size));
266        else
267          newsigma = findStddevDiff(input,output,isGood,size);
268
269        if(par.isVerbose()) printBackSpace(15);
270
271      } while( (iteration==1) ||
272               (fabs(oldsigma-newsigma)/newsigma > reconTolerance) );
273
274      if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
275
276      delete [] xLim1;
277      delete [] xLim2;
278      delete [] yLim1;
279      delete [] yLim2;
280      delete [] filter;
281      delete [] coeffs;
282      delete [] wavelet;
283      // delete [] residual;
284
285    }
286
287    delete [] isGood;
288    delete [] sigmaFactors;
289  }
290   
291}
Note: See TracBrowser for help on using the repository browser.