00001 /* --------------------------------------------------------------------------- 00002 Phission : 00003 Realtime Vision Processing System 00004 00005 Copyright (C) 2003-2006 Philip D.S. Thoren (pthoren@cs.uml.edu) 00006 University of Massachusetts at Lowell, 00007 Laboratory for Artificial Intelligence and Robotics 00008 00009 This file is part of Phission. 00010 00011 Phission is free software; you can redistribute it and/or modify 00012 it under the terms of the GNU Lesser General Public License as published by 00013 the Free Software Foundation; either version 2 of the License, or 00014 (at your option) any later version. 00015 00016 Phission is distributed in the hope that it will be useful, 00017 but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 GNU Lesser General Public License for more details. 00020 00021 You should have received a copy of the GNU Lesser General Public License 00022 along with Phission; if not, write to the Free Software 00023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00024 00025 ---------------------------------------------------------------------------*/ 00026 #ifdef HAVE_CONFIG_H 00027 #include <phissionconfig.h> 00028 #endif 00029 00030 #include <phStandard.h> 00031 00032 #include <cv_houghLines2_Filter.h> 00033 00034 #include <math.h> 00035 #include <cv.h> 00036 00037 #include <phError.h> 00038 #include <phMemory.h> 00039 #include <phPrint.h> 00040 00041 /* ------------------------------------------------------------------------- */ 00042 /* 00043 * This is taken from the OpenCV Manual 00044 * http://opencvlibrary.sourceforge.net/CvReference 00045 */ 00046 /* ------------------------------------------------------------------------- */ 00047 /* 00048 HoughLines2 00049 00050 Finds lines in binary image using Hough transform 00051 00052 CvSeq* cvHoughLines2( CvArr* image, void* line_storage, int method, 00053 double rho, double theta, int threshold, 00054 double param1=0, double param2=0 ); 00055 00056 image 00057 The input 8-bit single-channel binary image. In case of probabilistic 00058 method the image is modified by the function. 00059 line_storage 00060 The storage for the lines detected. It can be a memory storage (in this 00061 case a sequence of lines is created in the storage and returned by the 00062 function) or single row/single column matrix (CvMat*) of a particular 00063 type (see below) to which the lines' parameters are written. The matrix 00064 header is modified by the function so its cols or rows will contain a 00065 number of lines detected. If line_storage is a matrix and the actual 00066 number of lines exceeds the matrix size, the maximum possible number of 00067 lines is returned (in case of standard hough transform the lines are 00068 sorted by the accumulator value). 00069 method 00070 The Hough transform variant, one of: 00071 *CV_HOUGH_STANDARD - classical or standard Hough transform. Every line 00072 is represented by two floating-point numbers (?, ?), where ? is a 00073 distance between (0,0) point and the line, and ? is the angle 00074 between x-axis and the normal to the line. Thus, the matrix must 00075 be (the created sequence will be) of CV_32FC2 type. 00076 *CV_HOUGH_PROBABILISTIC - probabilistic Hough transform (more 00077 efficient in case if picture contains a few long linear 00078 segments). It returns line segments rather than the whole lines. 00079 Every segment is represented by starting and ending points, and 00080 the matrix must be (the created sequence will be) of CV_32SC4 type. 00081 *CV_HOUGH_MULTI_SCALE - multi-scale variant of classical Hough 00082 transform. The lines are encoded the same way as in 00083 CV_HOUGH_STANDARD. 00084 rho 00085 Distance resolution in pixel-related units. 00086 theta 00087 Angle resolution measured in radians. 00088 threshold 00089 Threshold parameter. A line is returned by the function if the 00090 corresponding accumulator value is greater than threshold. 00091 param1 00092 The first method-dependent parameter: 00093 *For classical Hough transform it is not used (0). 00094 *For probabilistic Hough transform it is the minimum line length. 00095 *For multi-scale Hough transform it is divisor for distance 00096 resolution rho. (The coarse distance resolution will be rho and 00097 the accurate resolution will be (rho / param1)). 00098 param2 00099 The second method-dependent parameter: 00100 *For classical Hough transform it is not used (0). 00101 *For probabilistic Hough transform it is the maximum gap between 00102 line segments lieing on the same line to treat them as the single 00103 line segment (i.e. to join them). 00104 *For multi-scale Hough transform it is divisor for angle resolution 00105 theta. (The coarse angle resolution will be theta and the accurate 00106 resolution will be (theta / param2)). 00107 */ 00108 /* ------------------------------------------------------------------------- */ 00109 /* ------------------------------------------------------------------------- */ 00110 cv_houghLines2_Filter::cv_houghLines2_Filter( phHoughMethod method, 00111 int draw_lines, 00112 double dRho, 00113 double dTheta, 00114 int threshold, 00115 double param1, 00116 double param2 ): 00117 phFilter("cv_houghLines2_Filter") 00118 00119 { 00120 this->m_format = phImageRGBA32 | 00121 phImageRGB24 | 00122 phImageGREY8; 00123 00124 this->m_draw_lines = 1; 00125 this->m_lines = NULL; 00126 this->m_lines_size = 0; 00127 00128 this->m_lastDepth = 0; 00129 this->m_lastWidth = 0; 00130 this->m_lastHeight = 0; 00131 00132 this->m_cv_temp = NULL; 00133 this->m_cv_input = NULL; 00134 this->m_cv_gray = NULL; 00135 this->m_storage = cvCreateMemStorage(0); 00136 00137 this->m_hough_data = new phHoughData(); 00138 00139 this->set( method, draw_lines, 00140 dRho, dTheta, threshold, param1, param2 ); 00141 } 00142 00143 /* ---------------------------------------------------------------------- */ 00144 cv_houghLines2_Filter::~cv_houghLines2_Filter() 00145 { 00146 CvMemStorage *storage = (CvMemStorage *)this->m_storage; 00147 IplImage *tmp = NULL; 00148 00149 if (this->m_cv_input != NULL) 00150 { 00151 cvSetData( ((IplImage *)this->m_cv_input), NULL, 0 ); 00152 tmp = ((IplImage *)this->m_cv_input); 00153 cvReleaseImageHeader(&tmp); 00154 } 00155 00156 if (this->m_cv_gray != NULL) 00157 { 00158 tmp = ((IplImage *)this->m_cv_gray); 00159 cvReleaseImage(&tmp); 00160 } 00161 00162 if (this->m_cv_temp != NULL) 00163 { 00164 tmp = ((IplImage *)this->m_cv_temp); 00165 cvReleaseImage(&tmp); 00166 } 00167 if (storage != NULL) 00168 { 00169 cvReleaseMemStorage( &storage ); 00170 } 00171 } 00172 00173 /* ------------------------------------------------------------------------ */ 00174 phFilter *cv_houghLines2_Filter::cloneFilter() 00175 { 00176 phFUNCTION("cv_houghLines2_Filter::cloneFilter") 00177 int locked = 0; 00178 cv_houghLines2_Filter *cv_houghLines2 = new cv_houghLines2_Filter(); 00179 00180 phTHIS_LOOSE_LOCK(locked); 00181 00182 cv_houghLines2->set(this->m_method, 00183 this->m_draw_lines, 00184 this->m_dRho, 00185 this->m_dTheta, 00186 this->m_threshold, 00187 this->m_param1, 00188 this->m_param2 ); 00189 00190 phTHIS_LOOSE_UNLOCK(locked); 00191 00192 return (phFilter *)cv_houghLines2; 00193 } 00194 00195 /* ---------------------------------------------------------------------- */ 00196 int cv_houghLines2_Filter::set( phHoughMethod method, 00197 int draw_lines, 00198 double dRho, 00199 double dTheta, 00200 int threshold, 00201 double param1, 00202 double param2 ) 00203 { 00204 phFUNCTION("cv_houghLines2_Filter::set") 00205 int locked = 0; 00206 00207 /* LOOSE locking means that if it fails it won't adjust 'locked' and 00208 * it will continue with the main body of this method */ 00209 phTHIS_LOOSE_LOCK(locked); 00210 00211 this->m_method = method; 00212 this->m_draw_lines = draw_lines; 00213 this->m_dRho = dRho; 00214 this->m_dTheta = dTheta; 00215 this->m_threshold = threshold; 00216 this->m_param1 = param1; 00217 this->m_param2 = param2; 00218 00219 phTHIS_LOOSE_UNLOCK(locked); 00220 00221 return phSUCCESS; 00222 } 00223 00224 /* ---------------------------------------------------------------------- */ 00225 int cv_houghLines2_Filter::setMethod ( phHoughMethod method ) 00226 { 00227 phFUNCTION("cv_houghLines2_Filter::setMethod") 00228 int locked = 0; 00229 00230 phTHIS_LOOSE_LOCK(locked); 00231 00232 this->m_method = method; 00233 00234 phTHIS_LOOSE_UNLOCK(locked); 00235 00236 return phSUCCESS; 00237 } 00238 00239 /* ---------------------------------------------------------------------- */ 00240 int cv_houghLines2_Filter::setRho ( double dRho ) 00241 { 00242 phFUNCTION("cv_houghLines2_Filter::setRho") 00243 int locked = 0; 00244 00245 phTHIS_LOOSE_LOCK(locked); 00246 00247 this->m_dRho = dRho; 00248 00249 phTHIS_LOOSE_UNLOCK(locked); 00250 00251 return phSUCCESS; 00252 } 00253 00254 /* ---------------------------------------------------------------------- */ 00255 int cv_houghLines2_Filter::setTheta ( double dTheta ) 00256 { 00257 phFUNCTION("cv_houghLines2_Filter::setTheta") 00258 int locked = 0; 00259 00260 phTHIS_LOOSE_LOCK(locked); 00261 00262 this->m_dTheta = dTheta; 00263 00264 phTHIS_LOOSE_UNLOCK(locked); 00265 00266 return phSUCCESS; 00267 } 00268 00269 /* ---------------------------------------------------------------------- */ 00270 int cv_houghLines2_Filter::setDrawLines( int draw_lines ) 00271 { 00272 phFUNCTION("cv_houghLines2_Filter::setDrawLines") 00273 int locked = 0; 00274 00275 phTHIS_LOOSE_LOCK(locked); 00276 00277 this->m_draw_lines = draw_lines; 00278 00279 phTHIS_LOOSE_UNLOCK(locked); 00280 00281 return phSUCCESS; 00282 } 00283 00284 /* ---------------------------------------------------------------------- */ 00285 int cv_houghLines2_Filter::setThreshold( int threshold ) 00286 { 00287 phFUNCTION("cv_houghLines2_Filter::setThreshold") 00288 int locked = 0; 00289 00290 phTHIS_LOOSE_LOCK(locked); 00291 00292 this->m_threshold = threshold; 00293 00294 phTHIS_LOOSE_UNLOCK(locked); 00295 00296 return phSUCCESS; 00297 } 00298 00299 /* ---------------------------------------------------------------------- */ 00300 int cv_houghLines2_Filter::setParam1 ( double param1 ) 00301 { 00302 phFUNCTION("cv_houghLines2_Filter::setParam1") 00303 int locked = 0; 00304 00305 phTHIS_LOOSE_LOCK(locked); 00306 00307 this->m_param1 = param1; 00308 00309 phTHIS_LOOSE_UNLOCK(locked); 00310 00311 return phSUCCESS; 00312 } 00313 00314 /* ---------------------------------------------------------------------- */ 00315 int cv_houghLines2_Filter::setParam2 ( double param2 ) 00316 { 00317 phFUNCTION("cv_houghLines2_Filter::setParam2") 00318 int locked = 0; 00319 00320 phTHIS_LOOSE_LOCK(locked); 00321 00322 this->m_param2 = param2; 00323 00324 phTHIS_LOOSE_UNLOCK(locked); 00325 00326 return phSUCCESS; 00327 } 00328 00329 /* ---------------------------------------------------------------------- */ 00330 int cv_houghLines2_Filter::get( phHoughMethod *method, 00331 int *draw_lines, 00332 double *dRho, 00333 double *dTheta, 00334 int *threshold, 00335 double *param1, 00336 double *param2 ) 00337 { 00338 phFUNCTION("cv_houghLines2_Filter::get") 00339 00340 int locked = 0; 00341 phTHIS_LOOSE_LOCK(locked); 00342 00343 if (draw_lines != NULL)*draw_lines = this->m_draw_lines; 00344 if (method != NULL) *method = this->m_method; 00345 if (dRho != NULL) *dRho = this->m_dRho; 00346 if (dTheta != NULL) *dTheta = this->m_dTheta; 00347 if (threshold != NULL) *threshold = this->m_threshold; 00348 if (param1 != NULL) *param1 = this->m_param1; 00349 if (param2 != NULL) *param2 = this->m_param2; 00350 00351 phTHIS_LOOSE_UNLOCK(locked); 00352 00353 return phSUCCESS; 00354 } 00355 00356 /* ---------------------------------------------------------------------- */ 00357 phHoughMethod cv_houghLines2_Filter::getMethod () 00358 { 00359 return this->m_method; 00360 } 00361 00362 /* ---------------------------------------------------------------------- */ 00363 int cv_houghLines2_Filter::getDrawLines() 00364 { 00365 return this->m_draw_lines; 00366 } 00367 00368 /* ---------------------------------------------------------------------- */ 00369 double cv_houghLines2_Filter::getRho () 00370 { 00371 return this->m_dRho; 00372 } 00373 00374 /* ---------------------------------------------------------------------- */ 00375 double cv_houghLines2_Filter::getTheta () 00376 { 00377 return this->m_dTheta; 00378 } 00379 00380 /* ---------------------------------------------------------------------- */ 00381 int cv_houghLines2_Filter::getThreshold() 00382 { 00383 return this->m_threshold; 00384 } 00385 00386 /* ---------------------------------------------------------------------- */ 00387 double cv_houghLines2_Filter::getParam1 () 00388 { 00389 return this->m_param1; 00390 } 00391 00392 /* ---------------------------------------------------------------------- */ 00393 double cv_houghLines2_Filter::getParam2 () 00394 { 00395 return this->m_param2; 00396 } 00397 00398 /* ---------------------------------------------------------------------- */ 00399 phHoughData *cv_houghLines2_Filter::getLiveHoughData() 00400 { 00401 return this->m_hough_data; 00402 } 00403 00404 /* ---------------------------------------------------------------------- */ 00405 phHoughData *cv_houghLines2_Filter::getOutput() 00406 { 00407 return this->m_hough_data; 00408 } 00409 00410 /* ---------------------------------------------------------------------- */ 00411 int cv_houghLines2_Filter::filter() 00412 { 00413 phFUNCTION("cv_houghLines2_Filter::filter") 00414 00415 /* defined before being called: 00416 * width, height, depth, format, Image 00417 */ 00418 int color_to_gray = 0; 00419 int gray_to_color = 0; 00420 int convert = 0; 00421 int alloc1 = 0; 00422 int alloc2 = 0; 00423 00424 CvSeq *lines = NULL; 00425 IplImage *tmp = NULL; 00426 IplImage *hough_input = NULL; 00427 int hough_method = 0; 00428 00429 /* Begin Filter */ 00430 /* Check the width and height from the previous iteration to make sure that 00431 * they are the same, otherwise we need to reallocate the IplImage * 00432 * information for the input, grey and output */ 00433 if ((this->m_lastWidth != width) || (this->m_lastHeight != height)) 00434 { 00435 /* alloc1: input */ 00436 alloc1 = alloc2 = 1; 00437 } 00438 00439 if ((this->m_cv_input == NULL) || (this->m_lastDepth != depth)) 00440 { 00441 alloc1 = 1; 00442 } 00443 00444 /* INPUT SETUP */ 00445 if (alloc1) 00446 { 00447 /* If the iinformatioin was previously allocated, free it */ 00448 if (this->m_cv_input != NULL) 00449 { 00450 IplImage *tmp = NULL; 00451 cvSetData( ((IplImage *)this->m_cv_input), NULL, 0 ); 00452 tmp = ((IplImage *)this->m_cv_input); 00453 cvReleaseImageHeader(&tmp); 00454 } 00455 00456 /* Allocate the input header for the input data */ 00457 this->m_cv_input = 00458 cvCreateImageHeader( cvSize(width,height), 00459 IPL_DEPTH_8U, 00460 depth ); 00461 } 00462 00463 /* FOR INPUT->GRAYSCALE CONVERSION */ 00464 if (alloc2) 00465 { 00466 /* If the grayscale data was previously allocated, free it */ 00467 if (this->m_cv_gray != NULL) 00468 { 00469 tmp = ((IplImage *)this->m_cv_gray); 00470 cvReleaseImage(&tmp); 00471 } 00472 00473 /* Allocate the gray scale image */ 00474 this->m_cv_gray = cvCreateImage( cvSize(width,height), 00475 IPL_DEPTH_8U, 00476 1 ); 00477 } 00478 00479 /* Set the data into the IplImage object because we only allocated the 00480 * header for the input image. This way we don't need to allocate more data 00481 * than we need since the input is a read only thing here */ 00482 cvSetData( ((IplImage *)this->m_cv_input), 00483 Image, 00484 width * depth * sizeof(uint8_t) ); 00485 00486 /* keep track of the last run's sizes so we know if we need to reallocate on 00487 * the next iteration of this filter */ 00488 this->m_lastDepth = depth; 00489 this->m_lastWidth = width; 00490 this->m_lastHeight = height; 00491 00492 /* DECIDE WHETHER TO CONVERT */ 00493 00494 /* Check the format of the incoming data and convert it to greyscale if it's 00495 * required. */ 00496 switch (format) 00497 { 00498 case phImageRGB24: 00499 convert = 1; 00500 color_to_gray = CV_RGB2GRAY; 00501 gray_to_color = CV_GRAY2RGB; 00502 break; 00503 case phImageRGBA32: 00504 convert = 1; 00505 color_to_gray = CV_RGBA2GRAY; 00506 gray_to_color = CV_GRAY2RGBA; 00507 break; 00508 case phImageGREY8: 00509 convert = 0; 00510 break; 00511 } 00512 00513 /* CONVERT FILTER INPUT TO HOUGH INPUT FORMAT */ 00514 00515 /* If we decided to convert, then do it and set the hough_input pointer to 00516 * point to which ever image is the input to the function */ 00517 if (convert) 00518 { 00519 cvCvtColor( ((IplImage *)this->m_cv_input), 00520 ((IplImage *)this->m_cv_gray), 00521 color_to_gray ); 00522 hough_input = ((IplImage *)this->m_cv_gray); 00523 } 00524 else 00525 { 00526 /* If the image isn't being converted to grayscale then we need to make 00527 * a copy of the input image because it will be changed when using 00528 * Probalistic 00529 */ 00530 if (this->m_method == phHoughProbalistic) 00531 { 00532 if (this->m_cv_temp != NULL) 00533 { 00534 tmp = ((IplImage *)this->m_cv_temp); 00535 cvReleaseImage(&tmp); 00536 } 00537 /* make a copy of the input image */ 00538 this->m_cv_temp = cvCloneImage( (IplImage *)this->m_cv_input ); 00539 00540 hough_input = ((IplImage *)this->m_cv_temp); 00541 } 00542 else 00543 { 00544 hough_input = ((IplImage *)this->m_cv_input); 00545 } 00546 //cvCopy(input,((IplImage *)this->m_cv_gray)); 00547 } 00548 00549 /* Set up the translation from Phission land to CV land for the method */ 00550 switch (this->m_method) 00551 { 00552 case phHoughStandard: 00553 hough_method = CV_HOUGH_STANDARD; 00554 break; 00555 case phHoughMultiScale: 00556 hough_method = CV_HOUGH_MULTI_SCALE; 00557 break; 00558 default: /* case phHoughProbalistic: */ 00559 hough_method = CV_HOUGH_PROBABILISTIC; 00560 break; 00561 } 00562 00563 /* Translate the classical hough lines */ 00564 if ((this->m_method == phHoughStandard) || 00565 (this->m_method == phHoughMultiScale)) 00566 { 00567 int i = 0; 00568 float *line = NULL; 00569 float rho = 0.0; 00570 float theta = 0.0; 00571 double a = 0.0; 00572 double b = 0.0; 00573 CvPoint pt1; 00574 CvPoint pt2; 00575 00576 phLine l; 00577 00578 /* DO IT! */ 00579 lines = cvHoughLines2( hough_input, 00580 (CvMemStorage *)this->m_storage, 00581 hough_method, 00582 this->m_dRho, 00583 this->m_dTheta, 00584 this->m_threshold, 00585 this->m_param1, 00586 this->m_param2 ); 00587 00588 /* Allocate our private line array */ 00589 this->m_line_count = lines->total; 00590 phDALLOC(this->m_lines, 00591 this->m_lines_size, 00592 this->m_line_count, 00593 phLine); 00594 00595 for( i = 0; i < lines->total; i++ ) 00596 { 00597 line = (float*)cvGetSeqElem(lines,i); 00598 rho = line[0]; 00599 theta = line[1]; 00600 a = cos(theta); 00601 b = sin(theta); 00602 00603 if( fabs(a) < 0.001 ) 00604 { 00605 pt1.x = pt2.x = l.x1 = l.x2 = cvRound(rho); 00606 pt1.y = l.y1 = 0; 00607 pt2.y = l.y2 = height; 00608 } 00609 else if( fabs(b) < 0.001 ) 00610 { 00611 pt1.y = pt2.y = l.y1 = l.y2 = cvRound(rho); 00612 pt1.x = l.x1 = 0; 00613 pt2.x = l.x2 = width; 00614 } 00615 else 00616 { 00617 pt1.x = l.x1 = 0; 00618 pt1.y = l.y1 = cvRound(rho/b); 00619 pt2.x = l.x2 = cvRound(rho/a); 00620 pt2.y = l.y2 = 0; 00621 } 00622 00623 /* Copy it into the private temp array */ 00624 this->m_lines[i] = l; 00625 00626 /* if we want to color lines on the image */ 00627 if (this->m_draw_lines) 00628 { 00629 if (depth == 1) 00630 cvLine( this->m_cv_input, 00631 pt1, 00632 pt2, 00633 cvScalarAll(128), 00634 1, 00635 8 ); 00636 else 00637 cvLine( this->m_cv_input, 00638 pt1, 00639 pt2, 00640 CV_RGB(255,0,0), 00641 1, 00642 8 ); 00643 } 00644 } 00645 } 00646 else if (this->m_method == phHoughProbalistic) 00647 { 00648 int i = 0; 00649 CvPoint *line = NULL; 00650 phLine l; 00651 00652 lines = cvHoughLines2( hough_input, 00653 (CvMemStorage *)this->m_storage, 00654 hough_method, 00655 this->m_dRho, 00656 this->m_dTheta, 00657 this->m_threshold, 00658 this->m_param1, 00659 this->m_param2 ); 00660 00661 /* Allocate our private line array */ 00662 this->m_line_count = lines->total; 00663 if (this->m_line_count > 0) 00664 { 00665 phDALLOC(this->m_lines, 00666 this->m_lines_size, 00667 this->m_line_count, 00668 phLine ); 00669 } 00670 00671 for( i = 0; i < lines->total; i++ ) 00672 { 00673 line = (CvPoint*)cvGetSeqElem(lines,i); 00674 00675 l.x1 = line[0].x; 00676 l.y1 = line[0].y; 00677 l.x2 = line[1].x; 00678 l.y2 = line[1].y; 00679 00680 /* Copy it into the private temp array */ 00681 this->m_lines[i] = l; 00682 00683 /* if we want to color lines on the image */ 00684 if (this->m_draw_lines) 00685 { 00686 if (depth == 1) 00687 cvLine( this->m_cv_input, 00688 line[0], 00689 line[1], 00690 cvScalarAll(128), 00691 1, 00692 8 ); 00693 else 00694 cvLine( this->m_cv_input, 00695 line[0], 00696 line[1], 00697 CV_RGB(255,0,0), 00698 1, 00699 8 ); 00700 } 00701 } 00702 } 00703 00704 rc = this->m_hough_data->setData(this->m_lines, 00705 this->m_line_count); 00706 phPRINT_RC(rc,NULL,"this->m_hough_data->setData"); 00707 00708 /* End Filter */ 00709 00710 /* make sure to free up any space here, not including Image */ 00711 00712 return phSUCCESS; 00713 00714 error: 00715 /* make sure to free up any space here, not including Image */ 00716 00717 return phFAIL; 00718 00719 } 00720 00721
Copyright (C) 2002 - 2007 |
Philip D.S. Thoren ( pthoren@users.sourceforge.net ) University Of Massachusetts at Lowell Robotics Lab |