// default <malloc> CV_IMPL void* icvDefaultAlloc( size_t size, const char*, int) { char *ptr, *ptr0 = (char*)malloc( (size_t)(size + CV_MALLOC_ALIGN*((size >= 4096) + 1) + sizeof(char*)*2)); if( !ptr0 ) return 0; // align the pointer ptr = ptr0 + sizeof(char*)*2 + 1; ptr = (char*)icvAlignPtr(ptr, CV_MALLOC_ALIGN); *(char**)(ptr - sizeof(char*)) = ptr0; return ptr; }
/*F/////////////////////////////////////////////////////////////////////////////////////// // Name: icvCalcPGH // Purpose: // Calculates PGH(pairwise geometric histogram) for contour given. // Context: // Parameters: // contour - pointer to input contour object. // pgh - output histogram // ang_dim - number of angle bins (vertical size of histogram) // dist_dim - number of distance bins (horizontal size of histogram) // Returns: // CV_OK or error code // Notes: //F*/ CvStatus icvCalcPGH( CvSeq * contour, float *pgh, int angle_dim, int dist_dim ) { char local_buffer[(1 << 14) + 32]; float *local_buffer_ptr = (float *)icvAlignPtr(local_buffer,32); float *buffer = local_buffer_ptr; double angle_scale = (angle_dim - 0.51) / icv_acos_table[0]; double dist_scale = DBL_EPSILON; int buffer_size; int i, count, pass; int *pghi = (int *) pgh; int hist_size = angle_dim * dist_dim; CvSeqReader reader1, reader2; /* external and internal readers */ if( !contour || !pgh ) return CV_NULLPTR_ERR; if( angle_dim <= 0 || angle_dim > 180 || dist_dim <= 0 ) return CV_BADRANGE_ERR; if( !CV_IS_SEQ_POLYGON( contour )) return CV_BADFLAG_ERR; memset( pgh, 0, hist_size * sizeof( pgh[0] )); count = contour->total; /* allocate buffer for distances */ buffer_size = count * sizeof( float ); if( buffer_size > (int)sizeof(local_buffer) - 32 ) { buffer = (float *) icvAlloc( buffer_size ); if( !buffer ) return CV_OUTOFMEM_ERR; } cvStartReadSeq( contour, &reader1, 0 ); cvStartReadSeq( contour, &reader2, 0 ); /* calc & store squared edge lengths, calculate maximal distance between edges */ for( i = 0; i < count; i++ ) { CvPoint pt1, pt2; int dx, dy; CV_READ_EDGE( pt1, pt2, reader1 ); dx = pt2.x - pt1.x; dy = pt2.y - pt1.y; buffer[i] = (float) (dx * dx + dy * dy); } icvbInvSqrt_32f( buffer, buffer, i ); /* do 2 passes. First calculates maximal distance. Second calculates histogram itself. */ for( pass = 1; pass <= 2; pass++ ) { double dist_coeff = 0, angle_coeff = 0; /* run external loop */ for( i = 0; i < count; i++ ) { CvPoint pt1, pt2; int dx, dy; int dist = 0; CV_READ_EDGE( pt1, pt2, reader1 ); dx = pt2.x - pt1.x; dy = pt2.y - pt1.y; if( (dx | dy) != 0 ) { int j; if( pass == 2 ) { dist_coeff = buffer[i] * dist_scale; angle_coeff = buffer[i] * (_CV_ACOS_TABLE_SIZE / 2); } /* run internal loop (for current edge) */ for( j = 0; j < count; j++ ) { CvPoint pt3, pt4; CV_READ_EDGE( pt3, pt4, reader2 ); if( i != j ) /* process edge pair */ { int d1 = (pt3.y - pt1.y) * dx - (pt3.x - pt1.x) * dy; int d2 = (pt4.y - pt1.y) * dx - (pt2.x - pt1.x) * dy; int cross_flag; int *hist_row = 0; if( pass == 2 ) { int dp = (pt4.x - pt3.x) * dx + (pt4.y - pt3.y) * dy; dp = cvRound( dp * angle_coeff * buffer[j] ) + (_CV_ACOS_TABLE_SIZE / 2); dp = MAX( dp, 0 ); dp = MIN( dp, _CV_ACOS_TABLE_SIZE - 1 ); hist_row = pghi + dist_dim * cvRound( icv_acos_table[dp] * angle_scale ); d1 = cvRound( d1 * dist_coeff ); d2 = cvRound( d2 * dist_coeff ); } cross_flag = (d1 ^ d2) < 0; d1 = CV_IABS( d1 ); d2 = CV_IABS( d2 ); if( pass == 2 ) { if( d1 >= dist_dim ) d1 = dist_dim - 1; if( d2 >= dist_dim ) d2 = dist_dim - 1; if( !cross_flag ) { if( d1 > d2 ) /* make d1 <= d2 */ { d1 ^= d2; d2 ^= d1; d1 ^= d2; } for( ; d1 <= d2; d1++ ) hist_row[d1]++; } else { for( ; d1 >= 0; d1-- ) hist_row[d1]++; for( ; d2 >= 0; d2-- ) hist_row[d2]++; } } else /* 1st pass */ { d1 = CV_IMAX( d1, d2 ); dist = CV_IMAX( dist, d1 ); } } /* end of processing of edge pair */ } /* end of internal loop */ if( pass == 1 ) { double scale = dist * buffer[i]; dist_scale = MAX( dist_scale, scale ); } } } /* end of external loop */ if( pass == 1 ) { dist_scale = (dist_dim - 0.51) / dist_scale; } } /* end of pass on loops */ /* convert hist to floats */ for( i = 0; i < hist_size; i++ ) { ((float *) pghi)[i] = (float) pghi[i]; } if( buffer != local_buffer_ptr ) icvFree( &buffer ); return CV_OK; }