latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 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-Lib: Image Processing and Computer Vision Library 00026 * file .......: ltiFastLineExtraction.h 00027 * authors ....: Ingo Grothues (ingo@isdevelop.de) 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 10.3.2004 00030 * revisions ..: $Id: ltiFastLineExtraction.h,v 1.10 2006/02/08 11:06:36 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_FAST_LINE_EXTRACTION_H_ 00034 #define _LTI_FAST_LINE_EXTRACTION_H_ 00035 00036 #include "ltiFeatureExtractor.h" 00037 #include "ltiPoint.h" 00038 #include <vector> 00039 00040 namespace lti { 00041 00042 /** 00043 * This functor implements a fast line extraction 00044 * using the line segments found in digital images. 00045 * 00046 * To achieve this, the (edge-)image is decomposed into 00047 * line segments of four types (I=horizontal, II=vertical, 00048 * III=diagonal horizontal, IV=diagonal vertical) 00049 * which are recomposed to lines in a second pass. 00050 * 00051 * The fastLineExtraction::parameters specify ranges 00052 * for segments/lines and conditions that a set of 00053 * segments must fulfill to be considered as a line. 00054 * The result strongly depends on these parameters, 00055 * especially the number and the precision of the 00056 * extracted lines. 00057 * 00058 * The extracted segments and lines are stored in STL vector 00059 * containers of the type <segmEntry> and can be accessed by 00060 * the methods getSegmentList() and getLineList(). 00061 * 00062 * \c ipoint is the data type for coordinates: 00063 * <pre> typedef tpoint<int> ipoint; </pre> 00064 * 00065 * \c segmEntry is the data struct for segments/lines: 00066 * <pre> struct segmEntry 00067 * { 00068 * ipoint start; // start point of segment or line 00069 * ipoint end; // end point of segment or line 00070 * int len; // length of segment or line 00071 * int used; // counts segment<->line assignments 00072 * };</pre> 00073 * 00074 * Additionally there are two methods which return some 00075 * statistical information about the line extraction process: 00076 * getNonGroupedSegmentCount() and getMultiGroupedSegmentCount() 00077 * 00078 * The fast line extraction does not perform any changes 00079 * to the analyzed image. To visualize the extracted lines 00080 * they have to be drawn by other code using the 00081 * segment lists and a drawing functor. 00082 * 00083 * 00084 * Example: 00085 * \code 00086 * 00087 * #include "ltiViewer.h" // visualization tool 00088 * #include "ltiDraw.h" // drawing tool 00089 * #include "ltiALLfunctor.h" // image loader 00090 * #include "ltiCannyEdges.h" // edge detector 00091 * #include "ltiFastLineExtraction.h" // line detector 00092 * 00093 * // ... 00094 * 00095 * lti::image inputImg; 00096 * lti::channel8 edges; 00097 * lti::channel8 result; 00098 * 00099 * // load image 00100 * lti::loadImage loader; 00101 * loader.load("myImage.bmp", inputImg); 00102 * 00103 * // we need the edges 00104 * lti::cannyEdges canny; 00105 * canny.apply(inputImg, edges); 00106 * 00107 * // create FLE functor (using default parameters) 00108 * lti::fastLineExtraction fle; 00109 * 00110 * // extract the lines 00111 * fle.apply(m_edges); 00112 * 00113 * // get the complete line list 00114 * std::vector<lti::fastLineExtraction::segmEntry> &lines = fle.getLineList(0); 00115 * 00116 * // create a drawing functor 00117 * lti::draw<lti::channel8::value_type> drawer; 00118 * drawer.use(result); 00119 * drawer.setColor(255); 00120 * 00121 * for(int i=0; i<lines.size(); i++) { 00122 * // draw all lines 00123 * drawer.line(lines[i].start, lines[i].end); 00124 * // print line data 00125 * printf("line[%i]: start=(%i,%i) end=(%i,%i) length=%i \n", i, 00126 * lines[i].start.x, lines[i].start.y, lines[i].end.x, lines[i].end.y, lines[i].len); 00127 * } 00128 * 00129 * // show the extracted lines 00130 * lti::viewer view("Detected lines"); 00131 * view.show(result); 00132 * 00133 * // wait for a mouse click in the viewer window 00134 * view.waitButtonPressed(); 00135 * 00136 * \endcode 00137 */ 00138 00139 class fastLineExtraction : public featureExtractor { 00140 public: 00141 00142 struct segmEntry 00143 { 00144 ipoint start; // start point of segment or line 00145 ipoint end; // end point of segment or line 00146 int len; // length of segment or line 00147 int used; // counts segment<->line assignments 00148 }; 00149 00150 00151 /** 00152 * the parameters for the class fastLineExtraction 00153 */ 00154 00155 class parameters : public featureExtractor::parameters { 00156 public: 00157 /** 00158 * default constructor 00159 */ 00160 parameters(); 00161 00162 /** 00163 * copy constructor 00164 * @param other the parameters object to be copied 00165 */ 00166 parameters(const parameters& other); 00167 00168 /** 00169 * destructor 00170 */ 00171 ~parameters(); 00172 00173 /** 00174 * returns name of this type 00175 */ 00176 const char* getTypeName() const; 00177 00178 /** 00179 * copy the contents of a parameters object 00180 * @param other the parameters object to be copied 00181 * @return a reference to this parameters object 00182 */ 00183 parameters& copy(const parameters& other); 00184 00185 /** 00186 * copy the contents of a parameters object 00187 * @param other the parameters object to be copied 00188 * @return a reference to this parameters object 00189 */ 00190 parameters& operator=(const parameters& other); 00191 00192 00193 /** 00194 * returns a pointer to a clone of the parameters 00195 */ 00196 virtual functor::parameters* clone() const; 00197 00198 /** 00199 * write the parameters in the given ioHandler 00200 * @param handler the ioHandler to be used 00201 * @param complete if true (the default) the enclosing begin/end will 00202 * be also written, otherwise only the data block will be written. 00203 * @return true if write was successful 00204 */ 00205 virtual bool write(ioHandler& handler,const bool complete=true) const; 00206 00207 /** 00208 * read the parameters from the given ioHandler 00209 * @param handler the ioHandler to be used 00210 * @param complete if true (the default) the enclosing begin/end will 00211 * be also written, otherwise only the data block will be written. 00212 * @return true if write was successful 00213 */ 00214 virtual bool read(ioHandler& handler,const bool complete=true); 00215 00216 #ifdef _LTI_MSC_6 00217 /** 00218 * this function is required by MSVC only, as a workaround for a 00219 * very awful bug, which exists since MSVC V.4.0, and still by 00220 * V.6.0 with all bugfixes (so called "service packs") remains 00221 * there... This method is also public due to another bug, so please 00222 * NEVER EVER call this method directly: use read() instead 00223 */ 00224 bool readMS(ioHandler& handler,const bool complete=true); 00225 00226 /** 00227 * this function is required by MSVC only, as a workaround for a 00228 * very awful bug, which exists since MSVC V.4.0, and still by 00229 * V.6.0 with all bugfixes (so called "service packs") remains 00230 * there... This method is also public due to another bug, so please 00231 * NEVER EVER call this method directly: use write() instead 00232 */ 00233 bool writeMS(ioHandler& handler,const bool complete=true) const; 00234 #endif 00235 00236 // ------------------------------------------------ 00237 // the parameters 00238 // ------------------------------------------------ 00239 00240 00241 00242 /** This threshold constant defines the maximum mismatch 00243 * between the found line segments and the estimated analog line. 00244 * The segment is discarded if its starting/finishing pixel 00245 * differs more than \c maxQuantizationError 00246 * from the estimated analog line. 00247 * If this value is greater than 1.0 the line detection will 00248 * also extract lines that are not completely straight, which 00249 * may be useful for estimation of lines. 00250 * possible values are 00251 * <pre> 00252 * 0.5 < maxQuantizationError 00253 * </pre> 00254 * A high maxQuantizationError value will extract longer lines 00255 * at the cost of precision. Low values result in better pixel 00256 * matching but also in shorter lines. 00257 * Best compromise between pixel matching and good detection 00258 * is a value between 0.6 and 0.7 (the default is 1.0) 00259 */ 00260 float maxQuantizationError; 00261 00262 00263 /** 00264 * This constant defines how much the value of two adjacent pixels 00265 * may differ and still be considered pixels of the same segment. 00266 * A <code>segmentTolerance</code> of 0 will only group pixels 00267 * of the same value to one segment. When analyzing binary maps 00268 * such as edge-images a value of 0 should be used. 00269 * possible values are 00270 * <pre> 00271 * 0 <= segmentTolerance <= 254 00272 * </pre> 00273 * Higher segmentTolerance values allow non-binary 00274 * images to be analysed but may also result in wrong 00275 * segment start/end detection. 00276 * The default is 0 00277 */ 00278 int segmentTolerance; 00279 00280 00281 /** 00282 * The maximum gap two line segments may have and 00283 * still be considered segments of the same line. 00284 * This parameter changes the size of the searching window 00285 * for line segments. Small sizes allow fast processing but may 00286 * also cause detection failures (as well as too high values) 00287 * A <code>maxSegmentGap</code> of 1 will only group 00288 * contiguous segments to a line. 00289 * possible values are 00290 * <pre> 00291 * maxSegmentGap >= 1 (pixel) 00292 * </pre> 00293 * Higher maxSegmentGap values also allow extraction of 00294 * non-contiguous lines such as found in corrupted images. 00295 * The default is 1 00296 */ 00297 int maxSegmentGap; 00298 00299 00300 /** 00301 * The minimum length a line must have to get extracted. 00302 * The parameter \c minLineLen is used as 00303 * threshold, smaller lines will be ignored. 00304 * possible values are 00305 * <pre> 00306 * minLineLen >= 3 (pixel) 00307 * </pre> 00308 * Values greater than 3 will strongly decrease 00309 * the number of extracted lines. 00310 * The default is 3 00311 */ 00312 int minLineLen; 00313 00314 00315 /** 00316 * The minimum length a line segment must have to be detected. 00317 * The parameter <code>minSegmLen</code> is used as 00318 * threshold, smaller segments will be ignored. 00319 * Values greater than 2 strongly decrease the number 00320 * of detected segments and the size of the segment lists. 00321 * possible values are 00322 * <pre> 00323 * minSegmLen >= 2 (pixel) 00324 * </pre> 00325 * Values greater than 2 result in smaller segment lists 00326 * and therefore allow slightly faster line detection. 00327 * But mostly good line detection is more important than 00328 * a small speedup, so don't change this parameter unless 00329 * there is a good reason to do so. 00330 * The default is 2 00331 */ 00332 int minSegmLen; 00333 }; 00334 00335 //////////////////////////////////////////////////////////////////////////// 00336 00337 /** 00338 * default constructor 00339 */ 00340 fastLineExtraction(); 00341 00342 /** 00343 * Construct a functor using the given parameters 00344 */ 00345 fastLineExtraction(const parameters& par); 00346 00347 /** 00348 * copy constructor 00349 * @param other the object to be copied 00350 */ 00351 fastLineExtraction(const fastLineExtraction& other); 00352 00353 /** 00354 * destructor 00355 */ 00356 virtual ~fastLineExtraction(); 00357 00358 /** 00359 * returns the name of this type ("fastLineExtraction") 00360 */ 00361 virtual const char* getTypeName() const; 00362 00363 00364 /** 00365 * Applies fast line detection on-place. 00366 * @param srcdest channel8 with the source data. 00367 * @return true if apply was successful or false otherwise. 00368 */ 00369 bool apply(const channel8& srcdest); 00370 00371 /** 00372 * Applies fast line detection on-place. 00373 * @param srcdest channel with the source data. 00374 * @return true if apply was successful or false otherwise. 00375 */ 00376 bool apply(const channel& srcdest); 00377 00378 /** 00379 * copy data of "other" functor. 00380 * @param other the functor to be copied 00381 * @return a reference to this functor object 00382 */ 00383 fastLineExtraction& copy(const fastLineExtraction& other); 00384 00385 /** 00386 * alias for copy member 00387 * @param other the functor to be copied 00388 * @return a reference to this functor object 00389 */ 00390 fastLineExtraction& operator=(const fastLineExtraction& other); 00391 00392 /** 00393 * returns a pointer to a clone of this functor. 00394 */ 00395 virtual functor* clone() const; 00396 00397 /** 00398 * returns used parameters 00399 */ 00400 const parameters& getParameters() const; 00401 00402 /////////////////////////////////////////////////////////// 00403 00404 /** 00405 * returns a vector with line segments of the specified group 00406 * @param group_number number of the line segment group (1,2,3,4) 00407 * @return vector with detected line segments 00408 */ 00409 virtual std::vector<segmEntry>& getSegmentList(const int group_number); 00410 00411 /** 00412 * returns a vector with lines of the specified group 00413 * @param group_number number of the line group (1,2,3,4, or 0 for all lines) 00414 * @return vector with extracted lines 00415 */ 00416 virtual std::vector<segmEntry>& getLineList(const int group_number); 00417 00418 /** 00419 * returns number of segments that could not be grouped to a line 00420 * @param group_number number of the line group (1,2,3,4) 00421 * @return number of non-grouped line segments 00422 */ 00423 virtual const int getNonGroupedSegmentCount(const int group_number) const; 00424 00425 /** 00426 * returns number of segments that are used in several lines 00427 * @param group_number number of the line group (1,2,3,4) 00428 * @return number of multi-grouped line segments 00429 */ 00430 virtual const int getMultiGroupedSegmentCount(const int group_number) const; 00431 00432 00433 private: 00434 00435 /** 00436 * The segment detection methods. They detect segments by scanning pixel rows. 00437 * For performance and review reasons there are 4 methods (one per segment group). 00438 * Results are stored in STL vectors of type <segmEntry>. These vectors can 00439 * be accessed by the method getSegmentList(). 00440 * @param src channel with source data 00441 */ 00442 virtual void detectGroup1Segments(const channel8& src); 00443 virtual void detectGroup2Segments(const channel8& src); 00444 virtual void detectGroup3Segments(const channel8& src); 00445 virtual void detectGroup4Segments(const channel8& src); 00446 00447 /** 00448 * The line extraction methods. They extract lines by tracking line segments. 00449 * For performance and review reasons there are 4 methods (one per segment group). 00450 * Results are stored in STL vectors of type <segmEntry>. These vectors can 00451 * be accessed by the method getLineList(). 00452 */ 00453 virtual void extractGroup1Lines(); 00454 virtual void extractGroup2Lines(); 00455 virtual void extractGroup3Lines(); 00456 virtual void extractGroup4Lines(); 00457 00458 /** 00459 * The line containers. 00460 * m_vecLines[1..4] contain line groups I..IV, 00461 * m_vecLines[0] contains all lines. 00462 */ 00463 std::vector<segmEntry> m_vecLines[5]; 00464 00465 /** 00466 * The segment containers. (to allow easier implementation 00467 * the arraysize is 5 although only 4 conatainers are used) 00468 * m_vecSegments[1..4] contain segment groups I..IV, 00469 * m_vecSegments[0] is not used. 00470 */ 00471 std::vector<segmEntry> m_vecSegments[5]; 00472 00473 /** 00474 * The input image width. Needed for coordinate transformation 00475 * when extracting diagonal lines. 00476 */ 00477 int m_iWidth; 00478 00479 /** 00480 * The number of pre-allocated vector entries. 00481 */ 00482 static const int SegmPreallocation; 00483 static const int LinePreallocation; 00484 }; 00485 } 00486 00487 #endif