1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
42 #include "precomp.hpp"
45 #define halfPi ((float)(CV_PI*0.5))
46 #define Pi ((float)CV_PI)
47 #define a0 0 /*-4.172325e-7f*/ /*(-(float)0x7)/((float)0x1000000); */
48 #define a1 1.000025f /*((float)0x1922253)/((float)0x1000000)*2/Pi; */
49 #define a2 -2.652905e-4f /*(-(float)0x2ae6)/((float)0x1000000)*4/(Pi*Pi); */
50 #define a3 -0.165624f /*(-(float)0xa45511)/((float)0x1000000)*8/(Pi*Pi*Pi); */
51 #define a4 -1.964532e-3f /*(-(float)0x30fd3)/((float)0x1000000)*16/(Pi*Pi*Pi*Pi); */
52 #define a5 1.02575e-2f /*((float)0x191cac)/((float)0x1000000)*32/(Pi*Pi*Pi*Pi*Pi); */
53 #define a6 -9.580378e-4f /*(-(float)0x3af27)/((float)0x1000000)*64/(Pi*Pi*Pi*Pi*Pi*Pi); */
55 #define _sin(x) ((((((a6*(x) + a5)*(x) + a4)*(x) + a3)*(x) + a2)*(x) + a1)*(x) + a0)
56 #define _cos(x) _sin(halfPi - (x))
58 /****************************************************************************************\
59 * Classical Hough Transform *
60 \****************************************************************************************/
62 typedef struct CvLinePolar
69 /*=====================================================================================*/
71 #define hough_cmp_gt(l1,l2) (aux[l1] > aux[l2])
73 static CV_IMPLEMENT_QSORT_EX( icvHoughSortDescent32s, int, hough_cmp_gt, const int* )
76 Here image is an input raster;
77 step is it's step; size characterizes it's ROI;
78 rho and theta are discretization steps (in pixels and radians correspondingly).
79 threshold is the minimum number of pixels in the feature for it
80 to be a candidate for line. lines is the output
81 array of (rho, theta) pairs. linesMax is the buffer size (number of pairs).
82 Functions return the actual number of found lines.
85 icvHoughLinesStandard( const CvMat* img, float rho, float theta,
86 int threshold, CvSeq *lines, int linesMax )
88 cv::AutoBuffer<int> _accum, _sort_buf;
89 cv::AutoBuffer<float> _tabSin, _tabCos;
92 int step, width, height;
99 CV_Assert( CV_IS_MAT(img) && CV_MAT_TYPE(img->type) == CV_8UC1 );
101 image = img->data.ptr;
106 numangle = cvRound(CV_PI / theta);
107 numrho = cvRound(((width + height) * 2 + 1) / rho);
109 _accum.allocate((numangle+2) * (numrho+2));
110 _sort_buf.allocate(numangle * numrho);
111 _tabSin.allocate(numangle);
112 _tabCos.allocate(numangle);
113 int *accum = _accum, *sort_buf = _sort_buf;
114 float *tabSin = _tabSin, *tabCos = _tabCos;
116 memset( accum, 0, sizeof(accum[0]) * (numangle+2) * (numrho+2) );
119 for(int n = 0; n < numangle; ang += theta, n++ )
121 tabSin[n] = (float)(sin((double)ang) * irho);
122 tabCos[n] = (float)(cos((double)ang) * irho);
125 // stage 1. fill accumulator
126 for( i = 0; i < height; i++ )
127 for( j = 0; j < width; j++ )
129 if( image[i * step + j] != 0 )
130 for(int n = 0; n < numangle; n++ )
132 int r = cvRound( j * tabCos[n] + i * tabSin[n] );
133 r += (numrho - 1) / 2;
134 accum[(n+1) * (numrho+2) + r+1]++;
138 // stage 2. find local maximums
139 for(int r = 0; r < numrho; r++ )
140 for(int n = 0; n < numangle; n++ )
142 int base = (n+1) * (numrho+2) + r+1;
143 if( accum[base] > threshold &&
144 accum[base] > accum[base - 1] && accum[base] >= accum[base + 1] &&
145 accum[base] > accum[base - numrho - 2] && accum[base] >= accum[base + numrho + 2] )
146 sort_buf[total++] = base;
149 // stage 3. sort the detected lines by accumulator value
150 icvHoughSortDescent32s( sort_buf, total, accum );
152 // stage 4. store the first min(total,linesMax) lines to the output buffer
153 linesMax = MIN(linesMax, total);
154 scale = 1./(numrho+2);
155 for( i = 0; i < linesMax; i++ )
158 int idx = sort_buf[i];
159 int n = cvFloor(idx*scale) - 1;
160 int r = idx - (n+1)*(numrho+2) - 1;
161 line.rho = (r - (numrho - 1)*0.5f) * rho;
162 line.angle = n * theta;
163 cvSeqPush( lines, &line );
168 /****************************************************************************************\
169 * Multi-Scale variant of Classical Hough Transform *
170 \****************************************************************************************/
172 //DECLARE_AND_IMPLEMENT_LIST( _index, h_ );
173 IMPLEMENT_LIST( _index, h_ )
176 icvHoughLinesSDiv( const CvMat* img,
177 float rho, float theta, int threshold,
179 CvSeq* lines, int linesMax )
181 std::vector<uchar> _caccum, _buffer;
182 std::vector<float> _sinTable;
183 std::vector<int> _x, _y;
186 uchar *caccum, *buffer;
189 #define _POINT(row, column)\
190 (image_src[(row)*step+(column)])
193 int rn, tn; /* number of rho and theta discrete values */
195 int ri, ti, ti1, ti0;
197 float r, t; /* Current rho and theta */
198 float rv; /* Some temporary rho value */
202 float isrho, istheta;
204 const uchar* image_src;
209 const float d2r = (float)(Pi / 180);
219 CV_Assert( CV_IS_MAT(img) && CV_MAT_TYPE(img->type) == CV_8UC1 );
220 CV_Assert( linesMax > 0 && rho > 0 && theta > 0 );
222 threshold = MIN( threshold, 255 );
224 image_src = img->data.ptr;
232 stheta = theta / stn;
234 istheta = 1 / stheta;
236 rn = cvFloor( sqrt( (double)w * w + (double)h * h ) * irho );
237 tn = cvFloor( 2 * Pi * itheta );
239 list = h_create_list__index( linesMax < 1000 ? linesMax : 1000 );
240 vi.value = threshold;
242 h_add_head__index( list, &vi );
244 /* Precalculating sin */
245 _sinTable.resize( 5 * tn * stn );
246 sinTable = &_sinTable[0];
248 for( index = 0; index < 5 * tn * stn; index++ )
249 sinTable[index] = (float)cos( stheta * index * 0.2f );
251 _caccum.resize(rn * tn);
252 caccum = &_caccum[0];
253 memset( caccum, 0, rn * tn * sizeof( caccum[0] ));
255 /* Counting all feature pixels */
256 for( row = 0; row < h; row++ )
257 for( col = 0; col < w; col++ )
258 fn += _POINT( row, col ) != 0;
265 /* Full Hough Transform (it's accumulator update part) */
267 for( row = 0; row < h; row++ )
269 for( col = 0; col < w; col++ )
271 if( _POINT( row, col ))
278 float theta_it; /* Value of theta for iterating */
280 /* Remember the feature point */
285 yc = (float) row + 0.5f;
286 xc = (float) col + 0.5f;
288 /* Update the accumulator */
289 t = (float) fabs( cvFastArctan( yc, xc ) * d2r );
290 r = (float) sqrt( (double)xc * xc + (double)yc * yc );
292 ti0 = cvFloor( (t + Pi / 2) * itheta );
297 theta_it = theta_it < theta ? theta_it : theta;
298 scale_factor = theta_it * itheta;
299 halftn = cvFloor( Pi / theta_it );
300 for( ti1 = 1, phi = theta_it - halfPi, phi1 = (theta_it + t) * itheta;
301 ti1 < halftn; ti1++, phi += theta_it, phi1 += scale_factor )
303 rv = r0 * _cos( phi );
304 i = cvFloor( rv ) * tn;
305 i += cvFloor( phi1 );
307 assert( i < rn * tn );
308 caccum[i] = (uchar) (caccum[i] + ((i ^ iprev) != 0));
310 if( cmax < caccum[i] )
317 /* Starting additional analysis */
319 for( ri = 0; ri < rn; ri++ )
321 for( ti = 0; ti < tn; ti++ )
323 if( caccum[ri * tn + ti] > threshold )
330 if( count * 100 > rn * tn )
332 icvHoughLinesStandard( img, rho, theta, threshold, lines, linesMax );
336 _buffer.resize(srn * stn + 2);
337 buffer = &_buffer[0];
338 mcaccum = buffer + 1;
341 for( ri = 0; ri < rn; ri++ )
343 for( ti = 0; ti < tn; ti++ )
345 if( caccum[ri * tn + ti] > threshold )
348 memset( mcaccum, 0, sfn * sizeof( uchar ));
350 for( index = 0; index < fn; index++ )
355 yc = (float) y[index] + 0.5f;
356 xc = (float) x[index] + 0.5f;
358 /* Update the accumulator */
359 t = (float) fabs( cvFastArctan( yc, xc ) * d2r );
360 r = (float) sqrt( (double)xc * xc + (double)yc * yc ) * isrho;
361 ti0 = cvFloor( (t + Pi * 0.5f) * istheta );
362 ti2 = (ti * stn - ti0) * 5;
363 r0 = (float) ri *srn;
365 for( ti1 = 0 /*, phi = ti*theta - Pi/2 - t */ ; ti1 < stn; ti1++, ti2 += 5
368 /*rv = r*_cos(phi) - r0; */
369 rv = r * sinTable[(int) (abs( ti2 ))] - r0;
370 i = cvFloor( rv ) * stn + ti1;
372 i = CV_IMAX( i, -1 );
373 i = CV_IMIN( i, sfn );
380 /* Find peaks in maccum... */
381 for( index = 0; index < sfn; index++ )
384 pos = h_get_tail_pos__index( list );
385 if( h_get_prev__index( &pos )->value < mcaccum[index] )
387 vi.value = mcaccum[index];
388 vi.rho = index / stn * srho + ri * rho;
389 vi.theta = index % stn * stheta + ti * theta - halfPi;
390 while( h_is_pos__index( pos ))
392 if( h_get__index( pos )->value > mcaccum[index] )
394 h_insert_after__index( list, pos, &vi );
395 if( h_get_count__index( list ) > linesMax )
397 h_remove_tail__index( list );
401 h_get_prev__index( &pos );
403 if( !h_is_pos__index( pos ))
405 h_add_head__index( list, &vi );
406 if( h_get_count__index( list ) > linesMax )
408 h_remove_tail__index( list );
417 pos = h_get_head_pos__index( list );
418 if( h_get_count__index( list ) == 1 )
420 if( h_get__index( pos )->rho < 0 )
422 h_clear_list__index( list );
427 while( h_is_pos__index( pos ))
430 pindex = h_get__index( pos );
431 if( pindex->rho < 0 )
433 /* This should be the last element... */
434 h_get_next__index( &pos );
435 assert( !h_is_pos__index( pos ));
438 line.rho = pindex->rho;
439 line.angle = pindex->theta;
440 cvSeqPush( lines, &line );
442 if( lines->total >= linesMax )
444 h_get_next__index( &pos );
448 h_destroy_list__index(list);
452 /****************************************************************************************\
453 * Probabilistic Hough Transform *
454 \****************************************************************************************/
457 icvHoughLinesProbabilistic( CvMat* image,
458 float rho, float theta, int threshold,
459 int lineLength, int lineGap,
460 CvSeq *lines, int linesMax )
463 cv::vector<float> trigtab;
464 cv::MemStorage storage(cvCreateMemStorage(0));
469 int numangle, numrho;
473 float irho = 1 / rho;
474 CvRNG rng = cvRNG(-1);
478 CV_Assert( CV_IS_MAT(image) && CV_MAT_TYPE(image->type) == CV_8UC1 );
481 height = image->rows;
483 numangle = cvRound(CV_PI / theta);
484 numrho = cvRound(((width + height) * 2 + 1) / rho);
486 accum.create( numangle, numrho, CV_32SC1 );
487 mask.create( height, width, CV_8UC1 );
488 trigtab.resize(numangle*2);
489 accum = cv::Scalar(0);
491 for( ang = 0, n = 0; n < numangle; ang += theta, n++ )
493 trigtab[n*2] = (float)(cos(ang) * irho);
494 trigtab[n*2+1] = (float)(sin(ang) * irho);
499 cvStartWriteSeq( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage, &writer );
501 // stage 1. collect non-zero image points
502 for( pt.y = 0, count = 0; pt.y < height; pt.y++ )
504 const uchar* data = image->data.ptr + pt.y*image->step;
505 uchar* mdata = mdata0 + pt.y*width;
506 for( pt.x = 0; pt.x < width; pt.x++ )
510 mdata[pt.x] = (uchar)1;
511 CV_WRITE_SEQ_ELEM( pt, writer );
518 seq = cvEndWriteSeq( &writer );
521 // stage 2. process all the points in random order
522 for( ; count > 0; count-- )
524 // choose random point out of the remaining ones
525 int idx = cvRandInt(&rng) % count;
526 int max_val = threshold-1, max_n = 0;
527 CvPoint* point = (CvPoint*)cvGetSeqElem( seq, idx );
528 CvPoint line_end[2] = {{0,0}, {0,0}};
530 int* adata = (int*)accum.data;
531 int i, j, k, x0, y0, dx0, dy0, xflag;
533 const int shift = 16;
538 // "remove" it by overriding it with the last element
539 *point = *(CvPoint*)cvGetSeqElem( seq, count-1 );
541 // check if it has been excluded already (i.e. belongs to some other line)
542 if( !mdata0[i*width + j] )
545 // update accumulator, find the most probable line
546 for( n = 0; n < numangle; n++, adata += numrho )
548 r = cvRound( j * ttab[n*2] + i * ttab[n*2+1] );
549 r += (numrho - 1) / 2;
550 int val = ++adata[r];
558 // if it is too "weak" candidate, continue with another point
559 if( max_val < threshold )
562 // from the current point walk in each direction
563 // along the found line and extract the line segment
564 a = -ttab[max_n*2+1];
568 if( fabs(a) > fabs(b) )
571 dx0 = a > 0 ? 1 : -1;
572 dy0 = cvRound( b*(1 << shift)/fabs(a) );
573 y0 = (y0 << shift) + (1 << (shift-1));
578 dy0 = b > 0 ? 1 : -1;
579 dx0 = cvRound( a*(1 << shift)/fabs(b) );
580 x0 = (x0 << shift) + (1 << (shift-1));
583 for( k = 0; k < 2; k++ )
585 int gap = 0, x = x0, y = y0, dx = dx0, dy = dy0;
590 // walk along the line using fixed-point arithmetics,
591 // stop at the image border or in case of too big gap
592 for( ;; x += dx, y += dy )
608 if( j1 < 0 || j1 >= width || i1 < 0 || i1 >= height )
611 mdata = mdata0 + i1*width + j1;
613 // for each non-zero point:
615 // clear the mask element
623 else if( ++gap > lineGap )
628 good_line = abs(line_end[1].x - line_end[0].x) >= lineLength ||
629 abs(line_end[1].y - line_end[0].y) >= lineLength;
631 for( k = 0; k < 2; k++ )
633 int x = x0, y = y0, dx = dx0, dy = dy0;
638 // walk along the line using fixed-point arithmetics,
639 // stop at the image border or in case of too big gap
640 for( ;; x += dx, y += dy )
656 mdata = mdata0 + i1*width + j1;
658 // for each non-zero point:
660 // clear the mask element
666 adata = (int*)accum.data;
667 for( n = 0; n < numangle; n++, adata += numrho )
669 r = cvRound( j1 * ttab[n*2] + i1 * ttab[n*2+1] );
670 r += (numrho - 1) / 2;
677 if( i1 == line_end[k].y && j1 == line_end[k].x )
684 CvRect lr = { line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y };
685 cvSeqPush( lines, &lr );
686 if( lines->total >= linesMax )
692 /* Wrapper function for standard hough transform */
694 cvHoughLines2( CvArr* src_image, void* lineStorage, int method,
695 double rho, double theta, int threshold,
696 double param1, double param2 )
700 CvMat stub, *img = (CvMat*)src_image;
704 CvSeqBlock lines_block;
705 int lineType, elemSize;
706 int linesMax = INT_MAX;
707 int iparam1, iparam2;
709 img = cvGetMat( img, &stub );
711 if( !CV_IS_MASK_ARR(img))
712 CV_Error( CV_StsBadArg, "The source image must be 8-bit, single-channel" );
715 CV_Error( CV_StsNullPtr, "NULL destination" );
717 if( rho <= 0 || theta <= 0 || threshold <= 0 )
718 CV_Error( CV_StsOutOfRange, "rho, theta and threshold must be positive" );
720 if( method != CV_HOUGH_PROBABILISTIC )
723 elemSize = sizeof(float)*2;
728 elemSize = sizeof(int)*4;
731 if( CV_IS_STORAGE( lineStorage ))
733 lines = cvCreateSeq( lineType, sizeof(CvSeq), elemSize, (CvMemStorage*)lineStorage );
735 else if( CV_IS_MAT( lineStorage ))
737 mat = (CvMat*)lineStorage;
739 if( !CV_IS_MAT_CONT( mat->type ) || (mat->rows != 1 && mat->cols != 1) )
740 CV_Error( CV_StsBadArg,
741 "The destination matrix should be continuous and have a single row or a single column" );
743 if( CV_MAT_TYPE( mat->type ) != lineType )
744 CV_Error( CV_StsBadArg,
745 "The destination matrix data type is inappropriate, see the manual" );
747 lines = cvMakeSeqHeaderForArray( lineType, sizeof(CvSeq), elemSize, mat->data.ptr,
748 mat->rows + mat->cols - 1, &lines_header, &lines_block );
749 linesMax = lines->total;
753 CV_Error( CV_StsBadArg, "Destination is not CvMemStorage* nor CvMat*" );
755 iparam1 = cvRound(param1);
756 iparam2 = cvRound(param2);
760 case CV_HOUGH_STANDARD:
761 icvHoughLinesStandard( img, (float)rho,
762 (float)theta, threshold, lines, linesMax );
764 case CV_HOUGH_MULTI_SCALE:
765 icvHoughLinesSDiv( img, (float)rho, (float)theta,
766 threshold, iparam1, iparam2, lines, linesMax );
768 case CV_HOUGH_PROBABILISTIC:
769 icvHoughLinesProbabilistic( img, (float)rho, (float)theta,
770 threshold, iparam1, iparam2, lines, linesMax );
773 CV_Error( CV_StsBadArg, "Unrecognized method id" );
778 if( mat->cols > mat->rows )
779 mat->cols = lines->total;
781 mat->rows = lines->total;
790 /****************************************************************************************\
792 \****************************************************************************************/
795 icvHoughCirclesGradient( CvMat* img, float dp, float min_dist,
796 int min_radius, int max_radius,
797 int canny_threshold, int acc_threshold,
798 CvSeq* circles, int circles_max )
800 const int SHIFT = 10, ONE = 1 << SHIFT;
801 cv::Ptr<CvMat> dx, dy;
802 cv::Ptr<CvMat> edges, accum, dist_buf;
803 std::vector<int> sort_buf;
804 cv::Ptr<CvMemStorage> storage;
806 int x, y, i, j, k, center_count, nz_count;
807 float min_radius2 = (float)min_radius*min_radius;
808 float max_radius2 = (float)max_radius*max_radius;
809 int rows, cols, arows, acols;
816 edges = cvCreateMat( img->rows, img->cols, CV_8UC1 );
817 cvCanny( img, edges, MAX(canny_threshold/2,1), canny_threshold, 3 );
819 dx = cvCreateMat( img->rows, img->cols, CV_16SC1 );
820 dy = cvCreateMat( img->rows, img->cols, CV_16SC1 );
821 cvSobel( img, dx, 1, 0, 3 );
822 cvSobel( img, dy, 0, 1, 3 );
827 accum = cvCreateMat( cvCeil(img->rows*idp)+2, cvCeil(img->cols*idp)+2, CV_32SC1 );
830 storage = cvCreateMemStorage();
831 nz = cvCreateSeq( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage );
832 centers = cvCreateSeq( CV_32SC1, sizeof(CvSeq), sizeof(int), storage );
836 arows = accum->rows - 2;
837 acols = accum->cols - 2;
838 adata = accum->data.i;
839 astep = accum->step/sizeof(adata[0]);
840 // Accumulate circle evidence for each edge pixel
841 for( y = 0; y < rows; y++ )
843 const uchar* edges_row = edges->data.ptr + y*edges->step;
844 const short* dx_row = (const short*)(dx->data.ptr + y*dx->step);
845 const short* dy_row = (const short*)(dy->data.ptr + y*dy->step);
847 for( x = 0; x < cols; x++ )
850 int sx, sy, x0, y0, x1, y1, r;
856 if( !edges_row[x] || (vx == 0 && vy == 0) )
859 float mag = sqrt(vx*vx+vy*vy);
861 sx = cvRound((vx*idp)*ONE/mag);
862 sy = cvRound((vy*idp)*ONE/mag);
864 x0 = cvRound((x*idp)*ONE);
865 y0 = cvRound((y*idp)*ONE);
866 // Step from min_radius to max_radius in both directions of the gradient
867 for(int k1 = 0; k1 < 2; k1++ )
869 x1 = x0 + min_radius * sx;
870 y1 = y0 + min_radius * sy;
872 for( r = min_radius; r <= max_radius; x1 += sx, y1 += sy, r++ )
874 int x2 = x1 >> SHIFT, y2 = y1 >> SHIFT;
875 if( (unsigned)x2 >= (unsigned)acols ||
876 (unsigned)y2 >= (unsigned)arows )
878 adata[y2*astep + x2]++;
885 cvSeqPush( nz, &pt );
889 nz_count = nz->total;
892 //Find possible circle centers
893 for( y = 1; y < arows - 1; y++ )
895 for( x = 1; x < acols - 1; x++ )
897 int base = y*(acols+2) + x;
898 if( adata[base] > acc_threshold &&
899 adata[base] > adata[base-1] && adata[base] > adata[base+1] &&
900 adata[base] > adata[base-acols-2] && adata[base] > adata[base+acols+2] )
901 cvSeqPush(centers, &base);
905 center_count = centers->total;
909 sort_buf.resize( MAX(center_count,nz_count) );
910 cvCvtSeqToArray( centers, &sort_buf[0] );
912 icvHoughSortDescent32s( &sort_buf[0], center_count, adata );
913 cvClearSeq( centers );
914 cvSeqPushMulti( centers, &sort_buf[0], center_count );
916 dist_buf = cvCreateMat( 1, nz_count, CV_32FC1 );
917 ddata = dist_buf->data.fl;
920 min_dist = MAX( min_dist, dp );
921 min_dist *= min_dist;
922 // For each found possible center
923 // Estimate radius and check support
924 for( i = 0; i < centers->total; i++ )
926 int ofs = *(int*)cvGetSeqElem( centers, i );
928 x = ofs - (y)*(acols+2);
929 //Calculate circle's center in pixels
930 float cx = (float)((x + 0.5f)*dp), cy = (float)(( y + 0.5f )*dp);
931 float start_dist, dist_sum;
934 // Check distance with previously detected circles
935 for( j = 0; j < circles->total; j++ )
937 float* c = (float*)cvGetSeqElem( circles, j );
938 if( (c[0] - cx)*(c[0] - cx) + (c[1] - cy)*(c[1] - cy) < min_dist )
942 if( j < circles->total )
944 // Estimate best radius
945 cvStartReadSeq( nz, &reader );
946 for( j = k = 0; j < nz_count; j++ )
950 CV_READ_SEQ_ELEM( pt, reader );
951 _dx = cx - pt.x; _dy = cy - pt.y;
952 _r2 = _dx*_dx + _dy*_dy;
953 if(min_radius2 <= _r2 && _r2 <= max_radius2 )
961 int nz_count1 = k, start_idx = nz_count1 - 1;
964 dist_buf->cols = nz_count1;
965 cvPow( dist_buf, dist_buf, 0.5 );
966 icvHoughSortDescent32s( &sort_buf[0], nz_count1, (int*)ddata );
968 dist_sum = start_dist = ddata[sort_buf[nz_count1-1]];
969 for( j = nz_count1 - 2; j >= 0; j-- )
971 float d = ddata[sort_buf[j]];
976 if( d - start_dist > dr )
978 float r_cur = ddata[sort_buf[(j + start_idx)/2]];
979 if( (start_idx - j)*r_best >= max_count*r_cur ||
980 (r_best < FLT_EPSILON && start_idx - j >= max_count) )
983 max_count = start_idx - j;
991 // Check if the circle has enough support
992 if( max_count > acc_threshold )
997 c[2] = (float)r_best;
998 cvSeqPush( circles, c );
999 if( circles->total > circles_max )
1006 cvHoughCircles( CvArr* src_image, void* circle_storage,
1007 int method, double dp, double min_dist,
1008 double param1, double param2,
1009 int min_radius, int max_radius )
1013 CvMat stub, *img = (CvMat*)src_image;
1016 CvSeq circles_header;
1017 CvSeqBlock circles_block;
1018 int circles_max = INT_MAX;
1019 int canny_threshold = cvRound(param1);
1020 int acc_threshold = cvRound(param2);
1022 img = cvGetMat( img, &stub );
1024 if( !CV_IS_MASK_ARR(img))
1025 CV_Error( CV_StsBadArg, "The source image must be 8-bit, single-channel" );
1027 if( !circle_storage )
1028 CV_Error( CV_StsNullPtr, "NULL destination" );
1030 if( dp <= 0 || min_dist <= 0 || canny_threshold <= 0 || acc_threshold <= 0 )
1031 CV_Error( CV_StsOutOfRange, "dp, min_dist, canny_threshold and acc_threshold must be all positive numbers" );
1033 min_radius = MAX( min_radius, 0 );
1034 if( max_radius <= 0 )
1035 max_radius = MAX( img->rows, img->cols );
1036 else if( max_radius <= min_radius )
1037 max_radius = min_radius + 2;
1039 if( CV_IS_STORAGE( circle_storage ))
1041 circles = cvCreateSeq( CV_32FC3, sizeof(CvSeq),
1042 sizeof(float)*3, (CvMemStorage*)circle_storage );
1044 else if( CV_IS_MAT( circle_storage ))
1046 mat = (CvMat*)circle_storage;
1048 if( !CV_IS_MAT_CONT( mat->type ) || (mat->rows != 1 && mat->cols != 1) ||
1049 CV_MAT_TYPE(mat->type) != CV_32FC3 )
1050 CV_Error( CV_StsBadArg,
1051 "The destination matrix should be continuous and have a single row or a single column" );
1053 circles = cvMakeSeqHeaderForArray( CV_32FC3, sizeof(CvSeq), sizeof(float)*3,
1054 mat->data.ptr, mat->rows + mat->cols - 1, &circles_header, &circles_block );
1055 circles_max = circles->total;
1056 cvClearSeq( circles );
1059 CV_Error( CV_StsBadArg, "Destination is not CvMemStorage* nor CvMat*" );
1063 case CV_HOUGH_GRADIENT:
1064 icvHoughCirclesGradient( img, (float)dp, (float)min_dist,
1065 min_radius, max_radius, canny_threshold,
1066 acc_threshold, circles, circles_max );
1069 CV_Error( CV_StsBadArg, "Unrecognized method id" );
1074 if( mat->cols > mat->rows )
1075 mat->cols = circles->total;
1077 mat->rows = circles->total;
1089 const int STORAGE_SIZE = 1 << 12;
1091 static void seqToMat(const CvSeq* seq, OutputArray _arr)
1093 if( seq && seq->total > 0 )
1095 _arr.create(1, seq->total, seq->flags, -1, true);
1096 Mat arr = _arr.getMat();
1097 cvCvtSeqToArray(seq, arr.data);
1105 void cv::HoughLines( InputArray _image, OutputArray _lines,
1106 double rho, double theta, int threshold,
1107 double srn, double stn )
1109 Ptr<CvMemStorage> storage = cvCreateMemStorage(STORAGE_SIZE);
1110 Mat image = _image.getMat();
1111 CvMat c_image = image;
1112 CvSeq* seq = cvHoughLines2( &c_image, storage, srn == 0 && stn == 0 ?
1113 CV_HOUGH_STANDARD : CV_HOUGH_MULTI_SCALE,
1114 rho, theta, threshold, srn, stn );
1115 seqToMat(seq, _lines);
1118 void cv::HoughLinesP( InputArray _image, OutputArray _lines,
1119 double rho, double theta, int threshold,
1120 double minLineLength, double maxGap )
1122 Ptr<CvMemStorage> storage = cvCreateMemStorage(STORAGE_SIZE);
1123 Mat image = _image.getMat();
1124 CvMat c_image = image;
1125 CvSeq* seq = cvHoughLines2( &c_image, storage, CV_HOUGH_PROBABILISTIC,
1126 rho, theta, threshold, minLineLength, maxGap );
1127 seqToMat(seq, _lines);
1130 void cv::HoughCircles( InputArray _image, OutputArray _circles,
1131 int method, double dp, double min_dist,
1132 double param1, double param2,
1133 int minRadius, int maxRadius )
1135 Ptr<CvMemStorage> storage = cvCreateMemStorage(STORAGE_SIZE);
1136 Mat image = _image.getMat();
1137 CvMat c_image = image;
1138 CvSeq* seq = cvHoughCircles( &c_image, storage, method,
1139 dp, min_dist, param1, param2, minRadius, maxRadius );
1140 seqToMat(seq, _circles);