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__; }
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__; }
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__; }
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 ); }