casa
$Rev:20696$
|
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