LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiBoundingBox.h

00001 /*
00002  * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 
00024 /*----------------------------------------------------------------
00025  * project ....: LTI Digital Image/Signal Processing Library
00026  * file .......: ltiBoundingBox.h
00027  * authors ....: Pablo Alvarado
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 9.10.2000
00030  * revisions ..: $Id: ltiBoundingBox.h,v 1.9 2007/02/02 14:42:04 alvarado Exp $
00031  */
00032 
00033 #ifndef _LTI_BOUNDING_BOX_H_
00034 #define _LTI_BOUNDING_BOX_H_
00035 
00036 #include "ltiObject.h"
00037 #include "ltiMatrix.h"
00038 #include "ltiContour.h"
00039 #include "ltiLocation.h"
00040 #include "ltiSegmentation.h"
00041 #include "ltiTypes.h"
00042 
00043 namespace lti {
00044   /**
00045    * Generate an image containing a region of another one specified
00046    * through a contour-instance, or compute the "best" rectLocation
00047    * that contains the specified region.
00048    *
00049    * After segmenting the biggest object on an image or channel,
00050    * it is usually desirable to get a new image with the extracted object only.
00051    * This class will allow to generate such an image.  The position of the
00052    * desired object will be indicated by the area points of a contour object.
00053    *
00054    * Type T of the template specify the type of the matrix to be used (for
00055    * images this will be rgbPixel and for channels float).
00056    *
00057    * Example:
00058    *
00059    * \code
00060    *
00061    * lti::loadBMP loader;
00062    * lti::image img,biggestObject;
00063    * lti::channel8 mask;
00064    *
00065    * loader.load("img/leo040801_00_019.bmp",img); // load an image
00066    *
00067    * lti::regionGrowing segmenter;  // functor for segmentation
00068    *
00069    * segmenter.apply(img,mask);     // get a mask to differentiate background
00070    *                                // and object.
00071    *
00072    * // get the biggest object on the mask
00073    * lti::objectsFromMask ofm;
00074    * std::list<areaPoints> objs;
00075    * ofm.apply(mask,objs); // the first object on "objs" is the biggest one
00076    *                       // on the mask!
00077    * // get a new image with the biggest object only
00078    * lti::boundingBox<image::value_type> bbox;
00079    * lti::boundingBox<image::value_type>::parameters bboxParam;
00080    * bboxParam.borderSize = 5; // the border will have 5 pixels (each side!)
00081    * bboxParam.centerOfGravity = false;
00082    * bbox.apply(img,objs.front(),biggestObject);
00083    *
00084    * \endcode
00085    */
00086   template<class T>
00087   class boundingBox : public segmentation {
00088   public:
00089     // implemetation of parameters here due to a MSVC++ bug
00090     /**
00091      * the parameters for the class boundingBox
00092      */
00093     class parameters : public segmentation::parameters {
00094     public:
00095       /**
00096        * default constructor
00097        */
00098       parameters() : segmentation::parameters() {
00099         borderSize = int(1);
00100         centerOfGravity = bool(false);
00101         backgroundColor = T(0);
00102         justSuppressBackground = false;
00103         optimalBox = false;
00104         useLengths = false;
00105       };
00106 
00107       /**
00108        * copy constructor
00109        * @param other the parameters object to be copied
00110        */
00111       parameters(const parameters& other) : segmentation::parameters() {
00112         copy(other);
00113       };
00114 
00115       /**
00116        * destructor
00117        */
00118       ~parameters() {
00119       };
00120 
00121       /**
00122        * returns name of this type
00123        */
00124       const char* getTypeName() const {
00125         return "boundingBox::parameters";
00126       };
00127 
00128       /**
00129        * copy the contents of a parameters object
00130        * @param other the parameters object to be copied
00131        * @return a reference to this parameters object
00132        */
00133       parameters& copy(const parameters& other) {
00134 #     ifndef _LTI_MSC_6
00135         // MS Visual C++ 6 is not able to compile this...
00136         segmentation::parameters::copy(other);
00137 #     else
00138         // ...so we have to use this workaround.
00139         // Conditional on that, copy may not be virtual.
00140         segmentation::parameters& (segmentation::parameters::* p_copy)
00141           (const segmentation::parameters&) =
00142           segmentation::parameters::copy;
00143         (this->*p_copy)(other);
00144 #     endif
00145 
00146         borderSize = other.borderSize;
00147         centerOfGravity = other.centerOfGravity;
00148         backgroundColor = other.backgroundColor;
00149         justSuppressBackground = other.justSuppressBackground;
00150         optimalBox = other.optimalBox;
00151         useLengths = other.useLengths;
00152 
00153         return *this;
00154       };
00155 
00156       /**
00157        * returns a pointer to a clone of the parameters
00158        */
00159       virtual functor::parameters* clone() const {
00160         return new parameters(*this);
00161       };
00162 
00163       /**
00164        * write the parameters in the given ioHandler
00165        * @param handler the ioHandler to be used
00166        * @param complete if true (the default) the enclosing begin/end will
00167        *        be also written, otherwise only the data block will be
00168        *        written.
00169        * @return true if write was successful
00170        */
00171 #     ifndef _LTI_MSC_6
00172       virtual bool write(ioHandler& handler,const bool complete=true) const
00173 #     else
00174         bool writeMS(ioHandler& handler,const bool complete=true) const
00175 #     endif
00176         {
00177           bool b = true;
00178           if (complete) {
00179             b = handler.writeBegin();
00180           }
00181 
00182           if (b) {
00183             lti::write(handler,"borderSize",borderSize);
00184             lti::write(handler,"centerOfGravity",centerOfGravity);
00185             lti::write(handler,"backgroundColor",backgroundColor);
00186             lti::write(handler,"justSuppressBackground",
00187                        justSuppressBackground);
00188             lti::write(handler,"optimalBox",optimalBox);
00189             lti::write(handler,"useLengths",useLengths);
00190           }
00191 
00192 #       ifndef _LTI_MSC_6
00193           // This is the standard C++ code, which MS Visual C++ 6 is not
00194           // able to compile...
00195           b = b && segmentation::parameters::write(handler,false);
00196 #       else
00197           bool (segmentation::parameters::* p_writeMS)(ioHandler&,
00198                                                    const bool) const =
00199             segmentation::parameters::writeMS;
00200           b = b && (this->*p_writeMS)(handler,false);
00201 #       endif
00202 
00203           if (complete) {
00204             b = b && handler.writeEnd();
00205           }
00206 
00207           return b;
00208         }
00209 
00210 #     ifdef _LTI_MSC_6
00211         virtual bool write(ioHandler& handler,
00212                            const bool complete = true) const {
00213            // ...we need this workaround to cope with another really
00214            // awful MSVC bug.
00215            return writeMS(handler,complete);
00216         }
00217 #     endif
00218 
00219         /**
00220          * read the parameters from the given ioHandler
00221          * @param handler the ioHandler to be used
00222          * @param complete if true (the default) the enclosing begin/end will
00223          *        be also read, otherwise only the data block will be read.
00224          * @return true if write was successful
00225          */
00226 #     ifndef _LTI_MSC_6
00227         virtual bool read(ioHandler& handler,const bool complete = true)
00228 #     else
00229         bool readMS(ioHandler& handler,const bool complete=true)
00230 #     endif
00231         {
00232           bool b = true;
00233           if (complete) {
00234             b = handler.readBegin();
00235           }
00236 
00237           if (b) {
00238             lti::read(handler,"borderSize",borderSize);
00239             lti::read(handler,"centerOfGravity",centerOfGravity);
00240             lti::read(handler,"backgroundColor",backgroundColor);
00241             lti::read(handler,"justSuppressBackground",justSuppressBackground);
00242             lti::read(handler,"optimalBox",optimalBox);
00243             lti::read(handler,"useLengths",useLengths);
00244           }
00245 
00246 #     ifndef _LTI_MSC_6
00247           // This is the standard C++ code, which MS Visual C++ 6 is not
00248           // able to compile...
00249 
00250           b = b && segmentation::parameters::read(handler,false);
00251 #     else
00252           bool (segmentation::parameters::* p_readMS)(ioHandler&,const bool) =
00253           segmentation::parameters::readMS;
00254           b = b && (this->*p_readMS)(handler,false);
00255 #     endif
00256 
00257           if (complete) {
00258             b = b && handler.readEnd();
00259           }
00260 
00261           return b;
00262         }
00263 
00264 #     ifdef _LTI_MSC_6
00265         virtual bool read(ioHandler& handler,const bool complete=true) {
00266           // ...we need this workaround to cope with another really awful MSVC
00267           // bug.
00268           return readMS(handler,complete);
00269         }
00270 #      endif
00271 
00272 
00273       // --------------------------------------------------
00274       // boundingBox::parameters
00275       // --------------------------------------------------
00276 
00277       /**
00278        * The extracted image will have at each side a border of (at least)
00279        * the specified number of pixels.  If "centerOfGravity" is false, the
00280        * border will have exactly "borderSize" pixels.
00281        *
00282        * Default value: 1
00283        */
00284       int borderSize;
00285 
00286       /**
00287        * If "true", the center of gravity of the object will be forced
00288        * to be at the center of the new image.  If false, only the
00289        * borders of the object will be considered in the calculations.
00290        *
00291        * Default value: false;
00292        */
00293       bool centerOfGravity;
00294 
00295       /**
00296        * Background color
00297        *
00298        * Default value: T(0) (i.e. Black for images or 0 for channels)
00299        */
00300       T backgroundColor;
00301 
00302       /**
00303        * Suppress background only.  If true, the borderSize and centerOfGravity
00304        * parameters will be ignored, and the resulting image will have exactly
00305        * the same dimensions than the input image.  If false, the size of the
00306        * resulting image will be determined by the other parameters.
00307        *
00308        * Default value: false.
00309        */
00310       bool justSuppressBackground;
00311 
00312       /**
00313        * If false, just the principal components of the convex hull will be
00314        * used to determine the rectLocation's angle.  If true, an optimal
00315        * angle will be determined, that minimizes the area of the rectLocation.
00316        *
00317        * This attribute takes effect only in the apply methods related to 
00318        * the computation of the rectLocation instances.
00319        *
00320        * Default value: false
00321        */
00322       bool optimalBox;
00323 
00324       /**
00325        * If true, the bounding box length is used for determining
00326        * which axis represents is the main axis. If false, this is determined
00327        * by a PCA of the contour points.
00328        *
00329        * Default value: false
00330        */
00331       bool useLengths;
00332 
00333     };
00334 
00335     /**
00336      * default constructor
00337      */
00338     boundingBox();
00339 
00340     /**
00341      * copy constructor
00342      * @param other the object to be copied
00343      */
00344     boundingBox(const boundingBox& other);
00345 
00346     /**
00347      * destructor
00348      */
00349     virtual ~boundingBox();
00350 
00351     /**
00352      * returns the name of this type ("boundingBox")
00353      */
00354     virtual const char* getTypeName() const;
00355 
00356     /**
00357      * Take the object specified by the area points, and
00358      * create a new image with only the object and a border of the specified
00359      * size on the srcdest.
00360      * @param srcdest matrix with the source data.  The result
00361      *                 will be left here too.
00362      * @param obj a contour which specifies which points of the image
00363      *            belong to the object.  Only the area points, center and
00364      *            boundary points
00365      * @return true if successful, false otherwise
00366      */
00367     bool apply(matrix<T>& srcdest,const areaPoints& obj) const;
00368 
00369     /**
00370      * Take the object specified by the area points on the given contour, and
00371      * create a new image with only the object and a border of the specified
00372      * size on the srcdest.
00373      * @param src matrix with the source data.
00374      * @param obj the areaPoints list which specifies which points of
00375      *            the image belong to the object.  The boundary must
00376      *            be calculated before calling this member (i.e. you
00377      *            need to call obj.computeBoundary()).  This is not
00378      *            done automatically, because many functors (like
00379      *            lti::objectsFromMask) compute the bounding box
00380      *            directly and computing it twice can cost too much
00381      *            time!
00382      * @param dest matrix where the destination data will be stored.
00383      * @return true if successful, false otherwise
00384      */
00385     bool apply(const matrix<T>& src,
00386                const areaPoints& obj,
00387                matrix<T>& dest) const;
00388 
00389     /**
00390      * Take the object specified by the area points on the given contour, and
00391      * create a new image with only the object and a border of the specified
00392      * size on the srcdest.
00393      * @param src matrix with the source data.
00394      * @param obj the areaPoints list which specifies which points of
00395      *            the image belong to the object.  The boundary must
00396      *            be calculated before calling this member (i.e. you
00397      *            need to call obj.computeBoundary()).  This is not
00398      *            done automatically, because many functors (like
00399      *            lti::objectsFromMask) compute the bounding box
00400      *            directly and computing it twice can cost too much
00401      *            time!
00402      * @param dest matrix where the destination data will be stored.
00403      * @param loc a rectangular location that indicates the smallest
00404      *            rectangular region that contains the hole object
00405      * @return true if successful, false otherwise
00406      */
00407     bool apply(const matrix<T>& src,
00408                const areaPoints& obj,
00409                matrix<T>& dest,
00410                rectLocation& loc) const;
00411 
00412 
00413     /**
00414      * computes the oriented rectangular bounding box for the given
00415      * area points, and leaves the result as a rectLocation.
00416      *
00417      * @param obj areaPoints with the object description
00418      * @param loc the rectangular location will represent the smallest
00419      *            rectangular region that contains all points of the
00420      *            areaPoints obj.
00421      * @return true if successful, false otherwise.
00422      */
00423     bool apply(const areaPoints& obj,
00424                rectLocation& loc) const;
00425 
00426     /**
00427      * computes the oriented rectangular bounding box for the given
00428      * io points, and leaves the result as a rectLocation.
00429      *
00430      * @param obj io points with the object description
00431      * @param loc the rectangular location will represent the smallest
00432      *            rectangular region that contains all points of the
00433      *            io points obj.
00434      * @return true if successful, false otherwise.
00435      */
00436     bool apply(const ioPoints& obj,
00437                rectLocation& loc) const;
00438 
00439     /**
00440      * computes the oriented rectangular bounding box for the given
00441      * point list, and leaves the result as a rectLocation.
00442      *
00443      * @param obj point list the object description
00444      * @param loc the rectangular location will represent the smallest
00445      *            rectangular region that contains all points of the list.
00446      * @return true if successful, false otherwise.
00447      */
00448     bool apply(const pointList& obj,
00449                rectLocation& loc) const;
00450 
00451     /**
00452      * copy data of "other" functor.
00453      * @param other the functor to be copied
00454      * @return a reference to this functor object
00455      */
00456     boundingBox& copy(const boundingBox& other);
00457 
00458     /**
00459      * returns a pointer to a clone of this functor.
00460      */
00461     virtual functor* clone() const;
00462 
00463     /**
00464      * returns used parameters
00465      */
00466     const parameters& getParameters() const;
00467 
00468   protected:
00469     /**
00470      * calculate the source box of the source image, the size of the
00471      * destination image, and the position of the box on the destination
00472      * image.
00473      * @param obj the area points of the object.  It is
00474      *            assumed that the boundary of the object is up to date.
00475      *            (see lti::pointList::updateBoundary())
00476      * @param destSize size of the destination image
00477      * @param delta translation vector of the area points to the new image.
00478      */
00479     void calculatePositions(const areaPoints& obj,
00480                             point& destSize,
00481                             point& delta) const;
00482 
00483 
00484     /**
00485      * compute the location given the angle in the location.
00486      */
00487     void computeLocation(const pointList& pts,
00488                          rectLocation& loc) const;
00489 
00490     /**
00491      * location from the convex hull
00492      */
00493     bool computeLocationFromCH(const pointList& convexHull,
00494                                rectLocation& loc) const;
00495   };
00496 }
00497 
00498 #endif

Generated on Sat Apr 10 15:25:10 2010 for LTI-Lib by Doxygen 1.6.1