📄 cvhough.cpp
字号:
mcaccum[i]++;
assert( i >= -1 );
assert( i <= sfn );
}
}
/* Find peaks in maccum... */
for( index = 0; index < sfn; index++ )
{
i = 0;
pos = h_get_tail_pos__index( list );
if( h_get_prev__index( &pos )->value < mcaccum[index] )
{
vi.value = mcaccum[index];
vi.rho = index / stn * srho + ri * rho;
vi.theta = index % stn * stheta + ti * theta - halfPi;
while( h_is_pos__index( pos ))
{
if( h_get__index( pos )->value > mcaccum[index] )
{
h_insert_after__index( list, pos, &vi );
if( h_get_count__index( list ) > linesMax )
{
h_remove_tail__index( list );
}
break;
}
h_get_prev__index( &pos );
}
if( !h_is_pos__index( pos ))
{
h_add_head__index( list, &vi );
if( h_get_count__index( list ) > linesMax )
{
h_remove_tail__index( list );
}
}
}
}
}
}
}
pos = h_get_head_pos__index( list );
if( h_get_count__index( list ) == 1 )
{
if( h_get__index( pos )->rho < 0 )
{
h_clear_list__index( list );
}
}
else
{
while( h_is_pos__index( pos ))
{
CvLinePolar line;
pindex = h_get__index( pos );
if( pindex->rho < 0 )
{
/* This should be the last element... */
h_get_next__index( &pos );
assert( !h_is_pos__index( pos ));
break;
}
line.rho = pindex->rho;
line.angle = pindex->theta;
cvSeqPush( lines, &line );
if( lines->total >= linesMax )
EXIT;
h_get_next__index( &pos );
}
}
__END__;
h_destroy_list__index( list );
cvFree( &sinTable );
cvFree( &x );
cvFree( &y );
cvFree( &caccum );
cvFree( &buffer );
}
/****************************************************************************************\
* Probabilistic Hough Transform *
\****************************************************************************************/
#if defined WIN64 && defined EM64T && _MSC_VER == 1400 && !defined CV_ICC
#pragma optimize("",off)
#endif
static void
icvHoughLinesProbabalistic( CvMat* image,
float rho, float theta, int threshold,
int lineLength, int lineGap,
CvSeq *lines, int linesMax )
{
CvMat* accum = 0;
CvMat* mask = 0;
CvMat* trigtab = 0;
CvMemStorage* storage = 0;
CV_FUNCNAME( "icvHoughLinesProbalistic" );
__BEGIN__;
CvSeq* seq;
CvSeqWriter writer;
int width, height;
int numangle, numrho;
float ang;
int r, n, count;
CvPoint pt;
float irho = 1 / rho;
CvRNG rng = cvRNG(-1);
const float* ttab;
uchar* mdata0;
CV_ASSERT( CV_IS_MAT(image) && CV_MAT_TYPE(image->type) == CV_8UC1 );
width = image->cols;
height = image->rows;
numangle = cvRound(CV_PI / theta);
numrho = cvRound(((width + height) * 2 + 1) / rho);
CV_CALL( accum = cvCreateMat( numangle, numrho, CV_32SC1 ));
CV_CALL( mask = cvCreateMat( height, width, CV_8UC1 ));
CV_CALL( trigtab = cvCreateMat( 1, numangle, CV_32FC2 ));
cvZero( accum );
CV_CALL( storage = cvCreateMemStorage(0) );
for( ang = 0, n = 0; n < numangle; ang += theta, n++ )
{
trigtab->data.fl[n*2] = (float)(cos(ang) * irho);
trigtab->data.fl[n*2+1] = (float)(sin(ang) * irho);
}
ttab = trigtab->data.fl;
mdata0 = mask->data.ptr;
CV_CALL( cvStartWriteSeq( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage, &writer ));
// stage 1. collect non-zero image points
for( pt.y = 0, count = 0; pt.y < height; pt.y++ )
{
const uchar* data = image->data.ptr + pt.y*image->step;
uchar* mdata = mdata0 + pt.y*width;
for( pt.x = 0; pt.x < width; pt.x++ )
{
if( data[pt.x] )
{
mdata[pt.x] = (uchar)1;
CV_WRITE_SEQ_ELEM( pt, writer );
}
else
mdata[pt.x] = 0;
}
}
seq = cvEndWriteSeq( &writer );
count = seq->total;
// stage 2. process all the points in random order
for( ; count > 0; count-- )
{
// choose random point out of the remaining ones
int idx = cvRandInt(&rng) % count;
int max_val = threshold-1, max_n = 0;
CvPoint* pt = (CvPoint*)cvGetSeqElem( seq, idx );
CvPoint line_end[2] = {{0,0}, {0,0}};
float a, b;
int* adata = accum->data.i;
int i, j, k, x0, y0, dx0, dy0, xflag;
int good_line;
const int shift = 16;
i = pt->y;
j = pt->x;
// "remove" it by overriding it with the last element
*pt = *(CvPoint*)cvGetSeqElem( seq, count-1 );
// check if it has been excluded already (i.e. belongs to some other line)
if( !mdata0[i*width + j] )
continue;
// update accumulator, find the most probable line
for( n = 0; n < numangle; n++, adata += numrho )
{
r = cvRound( j * ttab[n*2] + i * ttab[n*2+1] );
r += (numrho - 1) / 2;
int val = ++adata[r];
if( max_val < val )
{
max_val = val;
max_n = n;
}
}
// if it is too "weak" candidate, continue with another point
if( max_val < threshold )
continue;
// from the current point walk in each direction
// along the found line and extract the line segment
a = -ttab[max_n*2+1];
b = ttab[max_n*2];
x0 = j;
y0 = i;
if( fabs(a) > fabs(b) )
{
xflag = 1;
dx0 = a > 0 ? 1 : -1;
dy0 = cvRound( b*(1 << shift)/fabs(a) );
y0 = (y0 << shift) + (1 << (shift-1));
}
else
{
xflag = 0;
dy0 = b > 0 ? 1 : -1;
dx0 = cvRound( a*(1 << shift)/fabs(b) );
x0 = (x0 << shift) + (1 << (shift-1));
}
for( k = 0; k < 2; k++ )
{
int gap = 0, x = x0, y = y0, dx = dx0, dy = dy0;
if( k > 0 )
dx = -dx, dy = -dy;
// walk along the line using fixed-point arithmetics,
// stop at the image border or in case of too big gap
for( ;; x += dx, y += dy )
{
uchar* mdata;
int i1, j1;
if( xflag )
{
j1 = x;
i1 = y >> shift;
}
else
{
j1 = x >> shift;
i1 = y;
}
if( j1 < 0 || j1 >= width || i1 < 0 || i1 >= height )
break;
mdata = mdata0 + i1*width + j1;
// for each non-zero point:
// update line end,
// clear the mask element
// reset the gap
if( *mdata )
{
gap = 0;
line_end[k].y = i1;
line_end[k].x = j1;
}
else if( ++gap > lineGap )
break;
}
}
good_line = abs(line_end[1].x - line_end[0].x) >= lineLength ||
abs(line_end[1].y - line_end[0].y) >= lineLength;
for( k = 0; k < 2; k++ )
{
int x = x0, y = y0, dx = dx0, dy = dy0;
if( k > 0 )
dx = -dx, dy = -dy;
// walk along the line using fixed-point arithmetics,
// stop at the image border or in case of too big gap
for( ;; x += dx, y += dy )
{
uchar* mdata;
int i1, j1;
if( xflag )
{
j1 = x;
i1 = y >> shift;
}
else
{
j1 = x >> shift;
i1 = y;
}
mdata = mdata0 + i1*width + j1;
// for each non-zero point:
// update line end,
// clear the mask element
// reset the gap
if( *mdata )
{
if( good_line )
{
adata = accum->data.i;
for( n = 0; n < numangle; n++, adata += numrho )
{
r = cvRound( j1 * ttab[n*2] + i1 * ttab[n*2+1] );
r += (numrho - 1) / 2;
adata[r]--;
}
}
*mdata = 0;
}
if( i1 == line_end[k].y && j1 == line_end[k].x )
break;
}
}
if( good_line )
{
CvRect lr = { line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y };
cvSeqPush( lines, &lr );
if( lines->total >= linesMax )
EXIT;
}
}
__END__;
cvReleaseMat( &accum );
cvReleaseMat( &mask );
cvReleaseMat( &trigtab );
cvReleaseMemStorage( &storage );
}
#if defined WIN64 && defined EM64T && _MSC_VER == 1400 && !defined CV_ICC
#pragma optimize("",on)
#endif
/* Wrapper function for standard hough transform */
CV_IMPL CvSeq*
cvHoughLines2( CvArr* src_image, void* lineStorage, int method,
double rho, double theta, int threshold,
double param1, double param2 )
{
CvSeq* result = 0;
CV_FUNCNAME( "cvHoughLines" );
__BEGIN__;
CvMat stub, *img = (CvMat*)src_image;
CvMat* mat = 0;
CvSeq* lines = 0;
CvSeq lines_header;
CvSeqBlock lines_block;
int lineType, elemSize;
int linesMax = INT_MAX;
int iparam1, iparam2;
CV_CALL( img = cvGetMat( img, &stub ));
if( !CV_IS_MASK_ARR(img))
CV_ERROR( CV_StsBadArg, "The source image must be 8-bit, single-channel" );
if( !lineStorage )
CV_ERROR( CV_StsNullPtr, "NULL destination" );
if( rho <= 0 || theta <= 0 || threshold <= 0 )
CV_ERROR( CV_StsOutOfRange, "rho, theta and threshold must be positive" );
if( method != CV_HOUGH_PROBABILISTIC )
{
lineType = CV_32FC2;
elemSize = sizeof(float)*2;
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -