static void icxLogicSM( const void* srcarr, CxScalar* scalar, void* dstarr, const void* maskarr, CxArithmUniMaskFunc2D func ) { CX_FUNCNAME( "icxLogicSM" ); __BEGIN__; double buf[12]; int coi1 = 0, coi2 = 0; CxMat srcstub, *src = (CxMat*)srcarr; CxMat dststub, *dst = (CxMat*)dstarr; CxMat maskstub, *mask = (CxMat*)maskarr; int pix_size, type; int dst_step, mask_step; CxSize size; if( !CX_IS_MAT(src)) CX_CALL( src = cxGetMat( src, &srcstub, &coi1 )); if( !CX_IS_MAT(dst)) CX_CALL( dst = cxGetMat( dst, &dststub )); if( coi1 != 0 || coi2 != 0 ) CX_ERROR( CX_BadCOI, "" ); CX_CALL( mask = cxGetMat( mask, &maskstub )); if( !CX_IS_MASK_ARR(mask) ) CX_ERROR_FROM_CODE( CX_StsBadMask ); if( !CX_ARE_SIZES_EQ( mask, dst ) ) CX_ERROR_FROM_CODE( CX_StsUnmatchedSizes ); if( src->data.ptr != dst->data.ptr ) { CX_CALL( cxCopy( src, dst, mask )); } size = cxGetMatSize( dst ); dst_step = dst->step; mask_step = mask->step; if( CX_IS_MAT_CONT( mask->type & dst->type )) { size.width *= size.height; dst_step = mask_step = CX_STUB_STEP; size.height = 1; } type = CX_MAT_TYPE( src->type ); pix_size = icxPixSize[type]; CX_CALL( cxScalarToRawData( scalar, buf, type, 0 )); IPPI_CALL( func( dst->data.ptr, dst_step, mask->data.ptr, mask_step, size, buf, pix_size )); __END__; }
CX_IMPL void cxMinMaxLoc( const void* img, double* minVal, double* maxVal, CxPoint* minLoc, CxPoint* maxLoc, const void* mask ) { static CxFuncTable minmax_tab, minmaxcoi_tab; static CxFuncTable minmaxmask_tab, minmaxmaskcoi_tab; static int inittab = 0; CX_FUNCNAME("cxMinMaxLoc"); __BEGIN__; int type, depth, cn, coi = 0; int mat_step, mask_step = 0; CxSize size; CxMat stub, maskstub, *mat = (CxMat*)img, *matmask = (CxMat*)mask; if( !inittab ) { icxInitMinMaxIndxC1RTable( &minmax_tab ); icxInitMinMaxIndxCnCRTable( &minmaxcoi_tab ); icxInitMinMaxIndxC1MRTable( &minmaxmask_tab ); icxInitMinMaxIndxCnCMRTable( &minmaxmaskcoi_tab ); inittab = 1; } CX_CALL( mat = cxGetMat( mat, &stub, &coi )); type = CX_MAT_TYPE( mat->type ); depth = CX_MAT_DEPTH( type ); cn = CX_MAT_CN( type ); size = cxGetMatSize( mat ); if( cn > 1 && coi == 0 ) CX_ERROR( CX_StsBadArg, "" ); mat_step = mat->step; if( !mask ) { if( size.height == 1 ) mat_step = CX_STUB_STEP; if( CX_MAT_CN(type) == 1 || coi == 0 ) { CxFunc2D_1A4P func = (CxFunc2D_1A4P)(minmax_tab.fn_2d[depth]); if( !func ) CX_ERROR( CX_StsBadArg, cxUnsupportedFormat ); IPPI_CALL( func( mat->data.ptr, mat_step, size, minVal, maxVal, minLoc, maxLoc )); } else { CxFunc2DnC_1A4P func = (CxFunc2DnC_1A4P)(minmaxcoi_tab.fn_2d[depth]); if( !func ) CX_ERROR( CX_StsBadArg, cxUnsupportedFormat ); IPPI_CALL( func( mat->data.ptr, mat_step, size, cn, coi, minVal, maxVal, minLoc, maxLoc )); } } else { CX_CALL( matmask = cxGetMat( matmask, &maskstub )); if( !CX_IS_MASK_ARR( matmask )) CX_ERROR( CX_StsBadMask, "" ); if( !CX_ARE_SIZES_EQ( mat, matmask )) CX_ERROR( CX_StsUnmatchedSizes, "" ); mask_step = matmask->step; if( size.height == 1 ) mat_step = mask_step = CX_STUB_STEP; if( CX_MAT_CN(type) == 1 || coi == 0 ) { CxFunc2D_2A4P func = (CxFunc2D_2A4P)(minmaxmask_tab.fn_2d[depth]); if( !func ) CX_ERROR( CX_StsBadArg, cxUnsupportedFormat ); IPPI_CALL( func( mat->data.ptr, mat_step, matmask->data.ptr, mask_step, size, minVal, maxVal, minLoc, maxLoc )); } else { CxFunc2DnC_2A4P func = (CxFunc2DnC_2A4P)(minmaxmaskcoi_tab.fn_2d[depth]); if( !func ) CX_ERROR( CX_StsBadArg, cxUnsupportedFormat ); IPPI_CALL( func( mat->data.ptr, mat_step, matmask->data.ptr, mask_step, size, cn, coi, minVal, maxVal, minLoc, maxLoc )); } } if( depth < CX_32S || depth == CX_32F ) { if( minVal ) *minVal = *(float*)minVal; if( maxVal ) *maxVal = *(float*)maxVal; } __END__; }
CX_IMPL void icxLogicM( const void* srcimg1, const void* srcimg2, void* dstarr, const void* maskarr, CxArithmBinMaskFunc2D func ) { CX_FUNCNAME( "icxLogicM" ); __BEGIN__; int coi1 = 0, coi2 = 0, coi3 = 0; CxMat srcstub1, *src1 = (CxMat*)srcimg1; CxMat srcstub2, *src2 = (CxMat*)srcimg2; CxMat dststub, *dst = (CxMat*)dstarr; CxMat maskstub, *mask = (CxMat*)maskarr; int src_step, dst_step, mask_step; int pix_size; CxSize size; CX_CALL( src1 = cxGetMat( src1, &srcstub1, &coi1 )); CX_CALL( src2 = cxGetMat( src2, &srcstub2, &coi2 )); CX_CALL( dst = cxGetMat( dst, &dststub, &coi3 )); CX_CALL( mask = cxGetMat( mask, &maskstub )); if( coi1 != 0 || coi2 != 0 || coi3 != 0 ) CX_ERROR( CX_BadCOI, "" ); if( !CX_IS_MASK_ARR(mask) ) CX_ERROR_FROM_CODE( CX_StsBadMask ); if( !CX_ARE_SIZES_EQ( mask, dst ) ) CX_ERROR_FROM_CODE( CX_StsUnmatchedSizes ); if( !CX_ARE_SIZES_EQ( src1, src2 ) ) CX_ERROR_FROM_CODE( CX_StsUnmatchedSizes ); size = cxGetMatSize( src1 ); pix_size = icxPixSize[CX_MAT_TYPE(src1->type)]; if( src2->data.ptr != dst->data.ptr ) { if( src1->data.ptr != dst->data.ptr ) { CX_CALL( cxCopy( src2, dst, mask )); } else src1 = src2; } if( !CX_ARE_TYPES_EQ( src1, dst )) CX_ERROR_FROM_CODE( CX_StsUnmatchedFormats ); if( !CX_ARE_SIZES_EQ( src1, dst )) CX_ERROR_FROM_CODE( CX_StsUnmatchedSizes ); src_step = src1->step; dst_step = dst->step; mask_step = mask->step; if( CX_IS_MAT_CONT( src1->type & dst->type & mask->type )) { size.width *= size.height; src_step = dst_step = mask_step = CX_STUB_STEP; size.height = 1; } IPPI_CALL( func( src1->data.ptr, src_step, mask->data.ptr, mask_step, dst->data.ptr, dst_step, size, pix_size )); __END__; }
static void icxLogic( const void* srcimg1, const void* srcimg2, void* dstarr, CxFunc2D_3A fn_2d ) { CX_FUNCNAME( "icxLogic" ); __BEGIN__; int coi1 = 0, coi2 = 0, coi3 = 0; int is_nd = 0; CxMat srcstub1, *src1 = (CxMat*)srcimg1; CxMat srcstub2, *src2 = (CxMat*)srcimg2; CxMat dststub, *dst = (CxMat*)dstarr; int src1_step, src2_step, dst_step; CxSize size; if( !CX_IS_MAT(src1)) { if( CX_IS_MATND(src1) ) is_nd = 1; else CX_CALL( src1 = cxGetMat( src1, &srcstub1, &coi1 )); } if( !CX_IS_MAT(src2)) { if( CX_IS_MATND(src2) ) is_nd = 1; else CX_CALL( src2 = cxGetMat( src2, &srcstub2, &coi2 )); } if( !CX_IS_MAT(dst)) { if( CX_IS_MATND(dst) ) is_nd = 1; else CX_CALL( dst = cxGetMat( dst, &dststub, &coi3 )); } if( is_nd ) { CxArr* arrs[] = { src1, src2, dst }; CxMatND stubs[3]; CxNArrayIterator iterator; int type; CX_CALL( cxInitNArrayIterator( 3, arrs, 0, stubs, &iterator )); type = CX_MAT_TYPE(iterator.hdr[0]->type); iterator.size.width *= icxPixSize[type]; do { IPPI_CALL( fn_2d( iterator.ptr[0], CX_STUB_STEP, iterator.ptr[1], CX_STUB_STEP, iterator.ptr[2], CX_STUB_STEP, iterator.size )); } while( cxNextNArraySlice( &iterator )); EXIT; } if( coi1 != 0 || coi2 != 0 || coi3 != 0 ) CX_ERROR_FROM_CODE( CX_BadCOI ); if( !CX_ARE_TYPES_EQ( src1, src2 ) ) CX_ERROR_FROM_CODE( CX_StsUnmatchedFormats ); if( !CX_ARE_SIZES_EQ( src1, src2 ) ) CX_ERROR_FROM_CODE( CX_StsUnmatchedSizes ); size = cxGetMatSize( src1 ); if( !CX_ARE_TYPES_EQ( src1, dst ) ) CX_ERROR_FROM_CODE( CX_StsUnmatchedFormats ); if( !CX_ARE_SIZES_EQ( src1, dst ) ) CX_ERROR_FROM_CODE( CX_StsUnmatchedSizes ); src1_step = src1->step; src2_step = src2->step; dst_step = dst->step; if( CX_IS_MAT_CONT( src1->type & src2->type & dst->type )) { size.width *= size.height; src1_step = src2_step = dst_step = CX_STUB_STEP; size.height = 1; } size.width *= icxPixSize[CX_MAT_TYPE(src1->type)]; IPPI_CALL( fn_2d( src1->data.ptr, src1_step, src2->data.ptr, src2_step, dst->data.ptr, dst_step, size )); __END__; }
static void icxLogicS( const void* srcarr, CxScalar* scalar, void* dstarr, CxFunc2D_2A1P1I fn_2d ) { CX_FUNCNAME( "icxLogicS" ); __BEGIN__; CxMat srcstub, *src = (CxMat*)srcarr; CxMat dststub, *dst = (CxMat*)dstarr; int coi1 = 0, coi2 = 0; int is_nd = 0; int pix_size, type; double buf[12]; CxSize size; int src_step, dst_step; if( !CX_IS_MAT(src)) { if( CX_IS_MATND(src) ) is_nd = 1; else CX_CALL( src = cxGetMat( src, &srcstub, &coi1 )); } if( !CX_IS_MAT(dst)) { if( CX_IS_MATND(dst) ) is_nd = 1; else CX_CALL( dst = cxGetMat( dst, &dststub, &coi2 )); } if( is_nd ) { CxArr* arrs[] = { src, dst }; CxMatND stubs[2]; CxNArrayIterator iterator; CX_CALL( cxInitNArrayIterator( 2, arrs, 0, stubs, &iterator )); type = CX_MAT_TYPE(iterator.hdr[0]->type); iterator.size.width *= icxPixSize[type]; pix_size = icxPixSize[type & CX_MAT_DEPTH_MASK]; CX_CALL( cxScalarToRawData( scalar, buf, type, 1 )); do { IPPI_CALL( fn_2d( iterator.ptr[0], CX_STUB_STEP, iterator.ptr[1], CX_STUB_STEP, iterator.size, buf, pix_size )); } while( cxNextNArraySlice( &iterator )); EXIT; } if( coi1 != 0 || coi2 != 0 ) CX_ERROR( CX_BadCOI, "" ); if( !CX_ARE_TYPES_EQ( src, dst ) ) CX_ERROR_FROM_CODE( CX_StsUnmatchedFormats ); if( !CX_ARE_SIZES_EQ( src, dst ) ) CX_ERROR_FROM_CODE( CX_StsUnmatchedSizes ); size = cxGetMatSize( src ); src_step = src->step; dst_step = dst->step; if( CX_IS_MAT_CONT( src->type & dst->type )) { size.width *= size.height; src_step = dst_step = CX_STUB_STEP; size.height = 1; } type = CX_MAT_TYPE( src->type ); size.width *= icxPixSize[type]; pix_size = icxPixSize[type & CX_MAT_DEPTH_MASK]; CX_CALL( cxScalarToRawData( scalar, buf, type, 1 )); IPPI_CALL( fn_2d( src->data.ptr, src_step, dst->data.ptr, dst_step, size, buf, pix_size )); __END__; }
CX_IMPL void cxAvgSdv( const void* img, CxScalar* _mean, CxScalar* _sdv, const void* mask ) { CxScalar mean = {{0,0,0,0}}; CxScalar sdv = {{0,0,0,0}}; static CxBigFuncTable meansdv_tab; static CxFuncTable meansdvcoi_tab; static CxBigFuncTable meansdvmask_tab; static CxFuncTable meansdvmaskcoi_tab; static int inittab = 0; CX_FUNCNAME("cxMean_StdDev"); __BEGIN__; int type, coi = 0; int mat_step, mask_step = 0; CxSize size; CxMat stub, maskstub, *mat = (CxMat*)img, *matmask = (CxMat*)mask; if( !inittab ) { icxInitMean_StdDevRTable( &meansdv_tab ); icxInitMean_StdDevCnCRTable( &meansdvcoi_tab ); icxInitMean_StdDevMRTable( &meansdvmask_tab ); icxInitMean_StdDevCnCMRTable( &meansdvmaskcoi_tab ); inittab = 1; } CX_CALL( mat = cxGetMat( mat, &stub, &coi )); type = CX_MAT_TYPE( mat->type ); size = cxGetMatSize( mat ); mat_step = mat->step; if( !mask ) { if( CX_IS_MAT_CONT( mat->type )) { size.width *= size.height; size.height = 1; mat_step = CX_STUB_STEP; } if( CX_MAT_CN(type) == 1 || coi == 0 ) { CxFunc2D_1A2P func = (CxFunc2D_1A2P)(meansdv_tab.fn_2d[type]); if( !func ) CX_ERROR( CX_StsBadArg, cxUnsupportedFormat ); IPPI_CALL( func( mat->data.ptr, mat_step, size, mean.val, sdv.val )); } else { CxFunc2DnC_1A2P func = (CxFunc2DnC_1A2P) (meansdvcoi_tab.fn_2d[CX_MAT_DEPTH(type)]); if( !func ) CX_ERROR( CX_StsBadArg, cxUnsupportedFormat ); IPPI_CALL( func( mat->data.ptr, mat_step, size, CX_MAT_CN(type), coi, mean.val, sdv.val )); } } else { CX_CALL( matmask = cxGetMat( matmask, &maskstub )); mask_step = matmask->step; if( !CX_IS_MASK_ARR( matmask )) CX_ERROR( CX_StsBadMask, "" ); if( !CX_ARE_SIZES_EQ( mat, matmask )) CX_ERROR( CX_StsUnmatchedSizes, "" ); if( CX_IS_MAT_CONT( mat->type & matmask->type )) { size.width *= size.height; size.height = 1; mat_step = mask_step = CX_STUB_STEP; } if( CX_MAT_CN(type) == 1 || coi == 0 ) { CxFunc2D_2A2P func = (CxFunc2D_2A2P)(meansdvmask_tab.fn_2d[type]); if( !func ) CX_ERROR( CX_StsBadArg, cxUnsupportedFormat ); IPPI_CALL( func( mat->data.ptr, mat_step, matmask->data.ptr, mask_step, size, mean.val, sdv.val )); } else { CxFunc2DnC_2A2P func = (CxFunc2DnC_2A2P) (meansdvmaskcoi_tab.fn_2d[CX_MAT_DEPTH(type)]); if( !func ) CX_ERROR( CX_StsBadArg, cxUnsupportedFormat ); IPPI_CALL( func( mat->data.ptr, mat_step, matmask->data.ptr, mask_step, size, CX_MAT_CN(type), coi, mean.val, sdv.val )); } } __END__; if( _mean ) *_mean = mean; if( _sdv ) *_sdv = sdv; }
CX_IMPL void cxKMeans2( const CxArr* samples_arr, int cluster_count, CxArr* labels_arr, CxTermCriteria termcrit ) { CxMat* centers = 0; CxMat* old_centers = 0; CxMat* counters = 0; CX_FUNCNAME( "cxKMeans2" ); __BEGIN__; CxMat samples_stub, *samples = (CxMat*)samples_arr; CxMat cluster_idx_stub, *labels = (CxMat*)labels_arr; CxMat* temp = 0; CxRandState rng; int i, k, sample_count, dims; int ids_delta, iter; double max_dist; int pix_size; if( !CX_IS_MAT( samples )) CX_CALL( samples = cxGetMat( samples, &samples_stub )); if( !CX_IS_MAT( labels )) CX_CALL( labels = cxGetMat( labels, &cluster_idx_stub )); if( cluster_count < 1 ) CX_ERROR( CX_StsOutOfRange, "Number of clusters should be positive" ); if( CX_MAT_DEPTH(samples->type) != CX_32F || CX_MAT_TYPE(labels->type) != CX_32SC1 ) CX_ERROR( CX_StsUnsupportedFormat, "samples should be floating-point matrix, cluster_idx - integer vector" ); pix_size = CX_ELEM_SIZE(samples->type); if( labels->rows != 1 && labels->cols != 1 || labels->rows + labels->cols - 1 != samples->rows ) CX_ERROR( CX_StsUnmatchedSizes, "cluster_idx should be 1D vector of the same number of elements as samples' number of rows" ); switch( termcrit.type ) { case CX_TERMCRIT_EPS: if( termcrit.epsilon < 0 ) termcrit.epsilon = 0; termcrit.maxIter = 100; break; case CX_TERMCRIT_ITER: if( termcrit.maxIter < 1 ) termcrit.maxIter = 1; termcrit.epsilon = 1e-6; break; case CX_TERMCRIT_EPS|CX_TERMCRIT_ITER: if( termcrit.epsilon < 0 ) termcrit.epsilon = 0; if( termcrit.maxIter < 1 ) termcrit.maxIter = 1; break; default: CX_ERROR( CX_StsBadArg, "Invalid termination criteria" ); } termcrit.epsilon *= termcrit.epsilon; sample_count = samples->rows; if( cluster_count > sample_count ) cluster_count = sample_count; dims = samples->cols*CX_MAT_CN(samples->type); ids_delta = labels->step ? labels->step/(int)sizeof(int) : 1; cxRandInit( &rng, 0, 1, -1, CX_RAND_UNI ); CX_CALL( centers = cxCreateMat( cluster_count, dims, CX_64FC1 )); CX_CALL( old_centers = cxCreateMat( cluster_count, dims, CX_64FC1 )); // samples_count >= cluster_count, <samples_count> // elements are used during initialization #if 0 CX_CALL( counters = cxCreateMat( 1, sample_count, CX_32SC1 )); cxZero( counters ); // init centers for( i = 0; i < cluster_count; i++ ) { int j, idx; double* c = (double*)(centers->data.ptr + i*centers->step); float* s; do idx = cxRandNext( &rng ) % cluster_count; while( counters->data.i[idx] != 0 ); counters->data.i[idx] = 1; s = (float*)(samples->data.ptr + idx*samples->step); for( j = 0; j < samples->cols; j++ ) c[j] = s[j]; } counters->cols = cluster_count; #else CX_CALL( counters = cxCreateMat( 1, cluster_count, CX_32SC1 )); // init centers for( i = 0, k = 0; i < sample_count; i++ ) { labels->data.i[i] = k; k = k < cluster_count-1 ? k+1 : 0; } #endif counters->cols = cluster_count; // cut down counters max_dist = termcrit.epsilon*2; for( iter = 0; iter < termcrit.maxIter; iter++ ) { int i, j, k; // computer centers cxZero( centers ); cxZero( counters ); for( i = 0; i < sample_count; i++ ) { float* s = (float*)(samples->data.ptr + i*samples->step); int k = labels->data.i[i*ids_delta]; double* c = (double*)(centers->data.ptr + k*centers->step); j = 0; for( ; j <= dims - 4; j += 4 ) { double t0 = c[j] + s[j]; double t1 = c[j+1] + s[j+1]; c[j] = t0; c[j+1] = t1; t0 = c[j+2] + s[j+2]; t1 = c[j+3] + s[j+3]; c[j+2] = t0; c[j+3] = t1; } for( ; j < dims; j++ ) c[j] += s[j]; counters->data.i[k]++; } if( iter > 0 ) max_dist = 0; for( k = 0; k < cluster_count; k++ ) { double* c = (double*)(centers->data.ptr + k*centers->step); if( counters->data.i[k] != 0 ) { double scale = 1./counters->data.i[k]; for( j = 0; j < dims; j++ ) c[j] *= scale; } else { int i = cxRandNext( &rng ) % sample_count; float* s = (float*)(samples->data.ptr + i*samples->step); for( j = 0; j < dims; j++ ) c[j] = s[j]; } if( iter > 0 ) { double dist = 0; double* c_o = (double*)(old_centers->data.ptr + k*old_centers->step); for( j = 0; j < dims; j++ ) { double t = c[j] - c_o[j]; dist += t*t; } if( max_dist < dist ) max_dist = dist; } } // assign labels for( i = 0; i < sample_count; i++ ) { float* s = (float*)(samples->data.ptr + i*samples->step); int k_best = 0; double min_dist = DBL_MAX; for( k = 0; k < cluster_count; k++ ) { double* c = (double*)(centers->data.ptr + k*centers->step); double dist = 0; j = 0; for( ; j <= dims - 4; j += 4 ) { double t0 = c[j] - s[j]; double t1 = c[j+1] - s[j+1]; dist += t0*t0 + t1*t1; t0 = c[j+2] - s[j+2]; t1 = c[j+3] - s[j+3]; dist += t0*t0 + t1*t1; } for( ; j < dims; j++ ) { double t = c[j] - s[j]; dist += t*t; } if( min_dist > dist ) { min_dist = dist; k_best = k; } } labels->data.i[i*ids_delta] = k_best; } if( max_dist < termcrit.epsilon ) break; CX_SWAP( centers, old_centers, temp ); } __END__; cxReleaseMat( ¢ers ); cxReleaseMat( &old_centers ); cxReleaseMat( &counters ); }