From 05ea571b080841e4f599b64df0aaeb448f753bdc Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Tue, 12 Feb 2013 18:56:22 +0400 Subject: [PATCH] almost finished distance transform conversion (discrete voronoi diagram mode is not ready yet) --- modules/imgproc/src/distransform.cpp | 441 ++++++++---------- .../imgproc/test/test_distancetransform.cpp | 16 +- 2 files changed, 197 insertions(+), 260 deletions(-) diff --git a/modules/imgproc/src/distransform.cpp b/modules/imgproc/src/distransform.cpp index 89d3a550f..02ca0fad0 100644 --- a/modules/imgproc/src/distransform.cpp +++ b/modules/imgproc/src/distransform.cpp @@ -7,10 +7,11 @@ // copy or use the software. // // -// Intel License Agreement +// License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000, Intel Corporation, all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -23,7 +24,7 @@ // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // -// * The name of Intel Corporation may not be used to endorse or promote products +// * The name of the copyright holders may not be used to endorse or promote products // derived from this software without specific prior written permission. // // This software is provided by the copyright holders and contributors "as is" and @@ -40,44 +41,48 @@ //M*/ #include "precomp.hpp" -#define ICV_DIST_SHIFT 16 -#define ICV_INIT_DIST0 (INT_MAX >> 2) - -static CvStatus -icvInitTopBottom( int* temp, int tempstep, CvSize size, int border ) +namespace cv { - int i, j; - for( i = 0; i < border; i++ ) - { - int* ttop = (int*)(temp + i*tempstep); - int* tbottom = (int*)(temp + (size.height + border*2 - i - 1)*tempstep); - for( j = 0; j < size.width + border*2; j++ ) +static const int DIST_SHIFT = 16; +static const int INIT_DIST0 = (INT_MAX >> 2); + +static void +initTopBottom( Mat& temp, int border ) +{ + Size size = temp.size(); + for( int i = 0; i < border; i++ ) + { + int* ttop = temp.ptr(i); + int* tbottom = temp.ptr(size.height - i - 1); + + for( int j = 0; j < size.width; j++ ) { - ttop[j] = ICV_INIT_DIST0; - tbottom[j] = ICV_INIT_DIST0; + ttop[j] = INIT_DIST0; + tbottom[j] = INIT_DIST0; } } - - return CV_OK; } -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 ) +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], 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); + 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); - srcstep /= sizeof(src[0]); - step /= sizeof(temp[0]); - dststep /= sizeof(dist[0]); + const uchar* src = _src.data; + int* temp = _temp.ptr(); + float* dist = _dist.ptr(); + 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(); - icvInitTopBottom( temp, step, size, BORDER ); + initTopBottom( _temp, BORDER ); // forward pass for( i = 0; i < size.height; i++ ) @@ -86,7 +91,7 @@ icvDistanceTransform_3x3_C1R( const uchar* src, int srcstep, int* temp, int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER; for( j = 0; j < BORDER; j++ ) - tmp[-j-1] = tmp[size.width + j] = ICV_INIT_DIST0; + tmp[-j-1] = tmp[size.width + j] = INIT_DIST0; for( j = 0; j < size.width; j++ ) { @@ -130,27 +135,28 @@ icvDistanceTransform_3x3_C1R( const uchar* src, int srcstep, int* temp, d[j] = (float)(t0 * scale); } } - - return CV_OK; } -static CvStatus CV_STDCALL -icvDistanceTransform_5x5_C1R( const uchar* src, int srcstep, int* temp, - int step, float* dist, int dststep, CvSize size, const float* metrics ) +static void +distanceTransform_5x5( const Mat& _src, Mat& _temp, Mat& _dist, 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); + 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); - srcstep /= sizeof(src[0]); - step /= sizeof(temp[0]); - dststep /= sizeof(dist[0]); + const uchar* src = _src.data; + int* temp = _temp.ptr(); + float* dist = _dist.ptr(); + 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(); - icvInitTopBottom( temp, step, size, BORDER ); + initTopBottom( _temp, BORDER ); // forward pass for( i = 0; i < size.height; i++ ) @@ -159,7 +165,7 @@ icvDistanceTransform_5x5_C1R( const uchar* src, int srcstep, int* temp, int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER; for( j = 0; j < BORDER; j++ ) - tmp[-j-1] = tmp[size.width + j] = ICV_INIT_DIST0; + tmp[-j-1] = tmp[size.width + j] = INIT_DIST0; for( j = 0; j < size.width; j++ ) { @@ -219,30 +225,31 @@ icvDistanceTransform_5x5_C1R( const uchar* src, int srcstep, int* temp, d[j] = (float)(t0 * scale); } } - - return CV_OK; } -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 ) +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], 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); + 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); - srcstep /= sizeof(src[0]); - step /= sizeof(temp[0]); - dststep /= sizeof(dist[0]); - lstep /= sizeof(labels[0]); + const uchar* src = _src.data; + int* temp = _temp.ptr(); + float* dist = _dist.ptr(); + int* labels = _labels.ptr(); + 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(); - icvInitTopBottom( temp, step, size, BORDER ); + initTopBottom( _temp, BORDER ); // forward pass for( i = 0; i < size.height; i++ ) @@ -252,7 +259,7 @@ icvDistanceTransformEx_5x5_C1R( const uchar* src, int srcstep, int* temp, int* lls = (int*)(labels + i*lstep); for( j = 0; j < BORDER; j++ ) - tmp[-j-1] = tmp[size.width + j] = ICV_INIT_DIST0; + tmp[-j-1] = tmp[size.width + j] = INIT_DIST0; for( j = 0; j < size.width; j++ ) { @@ -263,7 +270,7 @@ icvDistanceTransformEx_5x5_C1R( const uchar* src, int srcstep, int* temp, } else { - int t0 = ICV_INIT_DIST0, t; + int t0 = INIT_DIST0, t; int l0 = 0; t = tmp[j-step*2-1] + LONG_DIST; @@ -388,16 +395,12 @@ icvDistanceTransformEx_5x5_C1R( const uchar* src, int srcstep, int* temp, d[j] = (float)(t0 * scale); } } - - return CV_OK; } -static CvStatus -icvGetDistanceTransformMask( int maskType, float *metrics ) +static void getDistanceTransformMask( int maskType, float *metrics ) { - if( !metrics ) - return CV_NULLPTR_ERR; + CV_Assert( metrics != 0 ); switch (maskType) { @@ -434,18 +437,13 @@ icvGetDistanceTransformMask( int maskType, float *metrics ) metrics[2] = 2.1969f; break; default: - return CV_BADRANGE_ERR; + CV_Error(CV_StsBadArg, "Uknown metric type"); } - - return CV_OK; } -namespace cv -{ - struct DTColumnInvoker { - DTColumnInvoker( const CvMat* _src, CvMat* _dst, const int* _sat_tab, const float* _sqr_tab) + DTColumnInvoker( const Mat* _src, Mat* _dst, const int* _sat_tab, const float* _sqr_tab) { src = _src; dst = _dst; @@ -463,8 +461,8 @@ struct DTColumnInvoker for( i = i1; i < i2; i++ ) { - const uchar* sptr = src->data.ptr + i + (m-1)*sstep; - float* dptr = dst->data.fl + i; + const uchar* sptr = src->ptr(m-1) + i; + float* dptr = dst->ptr() + i; int j, dist = m-1; for( j = m-1; j >= 0; j--, sptr -= sstep ) @@ -483,8 +481,8 @@ struct DTColumnInvoker } } - const CvMat* src; - CvMat* dst; + const Mat* src; + Mat* dst; const int* sat_tab; const float* sqr_tab; }; @@ -492,7 +490,7 @@ struct DTColumnInvoker struct DTRowInvoker { - DTRowInvoker( CvMat* _dst, const float* _sqr_tab, const float* _inv_tab ) + DTRowInvoker( Mat* _dst, const float* _sqr_tab, const float* _inv_tab ) { dst = _dst; sqr_tab = _sqr_tab; @@ -511,7 +509,7 @@ struct DTRowInvoker for( i = i1; i < i2; i++ ) { - float* d = (float*)(dst->data.ptr + i*dst->step); + float* d = dst->ptr(i); int p, q, k; v[0] = 0; @@ -549,27 +547,20 @@ struct DTRowInvoker } } - CvMat* dst; + Mat* dst; const float* sqr_tab; const float* inv_tab; }; -} - static void -icvTrueDistTrans( const CvMat* src, CvMat* dst ) +trueDistTrans( const Mat& src, Mat& dst ) { const float inf = 1e15f; - if( !CV_ARE_SIZES_EQ( src, dst )) - CV_Error( CV_StsUnmatchedSizes, "" ); + CV_Assert( src.size() == dst.size() ); - if( CV_MAT_TYPE(src->type) != CV_8UC1 || - CV_MAT_TYPE(dst->type) != CV_32FC1 ) - CV_Error( CV_StsUnsupportedFormat, - "The input image must have 8uC1 type and the output one must have 32fC1 type" ); - - int i, m = src->rows, n = src->cols; + CV_Assert( src.type() == CV_8UC1 && dst.type() == CV_32FC1 ); + int i, m = src.rows, n = src.cols; cv::AutoBuffer _buf(std::max(m*2*sizeof(float) + (m*3+1)*sizeof(int), n*2*sizeof(float))); // stage 1: compute 1d distance transform of each column @@ -586,7 +577,7 @@ icvTrueDistTrans( const CvMat* src, CvMat* dst ) for( ; i <= m*3; i++ ) sat_tab[i] = i - shift; - cv::parallel_for(cv::BlockedRange(0, n), cv::DTColumnInvoker(src, dst, sat_tab, sqr_tab)); + cv::parallel_for(cv::BlockedRange(0, n), cv::DTColumnInvoker(&src, &dst, sat_tab, sqr_tab)); // stage 2: compute modified distance transform for each row float* inv_tab = sqr_tab + n; @@ -598,25 +589,109 @@ icvTrueDistTrans( const CvMat* src, CvMat* dst ) sqr_tab[i] = (float)(i*i); } - cv::parallel_for(cv::BlockedRange(0, m), cv::DTRowInvoker(dst, sqr_tab, inv_tab)); + cv::parallel_for(cv::BlockedRange(0, m), cv::DTRowInvoker(&dst, sqr_tab, inv_tab)); +} + } -/*********************************** IPP functions *********************************/ +// Wrapper function for distance transform group +void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labels, + int distType, int maskSize, int labelType ) +{ + Mat src = _src.getMat(); + _dst.create( src.size(), CV_32F ); + Mat dst = _dst.getMat(), labels; + bool need_labels = _labels.needed(); -typedef CvStatus (CV_STDCALL * CvIPPDistTransFunc)( const uchar* src, int srcstep, - void* dst, int dststep, - CvSize size, const void* metrics ); + if( need_labels ) + { + CV_Assert( labelType == DIST_LABEL_PIXEL || labelType == DIST_LABEL_CCOMP ); -typedef CvStatus (CV_STDCALL * CvIPPDistTransFunc2)( uchar* src, int srcstep, - CvSize size, const int* metrics ); + _labels.create(src.size(), CV_32S); + labels = _labels.getMat(); + maskSize = CV_DIST_MASK_5; + } -/***********************************************************************************/ + CV_Assert( src.type() == CV_8UC1 ); + float _mask[5] = {0}; -typedef CvStatus (CV_STDCALL * CvDistTransFunc)( const uchar* src, int srcstep, - int* temp, int tempstep, - float* dst, int dststep, - CvSize size, const float* metrics ); + 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 = !need_labels ? CV_DIST_MASK_3 : CV_DIST_MASK_5; + else if( distType == CV_DIST_L2 && need_labels ) + maskSize = CV_DIST_MASK_5; + + if( maskSize == CV_DIST_MASK_PRECISE ) + { + trueDistTrans( src, dst ); + return; + } + + CV_Assert( distType == CV_DIST_C || distType == CV_DIST_L1 || distType == CV_DIST_L2 ); + + getDistanceTransformMask( (distType == CV_DIST_C ? 0 : + distType == CV_DIST_L1 ? 1 : 2) + maskSize*10, _mask ); + + Size size = src.size(); + + int border = maskSize == CV_DIST_MASK_3 ? 1 : 2; + Mat temp( size.height + border*2, size.width + border*2, CV_32SC1 ); + + if( !need_labels ) + { + if( maskSize == CV_DIST_MASK_3 ) + distanceTransform_3x3(src, temp, dst, _mask); + else + distanceTransform_5x5(src, temp, dst, _mask); + } + else + { + labels.setTo(Scalar::all(0)); + + if( labelType == CV_DIST_LABEL_CCOMP ) + { + /*CvSeq *contours = 0; + cv::Ptr st = cvCreateMemStorage(); + cv::Ptr 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 ); + }*/ + // TODO + } + else + { + int k = 1; + for( int i = 0; i < src.rows; i++ ) + { + const uchar* srcptr = src.ptr(i); + int* labelptr = labels.ptr(i); + + for( int j = 0; j < src.cols; j++ ) + if( srcptr[j] == 0 ) + labelptr[j] = k++; + } + } + + distanceTransformEx_5x5( src, temp, dst, labels, _mask ); + } +} + + +void cv::distanceTransform( InputArray _src, OutputArray _dst, + int distanceType, int maskSize ) +{ + distanceTransform(_src, _dst, noArray(), distanceType, maskSize, DIST_LABEL_PIXEL); +} /****************************************************************************************\ @@ -627,21 +702,21 @@ typedef CvStatus (CV_STDCALL * CvDistTransFunc)( const uchar* src, int srcstep, //BEGIN ATS ADDITION /* 8-bit grayscale distance transform function */ static void -icvDistanceATS_L1_8u( const CvMat* src, CvMat* dst ) +icvDistanceATS_L1_8u( const cv::Mat& src, cv::Mat& dst ) { - int width = src->cols, height = src->rows; + int width = src.cols, height = src.rows; int a; uchar lut[256]; int x, y; - const uchar *sbase = src->data.ptr; - uchar *dbase = dst->data.ptr; - int srcstep = src->step; - int dststep = dst->step; + const uchar *sbase = src.data; + uchar *dbase = dst.data; + int srcstep = (int)src.step; + int dststep = (int)dst.step; - CV_Assert( CV_IS_MASK_ARR( src ) && CV_MAT_TYPE( dst->type ) == CV_8UC1 ); - CV_Assert( CV_ARE_SIZES_EQ( src, dst )); + CV_Assert( src.type() == CV_8UC1 && dst.type() == CV_8UC1 ); + CV_Assert( src.size() == dst.size() ); ////////////////////// forward scan //////////////////////// for( x = 0; x < 256; x++ ) @@ -700,150 +775,22 @@ icvDistanceATS_L1_8u( const CvMat* src, CvMat* dst ) } //END ATS ADDITION - -/* 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 ) + 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; + cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr); + cv::Mat labels = cv::cvarrToMat(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 ) - { + if( !labelsarr && distType == CV_DIST_L1 && dst.type() == CV_8U ) icvDistanceATS_L1_8u( src, dst ); - } - else - { - int border = maskSize == CV_DIST_MASK_3 ? 1 : 2; - cv::Ptr 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; + cv::distanceTransform(src, dst, labelsarr ? cv::_OutputArray(labels) : cv::_OutputArray(), + distType, maskSize, labelType); - 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 st = cvCreateMemStorage(); - cv::Ptr 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 ); - } - } } -void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labels, - int distanceType, int maskSize, int labelType ) -{ - Mat src = _src.getMat(); - _dst.create(src.size(), CV_32F); - _labels.create(src.size(), CV_32S); - CvMat c_src = src, c_dst = _dst.getMat(), c_labels = _labels.getMat(); - cvDistTransform(&c_src, &c_dst, distanceType, maskSize, 0, &c_labels, labelType); -} - -void cv::distanceTransform( InputArray _src, OutputArray _dst, - int distanceType, int maskSize ) -{ - Mat src = _src.getMat(); - _dst.create(src.size(), CV_32F); - Mat dst = _dst.getMat(); - CvMat c_src = src, c_dst = _dst.getMat(); - cvDistTransform(&c_src, &c_dst, distanceType, maskSize, 0, 0, -1); -} /* End of file. */ diff --git a/modules/imgproc/test/test_distancetransform.cpp b/modules/imgproc/test/test_distancetransform.cpp index da7e33449..9ce9c6c42 100644 --- a/modules/imgproc/test/test_distancetransform.cpp +++ b/modules/imgproc/test/test_distancetransform.cpp @@ -90,30 +90,20 @@ void CV_DisTransTest::get_test_array_types_and_sizes( int test_case_idx, if( cvtest::randInt(rng) & 1 ) { mask_size = 3; - dist_type = cvtest::randInt(rng) % 4; - dist_type = dist_type == 0 ? CV_DIST_C : dist_type == 1 ? CV_DIST_L1 : - dist_type == 2 ? CV_DIST_L2 : CV_DIST_USER; } else { mask_size = 5; - dist_type = cvtest::randInt(rng) % 10; - dist_type = dist_type == 0 ? CV_DIST_C : dist_type == 1 ? CV_DIST_L1 : - dist_type < 6 ? CV_DIST_L2 : CV_DIST_USER; } + dist_type = cvtest::randInt(rng) % 3; + dist_type = dist_type == 0 ? CV_DIST_C : dist_type == 1 ? CV_DIST_L1 : CV_DIST_L2; + // for now, check only the "labeled" distance transform mode fill_labels = 0; if( !fill_labels ) sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = cvSize(0,0); - - if( dist_type == CV_DIST_USER ) - { - mask[0] = (float)(1.1 - cvtest::randReal(rng)*0.2); - mask[1] = (float)(1.9 - cvtest::randReal(rng)*0.8); - mask[2] = (float)(3. - cvtest::randReal(rng)); - } }