static void distanceTransform_3x3( const Mat& _src, Mat& _temp, Mat& _dist, const float* metrics ) { const int BORDER = 1; int i, j; const int HV_DIST = CV_FLT_TO_FIX( metrics[0], DIST_SHIFT ); const int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], DIST_SHIFT ); const float scale = 1.f/(1 << DIST_SHIFT); const uchar* src = _src.ptr(); int* temp = _temp.ptr<int>(); float* dist = _dist.ptr<float>(); int srcstep = (int)(_src.step/sizeof(src[0])); int step = (int)(_temp.step/sizeof(temp[0])); int dststep = (int)(_dist.step/sizeof(dist[0])); Size size = _src.size(); initTopBottom( _temp, BORDER ); // forward pass for( i = 0; i < size.height; i++ ) { const uchar* s = src + i*srcstep; int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER; for( j = 0; j < BORDER; j++ ) tmp[-j-1] = tmp[size.width + j] = INIT_DIST0; for( j = 0; j < size.width; j++ ) { if( !s[j] ) tmp[j] = 0; else { int t0 = tmp[j-step-1] + DIAG_DIST; int t = tmp[j-step] + HV_DIST; if( t0 > t ) t0 = t; t = tmp[j-step+1] + DIAG_DIST; if( t0 > t ) t0 = t; t = tmp[j-1] + HV_DIST; if( t0 > t ) t0 = t; tmp[j] = t0; } } } // backward pass for( i = size.height - 1; i >= 0; i-- ) { float* d = (float*)(dist + i*dststep); int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER; for( j = size.width - 1; j >= 0; j-- ) { int t0 = tmp[j]; if( t0 > HV_DIST ) { int t = tmp[j+step+1] + DIAG_DIST; if( t0 > t ) t0 = t; t = tmp[j+step] + HV_DIST; if( t0 > t ) t0 = t; t = tmp[j+step-1] + DIAG_DIST; if( t0 > t ) t0 = t; t = tmp[j+1] + HV_DIST; if( t0 > t ) t0 = t; tmp[j] = t0; } d[j] = (float)(t0 * scale); } } }
static CvStatus CV_STDCALL icvDistanceTransform_3x3_C1R( const uchar* src, int srcstep, int* temp, int step, float* dist, int dststep, CvSize size, const float* metrics ) { const int BORDER = 1; int i, j; const int HV_DIST = CV_FLT_TO_FIX( metrics[0], ICV_DIST_SHIFT ); const int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], ICV_DIST_SHIFT ); const float scale = 1.f/(1 << ICV_DIST_SHIFT); srcstep /= sizeof(src[0]); step /= sizeof(temp[0]); dststep /= sizeof(dist[0]); icvInitTopBottom( temp, step, size, BORDER ); // forward pass for( i = 0; i < size.height; i++ ) { const uchar* s = src + i*srcstep; int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER; for( j = 0; j < BORDER; j++ ) tmp[-j-1] = tmp[size.width + j] = ICV_INIT_DIST0; for( j = 0; j < size.width; j++ ) { if( !s[j] ) tmp[j] = 0; else { int t0 = tmp[j-step-1] + DIAG_DIST; int t = tmp[j-step] + HV_DIST; if( t0 > t ) t0 = t; t = tmp[j-step+1] + DIAG_DIST; if( t0 > t ) t0 = t; t = tmp[j-1] + HV_DIST; if( t0 > t ) t0 = t; tmp[j] = t0; } } } // backward pass for( i = size.height - 1; i >= 0; i-- ) { float* d = (float*)(dist + i*dststep); int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER; for( j = size.width - 1; j >= 0; j-- ) { int t0 = tmp[j]; if( t0 > HV_DIST ) { int t = tmp[j+step+1] + DIAG_DIST; if( t0 > t ) t0 = t; t = tmp[j+step] + HV_DIST; if( t0 > t ) t0 = t; t = tmp[j+step-1] + DIAG_DIST; if( t0 > t ) t0 = t; t = tmp[j+1] + HV_DIST; if( t0 > t ) t0 = t; tmp[j] = t0; } d[j] = (float)(t0 * scale); } } return CV_OK; }
static void distanceTransformEx_5x5( const Mat& _src, Mat& _temp, Mat& _dist, Mat& _labels, const float* metrics ) { const int BORDER = 2; int i, j; const int HV_DIST = CV_FLT_TO_FIX( metrics[0], DIST_SHIFT ); const int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], DIST_SHIFT ); const int LONG_DIST = CV_FLT_TO_FIX( metrics[2], DIST_SHIFT ); const float scale = 1.f/(1 << DIST_SHIFT); const uchar* src = _src.ptr(); int* temp = _temp.ptr<int>(); float* dist = _dist.ptr<float>(); int* labels = _labels.ptr<int>(); int srcstep = (int)(_src.step/sizeof(src[0])); int step = (int)(_temp.step/sizeof(temp[0])); int dststep = (int)(_dist.step/sizeof(dist[0])); int lstep = (int)(_labels.step/sizeof(dist[0])); Size size = _src.size(); initTopBottom( _temp, BORDER ); // forward pass for( i = 0; i < size.height; i++ ) { const uchar* s = src + i*srcstep; int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER; int* lls = (int*)(labels + i*lstep); for( j = 0; j < BORDER; j++ ) tmp[-j-1] = tmp[size.width + j] = INIT_DIST0; for( j = 0; j < size.width; j++ ) { if( !s[j] ) { tmp[j] = 0; //assert( lls[j] != 0 ); } else { int t0 = INIT_DIST0, t; int l0 = 0; t = tmp[j-step*2-1] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep*2-1]; } t = tmp[j-step*2+1] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep*2+1]; } t = tmp[j-step-2] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep-2]; } t = tmp[j-step-1] + DIAG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep-1]; } t = tmp[j-step] + HV_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep]; } t = tmp[j-step+1] + DIAG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep+1]; } t = tmp[j-step+2] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep+2]; } t = tmp[j-1] + HV_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-1]; } tmp[j] = t0; lls[j] = l0; } } } // backward pass for( i = size.height - 1; i >= 0; i-- ) { float* d = (float*)(dist + i*dststep); int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER; int* lls = (int*)(labels + i*lstep); for( j = size.width - 1; j >= 0; j-- ) { int t0 = tmp[j]; int l0 = lls[j]; if( t0 > HV_DIST ) { int t = tmp[j+step*2+1] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep*2+1]; } t = tmp[j+step*2-1] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep*2-1]; } t = tmp[j+step+2] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep+2]; } t = tmp[j+step+1] + DIAG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep+1]; } t = tmp[j+step] + HV_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep]; } t = tmp[j+step-1] + DIAG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep-1]; } t = tmp[j+step-2] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep-2]; } t = tmp[j+1] + HV_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+1]; } tmp[j] = t0; lls[j] = l0; } d[j] = (float)(t0 * scale); } } }
static CvStatus CV_STDCALL icvDistanceTransformEx_5x5_C1R( const uchar* src, int srcstep, int* temp, int step, float* dist, int dststep, int* labels, int lstep, CvSize size, const float* metrics ) { const int BORDER = 2; int i, j; const int HV_DIST = CV_FLT_TO_FIX( metrics[0], ICV_DIST_SHIFT ); const int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], ICV_DIST_SHIFT ); const int LONG_DIST = CV_FLT_TO_FIX( metrics[2], ICV_DIST_SHIFT ); const float scale = 1.f/(1 << ICV_DIST_SHIFT); srcstep /= sizeof(src[0]); step /= sizeof(temp[0]); dststep /= sizeof(dist[0]); lstep /= sizeof(labels[0]); icvInitTopBottom( temp, step, size, BORDER ); // forward pass for( i = 0; i < size.height; i++ ) { const uchar* s = src + i*srcstep; int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER; int* lls = (int*)(labels + i*lstep); for( j = 0; j < BORDER; j++ ) tmp[-j-1] = tmp[size.width + j] = ICV_INIT_DIST0; for( j = 0; j < size.width; j++ ) { if( !s[j] ) { tmp[j] = 0; //assert( lls[j] != 0 ); } else { int t0 = ICV_INIT_DIST0, t; int l0 = 0; t = tmp[j-step*2-1] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep*2-1]; } t = tmp[j-step*2+1] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep*2+1]; } t = tmp[j-step-2] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep-2]; } t = tmp[j-step-1] + DIAG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep-1]; } t = tmp[j-step] + HV_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep]; } t = tmp[j-step+1] + DIAG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep+1]; } t = tmp[j-step+2] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-lstep+2]; } t = tmp[j-1] + HV_DIST; if( t0 > t ) { t0 = t; l0 = lls[j-1]; } tmp[j] = t0; lls[j] = l0; } } } // backward pass for( i = size.height - 1; i >= 0; i-- ) { float* d = (float*)(dist + i*dststep); int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER; int* lls = (int*)(labels + i*lstep); for( j = size.width - 1; j >= 0; j-- ) { int t0 = tmp[j]; int l0 = lls[j]; if( t0 > HV_DIST ) { int t = tmp[j+step*2+1] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep*2+1]; } t = tmp[j+step*2-1] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep*2-1]; } t = tmp[j+step+2] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep+2]; } t = tmp[j+step+1] + DIAG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep+1]; } t = tmp[j+step] + HV_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep]; } t = tmp[j+step-1] + DIAG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep-1]; } t = tmp[j+step-2] + LONG_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+lstep-2]; } t = tmp[j+1] + HV_DIST; if( t0 > t ) { t0 = t; l0 = lls[j+1]; } tmp[j] = t0; lls[j] = l0; } d[j] = (float)(t0 * scale); } } return CV_OK; }