source: tags/release-1.1/src/ATrous/atrous_2d_reconstruct.cc @ 1391

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

Adding distribution text at the start of each file...

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