casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
ImageDecomposer.h
Go to the documentation of this file.
00001 //# ImageDecomposer.h: decompose images into components
00002 //# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001,2002
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id: ImageDecomposer.h 20739 2009-09-29 01:15:15Z Malte.Marquarding $
00027 
00028 #ifndef IMAGES_IMAGEDECOMPOSER_H
00029 #define IMAGES_IMAGEDECOMPOSER_H
00030 
00031 #include <casa/iostream.h>
00032 #include <casa/math.h>
00033 #include <casa/aips.h>
00034 #include <casa/Arrays/Vector.h>
00035 #include <casa/Arrays/Matrix.h>
00036 #include <casa/Containers/Block.h>
00037 #include <scimath/Functionals/Function1D.h>
00038 #include <lattices/Lattices/TempLattice.h>
00039 #include <lattices/Lattices/SubLattice.h>
00040 #include <images/Images/ImageInterface.h>
00041 
00042 
00043 namespace casa { //# NAMESPACE CASA - BEGIN
00044 
00045 // <summary>
00046 // A tool to separate a complex image into individual components.
00047 // </summary>
00048 //
00049 // <use visibility=export>
00050 //
00051 // <reviewed reviewer="" date="" tests="tImageDecomposer.cc">
00052 // </reviewed>
00053 //
00054 // <prerequisite>
00055 //   <li> <linkto class=CoordinateSystem>CoordinateSystem</linkto>   
00056 //   <li> <linkto class=ImageInterface>ImageInterface</linkto>
00057 // </prerequisite>
00058 
00059 // <etymology>
00060 // It takes an image, and separates it into components.
00061 // </etymology>
00062 
00063 // <synopsis>
00064 // ImageDecomposer is an image decomposition tool that performs several tasks,
00065 // with the end result being that a strongly blended image is separated into
00066 // components - both in the sense that it determines the parameters for each
00067 // component (assuming a Gaussian model) and that it physically assigns each
00068 // pixel in the image to an individual object.  The products of these two
00069 // operations are called the component list and the component map, 
00070 // respectively.  The fitting process (which determines the component list) and
00071 // the pixel-decomposition process (which determines the component map) are
00072 // designed to work cooperatively to increase the efficiency and accuracy of
00073 // both, though each can operate without the other if necessary.
00074 // 
00075 // The algorithm between the decomposition is based on the function clfind
00076 // described in Williams et al 1994, which uses a contouring procedure whereby
00077 // a closed contour designates a separate component.  The program first 
00078 // separates the image into clearly distint 'regions' of blended emission, then
00079 // contours each region to determine the areas constituting each component and
00080 // passes this information on to the fitter, which determines the component 
00081 // list.  
00082 //
00083 // The software is compatible with 2 and 3 dimensional images, but is not
00084 // yet structured for higher dimensions.
00085 // </synopsis>
00086 
00087 // <example>
00088 // <srcblock>
00089 //  TempImage<Double> image;
00090 //  //(populate the image with data: see dImageDecomposer.cc)
00091 //  ImageDecomposer<Double> id(image);
00092 //  id.setDeblendOptions(0.3, 8);
00093 //  id.setFitOptions(0.4);
00094 //  id.decomposeImage();
00095 //  id.display();
00096 //  id.printComponents();
00097 // </srcblock>
00098 // </example>
00099 //   
00100 // <motivation>
00101 // </motivation>
00102 //
00103 // <note>
00104 // </note>
00105 //
00106 // <todo asof="2002/07/23">
00107 //   <li> Generalize dimensionality 
00108 //   <li> Use Lattice iterators in place of IPosition loops wherever possible
00109 //   <li> Speed up fitting by not sending every region pixel to the fitter
00110 //   <li> Send the completed componentmap to the user as an AIPS++ (Int?) Image
00111 //   <li> Return a ComponentList instead of a Matrix
00112 //   <li> Enable custom contouring at user level
00113 //   <li> Add progress meter
00114 //   <li> Numerous other improvements to make are documented in the code
00115 // </todo>
00116   
00117 
00118 
00119 template <class T> class ImageDecomposer {
00120 
00121 public:
00122 
00123 // 'Special' flag values for pixels in the component map.  An indeterminate
00124 // pixel lies directly between two components and cannot be immediately 
00125 // assigned.  A masked pixel is not inside the targeted region of the
00126 // sub-componentmap and is not used in decomposition or fitting.
00127    enum componentValues {
00128      INDETERMINATE = -1,
00129      MASKED = -2 
00130    };
00131 
00132 // Default constructor.   Object is not viable until setImage called
00133    ImageDecomposer();
00134 
00135 // Construct from image
00136    ImageDecomposer(ImageInterface<T>& image);
00137 
00138 // Copy constructor.
00139    ImageDecomposer(const ImageDecomposer<T>& other);
00140 
00141 // Assignment
00142    ImageDecomposer<T> &operator=(const ImageDecomposer<T> &other);
00143 
00144 // Destructor
00145    ~ImageDecomposer();
00146 
00147 // Tell the decomposer what image to decompose ("target image").
00148 // Also resets the internal component map.
00149    void setImage (ImageInterface<T>& image);
00150 
00151 // Tells the program whether or not to use the contour-based deblender. If not,
00152 // the program will instead perform a single thresholding followed by a
00153 // local maximum scan before fitting.
00154    void setDeblend(Bool deblendIt=True);
00155 
00156 // Specifies deblending options:
00157 // <ul>
00158 // <li> thresholdVal: noise cutoff level, used to distinguish source pixels
00159 //      from background pixels.  Also, regions which are not blended above this
00160 //      value will be fit separately.
00161 // <li> nContour: number of total contours to use in deblending regions.
00162 // <li> minRange: the minimum number of contours necessary to distinguish
00163 //      an object as a separate component.
00164 // <li> nAxis: paramater used to define whether or not two adjacent blocks
00165 //      of pixels are contiguous - see identifyRegions for details.
00166 // </ul>
00167 // See decomposeImage for more information on the deblending process.
00168    void setDeblendOptions(T thresholdVal=0.1, uInt nContour=11, 
00169                           Int minRange=2, Int nAxis=2);
00170 
00171 // Tells the program whether or not to perform fitting.  If not, the component
00172 // list will be dstermined by estimation from the values of the first and 
00173 // second order moments of each component.
00174    void setFit(Bool fitIt=True);
00175 
00176 // Specifies fitting options:
00177 // <ul>
00178 // <li> maximumRMS: The maximum RMS residual value (after fitting) allowed to
00179 //      identify a fit as successful.
00180 // <li> maxRetries: the maximum number of times the fit will be restarted in
00181 //      order to try to reach a successful result (convergent with 
00182 //      RMS < maximumRMS).  The default value of -1 tells the program
00183 //      to calculate a reasonable value automatically based on the complexity
00184 //      of the image.
00185 // <li> maxIter: maximum number of iterations to spend on each fit.
00186 // <li> convCriteria: criterion to establish convergence: see NonLinearFitLM.
00187 // </ul>
00188 // Additional information on these parameters can be found in FitGaussian.
00189    void setFitOptions(T maximumRMS=0.1, Int maxRetries=-1, uInt maxIter=256,
00190                       T convCriteria=0.0001);
00191 
00192 
00193 // The primary method of this class - executes the instructions stated in the
00194 // options above by deblending and/or fitting to the image to generate
00195 // the component map and/or component list.
00196   void decomposeImage(); 
00197 
00198 
00199 // Returns the number of regions found in the image.  A 'region' as defined
00200 // in this code is a subset of the image of contiguous pixels whose values
00201 // are greater than the threshold value specified in decomposeImage. A region
00202 // may contain one or more components.
00203   uInt numRegions() const;
00204 
00205 // Returns the number of components found in the image.  A 'component' as
00206 // defined in this code is a source that can be described as a single Gaussian.
00207 // This can only be determined after deblending.
00208   uInt numComponents() const;
00209 
00210 // Returns the shape of the component map.
00211   IPosition shape() const;                
00212 
00213 // Returns the length of a specific axis.
00214   Int shape(uInt axis) const;            
00215 
00216 // Returns True if the image has been thresholded (split up into regions.)
00217   Bool isDerived() const;
00218 
00219 // Returns True if the image has been decomposed (split up into components.)
00220   Bool isDecomposed() const;  
00221 
00222 // Returns the component parameters as a Matrix.  (Ideally, this should be
00223 // a ComponentList.)
00224   Matrix<T> componentList() const;
00225 
00226 // Currently does nothing; in the future should return the component map
00227 // in a way that it can be seen by the user in AIPS++, preferably as a
00228 // colorized image.
00229   void componentMap() const; 
00230 
00231 // Command-line text output functions.
00232 // <group>
00233   void display() const;
00234   void displayContourMap(const Vector<T>& clevels) const;
00235   void printComponents() const;
00236 // </group>
00237 // Boxes each region in the componentmap:
00238 // blc is set to the lowest coordinate value in each region;
00239 // trc is set to one above the highest coordinate value in each region.
00240   void boundRegions(Block<IPosition>& blc, Block<IPosition>& trc);
00241 private:
00242   ImageInterface<T> *itsImagePtr;// Points to the target image.
00243   Lattice<Int> *itsMapPtr;       // The actual component map.  
00244   IPosition itsShape;            // Component map shape
00245   uInt itsDim;                   // Component map number of dimensions
00246   uInt itsNRegions;              // Number of distinct regions in component map
00247   uInt itsNComponents;           // Number of components that have been fitted
00248   Matrix<T> itsList;             // The component list (Gaussian parameters for
00249                                  // each component.)  
00250   Bool itsDeblendIt;
00251   T itsThresholdVal;
00252   uInt itsNContour;              // Decomposition options
00253   Int itsMinRange;               // IMPR: maybe use a struct?
00254   Int itsNAxis;
00255   
00256   Bool itsFitIt;
00257   T itsMaximumRMS; 
00258   Int itsMaxRetries;             // Fitting options
00259   uInt itsMaxIter;
00260   T itsConvCriteria;
00261 
00262 
00263 
00264   void copyOptions(const ImageDecomposer<T>& other);
00265 
00266 // Makes sure a pair of IPositions is in the correct format for blc/trc, and
00267 // corrects them if they are not.
00268   void correctBlcTrc(IPosition& blc, IPosition& trc) const;
00269 
00270 // Used as an N-dimensional interator.  This should probably be replaced by
00271 // LatticeIterators...?
00272 // <group>
00273   Bool increment(IPosition& pos, const IPosition& shape) const;
00274   void decrement(IPosition& pos) const;
00275 // </group>
00276 
00277 // Returns the component to which the specified cell belongs
00278 // <group>
00279   Int getCell(Int x, Int y) const;             
00280   Int getCell(Int x, Int y, Int z) const;    
00281   Int getCell(const IPosition& coord) const;
00282 // </group>
00283 
00284 // Assigns the specified cell to the specified component
00285 // <group>
00286   void setCell(Int x, Int y, Int sval);       
00287   void setCell(Int x, Int y, Int z, Int sval); 
00288   void setCell(const IPosition& coord, Int sval);
00289 // </group>
00290 
00291 // Semi-automatic way to set contour levels: at the given increment counting
00292 // between mincon and maxcon.
00293   Vector<T> autoContour(T minCon, T maxCon, T inc) const;
00294 
00295 // Linearly spaces contours between minvalue and just below the
00296 // maximum value in the target region of the target image, and returns
00297 // the contour values as a Vector.
00298   Vector<T> autoContour(Int nContours=11, T minValue=0) const;
00299 
00300 // Nonlinear spacing option for contouring; spaces contours according to the
00301 // function given.  The domain of the function is 0 <-> ncontours-1; the
00302 // range is automatically calibrated to be minvalue <-> maxvalue.  The function
00303 // should be nondecreasing in the domain such that each contour is greater
00304 // than the last.
00305   Vector<T> autoContour(const Function1D<T>& fn,
00306                         Int nContours = 11, T minValue = 0) const;
00307 
00308 
00309 //Eliminates any regions whose corresponding values in killRegion are True
00310 // by setting all pixel values in the componentmap set to that region to
00311 // zero.  Zero-oriented; there is an offset of one between the index in
00312 // killRegion and the actual region in the componentmap.
00313   void destroyRegions(const Vector<Bool>& killRegion);
00314 
00315 // Eliminates regions with no cells by replacing them with higher-numbered 
00316 // regions.
00317   void renumberRegions();
00318 
00319 // Overlays a smaller map onto an empty region of a larger map,
00320 // and adds submap component list to main component list.
00321 // The user should exercise caution with this function and synthesize submaps
00322 // only into regions of the main map that are truly empty (0), as no blending
00323 // is assumed between different maps.
00324   void synthesize(const ImageDecomposer<T>& subdecomposer, IPosition blc);
00325 
00326 // Set all elements in the component map to zero and clear the component list.
00327   void zero();
00328 
00329 // Set all nonmasked elements in the component map to zero and clear the 
00330 // component list.
00331   void clear();
00332 
00333 
00334 
00335 // Finds the greatest value inside the specified rectangular area of the
00336 // target image.
00337 // <group>
00338   T findAreaGlobalMax(IPosition blc, IPosition trc) const;
00339   void findAreaGlobalMax(T& maxval, IPosition& maxvalpos, 
00340                          IPosition blc, IPosition trc) const;
00341   Vector<T> findAreaGlobalMax(IPosition blc, IPosition trc, Int naxis) const;
00342   void findAreaGlobalMax(Vector<T>& maxvals,
00343                          Block<IPosition>& maxvalpos,
00344                          IPosition blc, IPosition trc,
00345                          Int naxis) const;
00346 // </group>
00347 
00348 // Finds all local maxima inside the specified rectangular area of the
00349 // target image.
00350 // <group>
00351   Vector<T> findAreaLocalMax(IPosition blc, IPosition trc, Int naxis) const;
00352   void findAreaLocalMax(Vector<T>& maxvals,Block<IPosition>& maxvalpos, 
00353                         IPosition blc, IPosition trc, Int naxis) const;
00354 // </group>
00355 
00356 // Finds the maximum value of the target image in each region of the
00357 // componentmap.
00358 // <group>
00359   Vector<T> findAllRegionGlobalMax() const;
00360   void findAllRegionGlobalMax(Vector<T>& maxvals, 
00361                               Block<IPosition>& maxvalpos) const;
00362 // </group>
00363 
00364 
00365 // Finds all local maxima of the target image inside the specifed region
00366 // of the componentmap.
00367 // <group>
00368   Vector<T> findRegionLocalMax(Int nregion, Int naxis) const;
00369   void findRegionLocalMax(Vector<T>& maxvals, Block<IPosition>& maxvalpos, 
00370                           Int nregion, Int naxis) const;
00371 // </group>
00372 
00373 
00374 //Compares specified pixel to adjacent pixels to determine if it is
00375 //greatest in local pixel block.
00376 //2D:
00377 //naxis = 1: compare to 4 adjacent pixels (axes only)
00378 //naxis = 2: compare to 8 adjacent pixels (axes and diagonals)
00379 //3D:
00380 //naxis = 1: compare to 6 adjacent pixels (axes only)
00381 //naxis = 2: compare to 18 adjacent pixels (axes and 2-axis diagonals)
00382 //naxis = 3: compare to 26 adjacent pixels (axes and 2/3-axis diagonals)
00383 // <group>
00384   Bool isLocalMax(const IPosition& pos, Int naxis) const;
00385   Bool isLocalMax(Int x, Int y, Int naxis) const;
00386   Bool isLocalMax(Int x, Int y, Int z, Int naxis) const;
00387 // </group>
00388 
00389 // Finds a rough estimate of the width of each component by scanning to find
00390 // the full width at quarter maximum.
00391 // Requires the location of each component.
00392 // This function is mostly obsolete, and is only used when the contour 
00393 // deblender is off (since the component map is necessary to determine the
00394 // moments).
00395   void estimateComponentWidths(Matrix<T>& width,
00396                                const Block<IPosition>& maxvalpos) const;
00397 
00398 // Calculates the 0th-2nd order moments of a region.
00399   Array<T> calculateMoments(Int region) const;
00400 
00401 
00402 // Performs a single threshold scan on the image.  In other words,
00403 // identifies all contigous blocks of pixels in the target image above the
00404 // threshold value thrval, assigning each unique block to an integer,
00405 // starting at one.  All pixels with target image values below thrval are set
00406 // to zero.
00407   uInt identifyRegions(T thrval, Int naxis=2);
00408 
00409 // Performs the contour decomposition on a blended image to generate a 
00410 // component map that can detect components blended above any threshold(s),
00411 // by performing threshold scans at each contour level and recognizing
00412 // as individual any components that are distinct above any such level.
00413   void deblendRegions(const Vector<T>& contours, Int minRange=1, Int naxis=2);
00414 
00415 // Retrieves the target image's value at the given location.
00416 // <group>
00417   T getImageVal(IPosition coord) const;
00418   T getImageVal(Int x, Int y) const;
00419   T getImageVal(Int x, Int y, Int z) const;
00420 // </group>
00421 
00422 // Retrieves the number of the highest contour with a value less then the
00423 // target image's value at the given location.
00424 // <group>
00425   Int getContourVal(IPosition coord, const Vector<T>& clevels) const;
00426   Int getContourVal(Int x, Int y, Int z, const Vector<T>& clevels) const;
00427   Int getContourVal(Int x, Int y, const Vector<T>& clevels) const;
00428   Int getContourVal(T val, const Vector<T>& clevels) const;
00429 // </group>
00430 
00431 // Fits multiple gaussians to a single region.  First performs a local 
00432 // maximum scan to estimate the number of components in the region.
00433   Matrix<T> fitRegion(Int region);
00434 
00435 // Fits gaussians to an image; multiple gaussians per region in the component
00436 // map.  The regions are fit sequentially and independently, so this function 
00437 // can be used on the main image.  If the map is not yet thresholded, will fit
00438 // to the entire image as if it  were a single composite object, which will be
00439 // very slow.
00440   void fitRegions();
00441 
00442 // Fits gaussians to an image; one gaussian per region in the pmap.
00443 // This function is intended to be used only by ImageDecomposer on its
00444 // intermediary subimages; using it at higher level will execute a full
00445 // gaussian fit on the main image and will be extremely slow. Every 
00446 // nonflagged object pixel in the image is used in fitting.
00447 
00448 // If the deblended flag is True, the function will treat each region as
00449 // an individual component and will fit that many gaussians to the image
00450   void fitComponents();
00451 
00452 // Estimate the component parameters based on moments calculated using 
00453 // the component map.
00454   Matrix<T> estimateComponents();
00455 
00456 // Fits the specified number of 3D gaussians to the data, and returns 
00457 // solution in image (world) coordinates.  Essentially just an interface
00458 // for FitGaussian.
00459 // <group>
00460   Matrix<T> fitGauss(const Matrix<T>& positions, const Vector<T>& dataValues,
00461                      const Matrix<T>& initestimate) const;
00462 
00463 // </group>
00464 
00465 };
00466 
00467 } //# NAMESPACE CASA - END
00468 
00469 #ifndef CASACORE_NO_AUTO_TEMPLATES
00470 #include <imageanalysis/ImageAnalysis/ImageDecomposer.tcc>
00471 #endif //# CASACORE_NO_AUTO_TEMPLATES
00472 #endif