📄 cvmoments.cpp
字号:
#define icvMomentsInTile_8s_CnCR 0
#define icvMomentsInTile_32s_CnCR 0
#define icvMomentsInTileBin_8s_CnCR icvMomentsInTileBin_8u_CnCR
#define icvMomentsInTileBin_16u_CnCR icvMomentsInTileBin_16s_CnCR
#define icvMomentsInTileBin_32s_CnCR 0
CV_DEF_INIT_FUNC_TAB_2D( MomentsInTile, CnCR )
CV_DEF_INIT_FUNC_TAB_2D( MomentsInTileBin, CnCR )
////////////////////////////////// IPP moment functions //////////////////////////////////
icvMoments_8u_C1R_t icvMoments_8u_C1R_p = 0;
icvMoments_32f_C1R_t icvMoments_32f_C1R_p = 0;
icvMomentInitAlloc_64f_t icvMomentInitAlloc_64f_p = 0;
icvMomentFree_64f_t icvMomentFree_64f_p = 0;
icvGetSpatialMoment_64f_t icvGetSpatialMoment_64f_p = 0;
typedef CvStatus (CV_STDCALL * CvMomentIPPFunc)
( const void* img, int step, CvSize size, void* momentstate );
CV_IMPL void
cvMoments( const void* array, CvMoments* moments, int binary )
{
static CvFuncTable mom_tab;
static CvFuncTable mombin_tab;
static int inittab = 0;
double* tiles = 0;
void* ippmomentstate = 0;
CV_FUNCNAME("cvMoments");
__BEGIN__;
int type = 0, depth, cn, pix_size;
int coi = 0;
int x, y, k, tile_num = 1;
CvSize size, tile_size = { 32, 32 };
CvMat stub, *mat = (CvMat*)array;
CvFunc2DnC_1A1P func = 0;
CvMomentIPPFunc ipp_func = 0;
CvContour contour_header;
CvSeq* contour = 0;
CvSeqBlock block;
if( CV_IS_SEQ( array ))
{
contour = (CvSeq*)array;
if( !CV_IS_SEQ_POLYGON( contour ))
CV_ERROR( CV_StsBadArg, "The passed sequence is not a valid contour" );
}
if( !inittab )
{
icvInitMomentsInTileCnCRTable( &mom_tab );
icvInitMomentsInTileBinCnCRTable( &mombin_tab );
inittab = 1;
}
if( !moments )
CV_ERROR( CV_StsNullPtr, "" );
memset( moments, 0, sizeof(*moments));
if( !contour )
{
CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
type = CV_MAT_TYPE( mat->type );
if( type == CV_32SC2 || type == CV_32FC2 )
{
CV_CALL( contour = cvPointSeqFromMat(
CV_SEQ_KIND_CURVE | CV_SEQ_FLAG_CLOSED,
mat, &contour_header, &block ));
}
}
if( contour )
{
icvContourMoments( contour, moments );
EXIT;
}
type = CV_MAT_TYPE( mat->type );
depth = CV_MAT_DEPTH( type );
cn = CV_MAT_CN( type );
pix_size = CV_ELEM_SIZE(type);
size = cvGetMatSize( mat );
if( cn > 1 && coi == 0 )
CV_ERROR( CV_StsBadArg, "Invalid image type" );
if( size.width <= 0 || size.height <= 0 )
{
EXIT;
}
if( type == CV_8UC1 )
ipp_func = (CvMomentIPPFunc)icvMoments_8u_C1R_p;
else if( type == CV_32FC1 )
ipp_func = (CvMomentIPPFunc)icvMoments_32f_C1R_p;
if( ipp_func && !binary )
{
int matstep = mat->step ? mat->step : CV_STUB_STEP;
IPPI_CALL( icvMomentInitAlloc_64f_p( &ippmomentstate, cvAlgHintAccurate ));
IPPI_CALL( ipp_func( mat->data.ptr, matstep, size, ippmomentstate ));
icvGetSpatialMoment_64f_p( ippmomentstate, 0, 0, 0, cvPoint(0,0), &moments->m00 );
icvGetSpatialMoment_64f_p( ippmomentstate, 1, 0, 0, cvPoint(0,0), &moments->m10 );
icvGetSpatialMoment_64f_p( ippmomentstate, 0, 1, 0, cvPoint(0,0), &moments->m01 );
icvGetSpatialMoment_64f_p( ippmomentstate, 2, 0, 0, cvPoint(0,0), &moments->m20 );
icvGetSpatialMoment_64f_p( ippmomentstate, 1, 1, 0, cvPoint(0,0), &moments->m11 );
icvGetSpatialMoment_64f_p( ippmomentstate, 0, 2, 0, cvPoint(0,0), &moments->m02 );
icvGetSpatialMoment_64f_p( ippmomentstate, 3, 0, 0, cvPoint(0,0), &moments->m30 );
icvGetSpatialMoment_64f_p( ippmomentstate, 2, 1, 0, cvPoint(0,0), &moments->m21 );
icvGetSpatialMoment_64f_p( ippmomentstate, 1, 2, 0, cvPoint(0,0), &moments->m12 );
icvGetSpatialMoment_64f_p( ippmomentstate, 0, 3, 0, cvPoint(0,0), &moments->m03 );
icvCompleteMomentState( moments );
EXIT;
}
func = (CvFunc2DnC_1A1P)(!binary ? mom_tab.fn_2d[depth] : mombin_tab.fn_2d[depth]);
if( !func )
CV_ERROR( CV_StsBadArg, cvUnsupportedFormat );
if( depth >= CV_32S && !binary )
tile_size = size;
else
tile_num = ((size.width + tile_size.width - 1)/tile_size.width)*
((size.height + tile_size.height - 1)/tile_size.height);
CV_CALL( tiles = (double*)cvAlloc( tile_num*10*sizeof(double)));
for( y = 0, k = 0; y < size.height; y += tile_size.height )
{
CvSize cur_tile_size = tile_size;
if( y + cur_tile_size.height > size.height )
cur_tile_size.height = size.height - y;
for( x = 0; x < size.width; x += tile_size.width, k++ )
{
if( x + cur_tile_size.width > size.width )
cur_tile_size.width = size.width - x;
assert( k < tile_num );
IPPI_CALL( func( mat->data.ptr + y*mat->step + x*pix_size,
mat->step, cur_tile_size, cn, coi, tiles + k*10 ));
}
}
icvAccumulateMoments( tiles, size, tile_size, moments );
__END__;
if( ippmomentstate )
icvMomentFree_64f_p( ippmomentstate );
cvFree( &tiles );
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvGetHuMoments
// Purpose: Returns Hu moments
// Context:
// Parameters:
// mState - moment structure filled by one of the icvMoments[Binary]*** function
// HuState - pointer to output structure containing seven Hu moments
// Returns:
// CV_NO_ERR if success or error code
// Notes:
//F*/
CV_IMPL void
cvGetHuMoments( CvMoments * mState, CvHuMoments * HuState )
{
CV_FUNCNAME( "cvGetHuMoments" );
__BEGIN__;
if( !mState || !HuState )
CV_ERROR_FROM_STATUS( CV_NULLPTR_ERR );
{
double m00s = mState->inv_sqrt_m00, m00 = m00s * m00s, s2 = m00 * m00, s3 = s2 * m00s;
double nu20 = mState->mu20 * s2,
nu11 = mState->mu11 * s2,
nu02 = mState->mu02 * s2,
nu30 = mState->mu30 * s3,
nu21 = mState->mu21 * s3, nu12 = mState->mu12 * s3, nu03 = mState->mu03 * s3;
double t0 = nu30 + nu12;
double t1 = nu21 + nu03;
double q0 = t0 * t0, q1 = t1 * t1;
double n4 = 4 * nu11;
double s = nu20 + nu02;
double d = nu20 - nu02;
HuState->hu1 = s;
HuState->hu2 = d * d + n4 * nu11;
HuState->hu4 = q0 + q1;
HuState->hu6 = d * (q0 - q1) + n4 * t0 * t1;
t0 *= q0 - 3 * q1;
t1 *= 3 * q0 - q1;
q0 = nu30 - 3 * nu12;
q1 = 3 * nu21 - nu03;
HuState->hu3 = q0 * q0 + q1 * q1;
HuState->hu5 = q0 * t0 + q1 * t1;
HuState->hu7 = q1 * t0 - q0 * t1;
}
__END__;
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvGetSpatialMoment
// Purpose: Returns spatial moment(x_order, y_order) which is determined as:
// m(x_o,y_o) = sum (x ^ x_o)*(y ^ y_o)*I(x,y)
// 0 <= x_o, y_o; x_o + y_o <= 3
// Context:
// Parameters:
// mom - moment structure filled by one of the icvMoments[Binary]*** function
// x_order - x order of the moment
// y_order - y order of the moment
// Returns:
// moment value or large negative number (-DBL_MAX) if error
// Notes:
//F*/
CV_IMPL double
cvGetSpatialMoment( CvMoments * moments, int x_order, int y_order )
{
int order = x_order + y_order;
double moment = -DBL_MAX;
CV_FUNCNAME( "cvGetSpatialMoment" );
__BEGIN__;
if( !moments )
CV_ERROR_FROM_STATUS( CV_NULLPTR_ERR );
if( (x_order | y_order) < 0 || order > 3 )
CV_ERROR_FROM_STATUS( CV_BADRANGE_ERR );
moment = (&(moments->m00))[order + (order >> 1) + (order > 2) * 2 + y_order];
__END__;
return moment;
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvGetCentralMoment
// Purpose: Returns central moment(x_order, y_order) which is determined as:
// mu(x_o,y_o) = sum ((x - xc)^ x_o)*((y - yc) ^ y_o)*I(x,y)
// 0 <= x_o, y_o; x_o + y_o <= 3,
// (xc, yc) = (m10/m00,m01/m00) - center of gravity
// Context:
// Parameters:
// mom - moment structure filled by one of the icvMoments[Binary]*** function
// x_order - x order of the moment
// y_order - y order of the moment
// Returns:
// moment value or large negative number (-DBL_MAX) if error
// Notes:
//F*/
CV_IMPL double
cvGetCentralMoment( CvMoments * moments, int x_order, int y_order )
{
int order = x_order + y_order;
double mu = 0;
CV_FUNCNAME( "cvGetCentralMoment" );
__BEGIN__;
if( !moments )
CV_ERROR_FROM_STATUS( CV_NULLPTR_ERR );
if( (x_order | y_order) < 0 || order > 3 )
CV_ERROR_FROM_STATUS( CV_BADRANGE_ERR );
if( order >= 2 )
{
mu = (&(moments->m00))[4 + order * 3 + y_order];
}
else if( order == 0 )
mu = moments->m00;
__END__;
return mu;
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvGetNormalizedCentralMoment
// Purpose: Returns normalized central moment(x_order,y_order) which is determined as:
// nu(x_o,y_o) = mu(x_o, y_o)/(m00 ^ (((x_o + y_o)/2) + 1))
// 0 <= x_o, y_o; x_o + y_o <= 3,
// (xc, yc) = (m10/m00,m01/m00) - center of gravity
// Context:
// Parameters:
// mom - moment structure filled by one of the icvMoments[Binary]*** function
// x_order - x order of the moment
// y_order - y order of the moment
// Returns:
// moment value or large negative number (-DBL_MAX) if error
// Notes:
//F*/
CV_IMPL double
cvGetNormalizedCentralMoment( CvMoments * moments, int x_order, int y_order )
{
int order = x_order + y_order;
double mu = 0;
double m00s, m00;
CV_FUNCNAME( "cvGetCentralNormalizedMoment" );
__BEGIN__;
mu = cvGetCentralMoment( moments, x_order, y_order );
CV_CHECK();
m00s = moments->inv_sqrt_m00;
m00 = m00s * m00s;
while( --order >= 0 )
m00 *= m00s;
mu *= m00;
__END__;
return mu;
}
/* End of file. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -