latest version v1.9 - last update 10 Apr 2010 |
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