/* Wrapper function for distance transform group */ CV_IMPL void cvDistTransform( const void* srcarr, void* dstarr, int distType, int maskSize, const float *mask, void* labelsarr ) { cv::Ptr<CvMat> temp; cv::Ptr<CvMat> src_copy; cv::Ptr<CvMemStorage> st; float _mask[5] = {0}; CvMat srcstub, *src = (CvMat*)srcarr; CvMat dststub, *dst = (CvMat*)dstarr; CvMat lstub, *labels = (CvMat*)labelsarr; CvSize size; //CvIPPDistTransFunc ipp_func = 0; //CvIPPDistTransFunc2 ipp_inp_func = 0; src = cvGetMat( src, &srcstub ); dst = cvGetMat( dst, &dststub ); if( !CV_IS_MASK_ARR( src ) || (CV_MAT_TYPE( dst->type ) != CV_32FC1 && (CV_MAT_TYPE(dst->type) != CV_8UC1 || distType != CV_DIST_L1 || labels)) ) CV_Error( CV_StsUnsupportedFormat, "source image must be 8uC1 and the distance map must be 32fC1 " "(or 8uC1 in case of simple L1 distance transform)" ); if( !CV_ARE_SIZES_EQ( src, dst )) CV_Error( CV_StsUnmatchedSizes, "the source and the destination images must be of the same size" ); if( maskSize != CV_DIST_MASK_3 && maskSize != CV_DIST_MASK_5 && maskSize != CV_DIST_MASK_PRECISE ) CV_Error( CV_StsBadSize, "Mask size should be 3 or 5 or 0 (presize)" ); if( distType == CV_DIST_C || distType == CV_DIST_L1 ) maskSize = !labels ? CV_DIST_MASK_3 : CV_DIST_MASK_5; else if( distType == CV_DIST_L2 && labels ) maskSize = CV_DIST_MASK_5; if( maskSize == CV_DIST_MASK_PRECISE ) { icvTrueDistTrans( src, dst ); return; } if( labels ) { labels = cvGetMat( labels, &lstub ); if( CV_MAT_TYPE( labels->type ) != CV_32SC1 ) CV_Error( CV_StsUnsupportedFormat, "the output array of labels must be 32sC1" ); if( !CV_ARE_SIZES_EQ( labels, dst )) CV_Error( CV_StsUnmatchedSizes, "the array of labels has a different size" ); if( maskSize == CV_DIST_MASK_3 ) CV_Error( CV_StsNotImplemented, "3x3 mask can not be used for \"labeled\" distance transform. Use 5x5 mask" ); } if( distType == CV_DIST_C || distType == CV_DIST_L1 || distType == CV_DIST_L2 ) { icvGetDistanceTransformMask( (distType == CV_DIST_C ? 0 : distType == CV_DIST_L1 ? 1 : 2) + maskSize*10, _mask ); } else if( distType == CV_DIST_USER ) { if( !mask ) CV_Error( CV_StsNullPtr, "" ); memcpy( _mask, mask, (maskSize/2 + 1)*sizeof(float)); } /*if( !labels ) { if( CV_MAT_TYPE(dst->type) == CV_32FC1 ) ipp_func = (CvIPPDistTransFunc)(maskSize == CV_DIST_MASK_3 ? icvDistanceTransform_3x3_8u32f_C1R_p : icvDistanceTransform_5x5_8u32f_C1R_p); else if( src->data.ptr != dst->data.ptr ) ipp_func = (CvIPPDistTransFunc)icvDistanceTransform_3x3_8u_C1R_p; else ipp_inp_func = icvDistanceTransform_3x3_8u_C1IR_p; }*/ size = cvGetMatSize(src); /*if( (ipp_func || ipp_inp_func) && src->cols >= 4 && src->rows >= 2 ) { int _imask[3]; _imask[0] = cvRound(_mask[0]); _imask[1] = cvRound(_mask[1]); _imask[2] = cvRound(_mask[2]); if( ipp_func ) { IPPI_CALL( ipp_func( src->data.ptr, src->step, dst->data.fl, dst->step, size, CV_MAT_TYPE(dst->type) == CV_8UC1 ? (void*)_imask : (void*)_mask )); } else { IPPI_CALL( ipp_inp_func( src->data.ptr, src->step, size, _imask )); } } else*/ if( CV_MAT_TYPE(dst->type) == CV_8UC1 ) { icvDistanceATS_L1_8u( src, dst ); } else { int border = maskSize == CV_DIST_MASK_3 ? 1 : 2; temp = cvCreateMat( size.height + border*2, size.width + border*2, CV_32SC1 ); if( !labels ) { CvDistTransFunc func = maskSize == CV_DIST_MASK_3 ? icvDistanceTransform_3x3_C1R : icvDistanceTransform_5x5_C1R; func( src->data.ptr, src->step, temp->data.i, temp->step, dst->data.fl, dst->step, size, _mask ); } else { CvSeq *contours = 0; CvPoint top_left = {0,0}, bottom_right = {size.width-1,size.height-1}; int label; st = cvCreateMemStorage(); src_copy = cvCreateMat( size.height, size.width, src->type ); cvCmpS( src, 0, src_copy, CV_CMP_EQ ); cvFindContours( src_copy, st, &contours, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); cvZero( labels ); for( label = 1; contours != 0; contours = contours->h_next, label++ ) { CvScalar area_color = cvScalarAll(label); cvDrawContours( labels, contours, area_color, area_color, -255, -1, 8 ); } cvCopy( src, src_copy ); cvRectangle( src_copy, top_left, bottom_right, cvScalarAll(255), 1, 8 ); icvDistanceTransformEx_5x5_C1R( src_copy->data.ptr, src_copy->step, temp->data.i, temp->step, dst->data.fl, dst->step, labels->data.i, labels->step, size, _mask ); } } }
/* Wrapper function for distance transform group */ CV_IMPL void cvDistTransform( const void* srcarr, void* dstarr, int distType, int maskSize, const float *mask, void* labelsarr, int labelType ) { float _mask[5] = {0}; CvMat srcstub, *src = (CvMat*)srcarr; CvMat dststub, *dst = (CvMat*)dstarr; CvMat lstub, *labels = (CvMat*)labelsarr; src = cvGetMat( src, &srcstub ); dst = cvGetMat( dst, &dststub ); if( !CV_IS_MASK_ARR( src ) || (CV_MAT_TYPE( dst->type ) != CV_32FC1 && (CV_MAT_TYPE(dst->type) != CV_8UC1 || distType != CV_DIST_L1 || labels)) ) CV_Error( CV_StsUnsupportedFormat, "source image must be 8uC1 and the distance map must be 32fC1 " "(or 8uC1 in case of simple L1 distance transform)" ); if( !CV_ARE_SIZES_EQ( src, dst )) CV_Error( CV_StsUnmatchedSizes, "the source and the destination images must be of the same size" ); if( maskSize != CV_DIST_MASK_3 && maskSize != CV_DIST_MASK_5 && maskSize != CV_DIST_MASK_PRECISE ) CV_Error( CV_StsBadSize, "Mask size should be 3 or 5 or 0 (presize)" ); if( distType == CV_DIST_C || distType == CV_DIST_L1 ) maskSize = !labels ? CV_DIST_MASK_3 : CV_DIST_MASK_5; else if( distType == CV_DIST_L2 && labels ) maskSize = CV_DIST_MASK_5; if( maskSize == CV_DIST_MASK_PRECISE ) { icvTrueDistTrans( src, dst ); return; } if( labels ) { labels = cvGetMat( labels, &lstub ); if( CV_MAT_TYPE( labels->type ) != CV_32SC1 ) CV_Error( CV_StsUnsupportedFormat, "the output array of labels must be 32sC1" ); if( !CV_ARE_SIZES_EQ( labels, dst )) CV_Error( CV_StsUnmatchedSizes, "the array of labels has a different size" ); if( maskSize == CV_DIST_MASK_3 ) CV_Error( CV_StsNotImplemented, "3x3 mask can not be used for \"labeled\" distance transform. Use 5x5 mask" ); } if( distType == CV_DIST_C || distType == CV_DIST_L1 || distType == CV_DIST_L2 ) { icvGetDistanceTransformMask( (distType == CV_DIST_C ? 0 : distType == CV_DIST_L1 ? 1 : 2) + maskSize*10, _mask ); } else if( distType == CV_DIST_USER ) { if( !mask ) CV_Error( CV_StsNullPtr, "" ); memcpy( _mask, mask, (maskSize/2 + 1)*sizeof(float)); } CvSize size = cvGetMatSize(src); if( CV_MAT_TYPE(dst->type) == CV_8UC1 ) { icvDistanceATS_L1_8u( src, dst ); } else { int border = maskSize == CV_DIST_MASK_3 ? 1 : 2; cv::Ptr<CvMat> temp = cvCreateMat( size.height + border*2, size.width + border*2, CV_32SC1 ); if( !labels ) { CvDistTransFunc func = maskSize == CV_DIST_MASK_3 ? icvDistanceTransform_3x3_C1R : icvDistanceTransform_5x5_C1R; func( src->data.ptr, src->step, temp->data.i, temp->step, dst->data.fl, dst->step, size, _mask ); } else { cvZero( labels ); if( labelType == CV_DIST_LABEL_CCOMP ) { CvSeq *contours = 0; cv::Ptr<CvMemStorage> st = cvCreateMemStorage(); cv::Ptr<CvMat> src_copy = cvCreateMat( size.height+border*2, size.width+border*2, src->type ); cvCopyMakeBorder(src, src_copy, cvPoint(border, border), IPL_BORDER_CONSTANT, cvScalarAll(255)); cvCmpS( src_copy, 0, src_copy, CV_CMP_EQ ); cvFindContours( src_copy, st, &contours, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(-border, -border)); for( int label = 1; contours != 0; contours = contours->h_next, label++ ) { CvScalar area_color = cvScalarAll(label); cvDrawContours( labels, contours, area_color, area_color, -255, -1, 8 ); } } else { int k = 1; for( int i = 0; i < src->rows; i++ ) { const uchar* srcptr = src->data.ptr + src->step*i; int* labelptr = (int*)(labels->data.ptr + labels->step*i); for( int j = 0; j < src->cols; j++ ) if( srcptr[j] == 0 ) labelptr[j] = k++; } } icvDistanceTransformEx_5x5_C1R( src->data.ptr, src->step, temp->data.i, temp->step, dst->data.fl, dst->step, labels->data.i, labels->step, size, _mask ); } } }