Merge pull request #2624 from ElenaGvozdeva:ipp_DistanceTransform
This commit is contained in:
commit
6823b36974
@ -411,7 +411,7 @@ distanceTransform
|
|||||||
-----------------
|
-----------------
|
||||||
Calculates the distance to the closest zero pixel for each pixel of the source image.
|
Calculates the distance to the closest zero pixel for each pixel of the source image.
|
||||||
|
|
||||||
.. ocv:function:: void distanceTransform( InputArray src, OutputArray dst, int distanceType, int maskSize )
|
.. ocv:function:: void distanceTransform( InputArray src, OutputArray dst, int distanceType, int maskSize, int dstType=CV_32F )
|
||||||
|
|
||||||
.. ocv:function:: void distanceTransform( InputArray src, OutputArray dst, OutputArray labels, int distanceType, int maskSize, int labelType=DIST_LABEL_CCOMP )
|
.. ocv:function:: void distanceTransform( InputArray src, OutputArray dst, OutputArray labels, int distanceType, int maskSize, int labelType=DIST_LABEL_CCOMP )
|
||||||
|
|
||||||
@ -421,12 +421,14 @@ Calculates the distance to the closest zero pixel for each pixel of the source i
|
|||||||
|
|
||||||
:param src: 8-bit, single-channel (binary) source image.
|
:param src: 8-bit, single-channel (binary) source image.
|
||||||
|
|
||||||
:param dst: Output image with calculated distances. It is a 32-bit floating-point, single-channel image of the same size as ``src`` .
|
:param dst: Output image with calculated distances. It is a 8-bit or 32-bit floating-point, single-channel image of the same size as ``src`` .
|
||||||
|
|
||||||
:param distanceType: Type of distance. It can be ``CV_DIST_L1, CV_DIST_L2`` , or ``CV_DIST_C`` .
|
:param distanceType: Type of distance. It can be ``CV_DIST_L1, CV_DIST_L2`` , or ``CV_DIST_C`` .
|
||||||
|
|
||||||
:param maskSize: Size of the distance transform mask. It can be 3, 5, or ``CV_DIST_MASK_PRECISE`` (the latter option is only supported by the first function). In case of the ``CV_DIST_L1`` or ``CV_DIST_C`` distance type, the parameter is forced to 3 because a :math:`3\times 3` mask gives the same result as :math:`5\times 5` or any larger aperture.
|
:param maskSize: Size of the distance transform mask. It can be 3, 5, or ``CV_DIST_MASK_PRECISE`` (the latter option is only supported by the first function). In case of the ``CV_DIST_L1`` or ``CV_DIST_C`` distance type, the parameter is forced to 3 because a :math:`3\times 3` mask gives the same result as :math:`5\times 5` or any larger aperture.
|
||||||
|
|
||||||
|
:param dstType: Type of output image. It can be ``CV_8U`` or ``CV_32F``. Type ``CV_8U`` can be used only for the first variant of the function and ``distanceType == CV_DIST_L1``.
|
||||||
|
|
||||||
:param labels: Optional output 2D array of labels (the discrete Voronoi diagram). It has the type ``CV_32SC1`` and the same size as ``src`` . See the details below.
|
:param labels: Optional output 2D array of labels (the discrete Voronoi diagram). It has the type ``CV_32SC1`` and the same size as ``src`` . See the details below.
|
||||||
|
|
||||||
:param labelType: Type of the label array to build. If ``labelType==DIST_LABEL_CCOMP`` then each connected component of zeros in ``src`` (as well as all the non-zero pixels closest to the connected component) will be assigned the same label. If ``labelType==DIST_LABEL_PIXEL`` then each zero pixel (and all the non-zero pixels closest to it) gets its own label.
|
:param labelType: Type of the label array to build. If ``labelType==DIST_LABEL_CCOMP`` then each connected component of zeros in ``src`` (as well as all the non-zero pixels closest to the connected component) will be assigned the same label. If ``labelType==DIST_LABEL_PIXEL`` then each zero pixel (and all the non-zero pixels closest to it) gets its own label.
|
||||||
|
@ -1389,7 +1389,7 @@ CV_EXPORTS_AS(distanceTransformWithLabels) void distanceTransform( InputArray sr
|
|||||||
|
|
||||||
//! computes the distance transform map
|
//! computes the distance transform map
|
||||||
CV_EXPORTS_W void distanceTransform( InputArray src, OutputArray dst,
|
CV_EXPORTS_W void distanceTransform( InputArray src, OutputArray dst,
|
||||||
int distanceType, int maskSize );
|
int distanceType, int maskSize, int dstType=CV_32F);
|
||||||
|
|
||||||
|
|
||||||
//! fills the semi-uniform image region starting from the specified seed point
|
//! fills the semi-uniform image region starting from the specified seed point
|
||||||
|
@ -21,3 +21,82 @@ PERF_TEST_P(Size_DistanceTransform, icvTrueDistTrans, testing::Values(TYPICAL_MA
|
|||||||
|
|
||||||
SANITY_CHECK(dst, 1);
|
SANITY_CHECK(dst, 1);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
#include "perf_precomp.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace cv;
|
||||||
|
using namespace perf;
|
||||||
|
using std::tr1::make_tuple;
|
||||||
|
using std::tr1::get;
|
||||||
|
|
||||||
|
CV_ENUM(DistanceType, DIST_L1, DIST_L2 , DIST_C)
|
||||||
|
CV_ENUM(MaskSize, DIST_MASK_3, DIST_MASK_5, DIST_MASK_PRECISE)
|
||||||
|
CV_ENUM(DstType, CV_8U, CV_32F)
|
||||||
|
CV_ENUM(LabelType, DIST_LABEL_CCOMP, DIST_LABEL_PIXEL)
|
||||||
|
|
||||||
|
typedef std::tr1::tuple<Size, DistanceType, MaskSize, DstType> SrcSize_DistType_MaskSize_DstType;
|
||||||
|
typedef std::tr1::tuple<Size, DistanceType, MaskSize, LabelType> SrcSize_DistType_MaskSize_LabelType;
|
||||||
|
typedef perf::TestBaseWithParam<SrcSize_DistType_MaskSize_DstType> DistanceTransform_Test;
|
||||||
|
typedef perf::TestBaseWithParam<SrcSize_DistType_MaskSize_LabelType> DistanceTransform_NeedLabels_Test;
|
||||||
|
|
||||||
|
PERF_TEST_P(DistanceTransform_Test, distanceTransform,
|
||||||
|
testing::Combine(
|
||||||
|
testing::Values(cv::Size(640, 480), cv::Size(800, 600), cv::Size(1024, 768), cv::Size(1280, 1024)),
|
||||||
|
DistanceType::all(),
|
||||||
|
MaskSize::all(),
|
||||||
|
DstType::all()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Size srcSize = get<0>(GetParam());
|
||||||
|
int distanceType = get<1>(GetParam());
|
||||||
|
int maskSize = get<2>(GetParam());
|
||||||
|
int dstType = get<3>(GetParam());
|
||||||
|
|
||||||
|
Mat src(srcSize, CV_8U);
|
||||||
|
Mat dst(srcSize, dstType);
|
||||||
|
|
||||||
|
declare
|
||||||
|
.in(src, WARMUP_RNG)
|
||||||
|
.out(dst, WARMUP_RNG)
|
||||||
|
.time(30);
|
||||||
|
|
||||||
|
TEST_CYCLE() distanceTransform( src, dst, distanceType, maskSize, dstType);
|
||||||
|
|
||||||
|
double eps = 2e-4;
|
||||||
|
|
||||||
|
SANITY_CHECK(dst, eps);
|
||||||
|
}
|
||||||
|
|
||||||
|
PERF_TEST_P(DistanceTransform_NeedLabels_Test, distanceTransform_NeedLabels,
|
||||||
|
testing::Combine(
|
||||||
|
testing::Values(cv::Size(640, 480), cv::Size(800, 600), cv::Size(1024, 768), cv::Size(1280, 1024)),
|
||||||
|
DistanceType::all(),
|
||||||
|
MaskSize::all(),
|
||||||
|
LabelType::all()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Size srcSize = get<0>(GetParam());
|
||||||
|
int distanceType = get<1>(GetParam());
|
||||||
|
int maskSize = get<2>(GetParam());
|
||||||
|
int labelType = get<3>(GetParam());
|
||||||
|
|
||||||
|
Mat src(srcSize, CV_8U);
|
||||||
|
Mat label(srcSize, CV_32S);
|
||||||
|
Mat dst(srcSize, CV_32F);
|
||||||
|
|
||||||
|
declare
|
||||||
|
.in(src, WARMUP_RNG)
|
||||||
|
.out(label, WARMUP_RNG)
|
||||||
|
.out(dst, WARMUP_RNG)
|
||||||
|
.time(30);
|
||||||
|
|
||||||
|
TEST_CYCLE() distanceTransform( src, dst, label, distanceType, maskSize, labelType);
|
||||||
|
|
||||||
|
double eps = 2e-4;
|
||||||
|
|
||||||
|
SANITY_CHECK(label, eps);
|
||||||
|
SANITY_CHECK(dst, eps);
|
||||||
|
}
|
||||||
|
@ -488,7 +488,6 @@ struct DTColumnInvoker : ParallelLoopBody
|
|||||||
const float* sqr_tab;
|
const float* sqr_tab;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct DTRowInvoker : ParallelLoopBody
|
struct DTRowInvoker : ParallelLoopBody
|
||||||
{
|
{
|
||||||
DTRowInvoker( Mat* _dst, const float* _sqr_tab, const float* _inv_tab )
|
DTRowInvoker( Mat* _dst, const float* _sqr_tab, const float* _inv_tab )
|
||||||
@ -669,7 +668,8 @@ distanceATS_L1_8u( const Mat& src, Mat& dst )
|
|||||||
{
|
{
|
||||||
int b = dbase[x+dststep];
|
int b = dbase[x+dststep];
|
||||||
a = lut[MIN(a, b)];
|
a = lut[MIN(a, b)];
|
||||||
dbase[x] = (uchar)(MIN(a, dbase[x]));
|
a = MIN(a, dbase[x]);
|
||||||
|
dbase[x] = (uchar)(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -677,23 +677,40 @@ distanceATS_L1_8u( const Mat& src, Mat& dst )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace cv
|
||||||
|
{
|
||||||
|
static void distanceTransform_L1_8U(InputArray _src, OutputArray _dst)
|
||||||
|
{
|
||||||
|
Mat src = _src.getMat();
|
||||||
|
|
||||||
|
CV_Assert( src.type() == CV_8UC1);
|
||||||
|
|
||||||
|
_dst.create( src.size(), CV_8UC1);
|
||||||
|
Mat dst = _dst.getMat();
|
||||||
|
|
||||||
|
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) && !defined HAVE_IPP_ICV_ONLY
|
||||||
|
IppiSize roi = { src.cols, src.rows };
|
||||||
|
Ipp32s pMetrics[2] = { 1, 2 }; //L1, 3x3 mask
|
||||||
|
if (ippiDistanceTransform_3x3_8u_C1R(src.ptr<uchar>(), (int)src.step, dst.ptr<uchar>(), (int)dst.step, roi, pMetrics)>=0)
|
||||||
|
return;
|
||||||
|
setIppErrorStatus();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
distanceATS_L1_8u(src, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Wrapper function for distance transform group
|
// Wrapper function for distance transform group
|
||||||
void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labels,
|
void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labels,
|
||||||
int distType, int maskSize, int labelType )
|
int distType, int maskSize, int labelType )
|
||||||
{
|
{
|
||||||
Mat src = _src.getMat(), dst = _dst.getMat(), labels;
|
Mat src = _src.getMat(), labels;
|
||||||
bool need_labels = _labels.needed();
|
bool need_labels = _labels.needed();
|
||||||
|
|
||||||
CV_Assert( src.type() == CV_8U );
|
CV_Assert( src.type() == CV_8UC1);
|
||||||
if( dst.size == src.size && dst.type() == CV_8U && !need_labels && distType == CV_DIST_L1 )
|
|
||||||
{
|
|
||||||
distanceATS_L1_8u(src, dst);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_dst.create( src.size(), CV_32F );
|
_dst.create( src.size(), CV_32F);
|
||||||
dst = _dst.getMat();
|
Mat dst = _dst.getMat();
|
||||||
|
|
||||||
if( need_labels )
|
if( need_labels )
|
||||||
{
|
{
|
||||||
@ -704,7 +721,6 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
|
|||||||
maskSize = CV_DIST_MASK_5;
|
maskSize = CV_DIST_MASK_5;
|
||||||
}
|
}
|
||||||
|
|
||||||
CV_Assert( src.type() == CV_8UC1 );
|
|
||||||
float _mask[5] = {0};
|
float _mask[5] = {0};
|
||||||
|
|
||||||
if( maskSize != CV_DIST_MASK_3 && maskSize != CV_DIST_MASK_5 && maskSize != CV_DIST_MASK_PRECISE )
|
if( maskSize != CV_DIST_MASK_3 && maskSize != CV_DIST_MASK_5 && maskSize != CV_DIST_MASK_PRECISE )
|
||||||
@ -717,6 +733,28 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
|
|||||||
|
|
||||||
if( maskSize == CV_DIST_MASK_PRECISE )
|
if( maskSize == CV_DIST_MASK_PRECISE )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||||
|
if ((currentParallelFramework()==NULL) || (src.total()<(int)(1<<14)))
|
||||||
|
{
|
||||||
|
IppStatus status;
|
||||||
|
IppiSize roi = { src.cols, src.rows };
|
||||||
|
Ipp8u *pBuffer;
|
||||||
|
int bufSize=0;
|
||||||
|
|
||||||
|
status = ippiTrueDistanceTransformGetBufferSize_8u32f_C1R(roi, &bufSize);
|
||||||
|
if (status>=0)
|
||||||
|
{
|
||||||
|
pBuffer = ippsMalloc_8u( bufSize );
|
||||||
|
status = ippiTrueDistanceTransform_8u32f_C1R(src.ptr<uchar>(),(int)src.step, dst.ptr<float>(), (int)dst.step, roi, pBuffer);
|
||||||
|
ippsFree( pBuffer );
|
||||||
|
if (status>=0)
|
||||||
|
return;
|
||||||
|
setIppErrorStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
trueDistTrans( src, dst );
|
trueDistTrans( src, dst );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -734,9 +772,27 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
|
|||||||
if( !need_labels )
|
if( !need_labels )
|
||||||
{
|
{
|
||||||
if( maskSize == CV_DIST_MASK_3 )
|
if( maskSize == CV_DIST_MASK_3 )
|
||||||
|
{
|
||||||
|
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) && !defined HAVE_IPP_ICV_ONLY
|
||||||
|
IppiSize roi = { src.cols, src.rows };
|
||||||
|
if (ippiDistanceTransform_3x3_8u32f_C1R(src.ptr<uchar>(), (int)src.step, dst.ptr<float>(), (int)dst.step, roi, _mask)>=0)
|
||||||
|
return;
|
||||||
|
setIppErrorStatus();
|
||||||
|
#endif
|
||||||
|
|
||||||
distanceTransform_3x3(src, temp, dst, _mask);
|
distanceTransform_3x3(src, temp, dst, _mask);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||||
|
IppiSize roi = { src.cols, src.rows };
|
||||||
|
if (ippiDistanceTransform_5x5_8u32f_C1R(src.ptr<uchar>(), (int)src.step, dst.ptr<float>(), (int)dst.step, roi, _mask)>=0)
|
||||||
|
return;
|
||||||
|
setIppErrorStatus();
|
||||||
|
#endif
|
||||||
|
|
||||||
distanceTransform_5x5(src, temp, dst, _mask);
|
distanceTransform_5x5(src, temp, dst, _mask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -744,17 +800,6 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
|
|||||||
|
|
||||||
if( labelType == CV_DIST_LABEL_CCOMP )
|
if( labelType == CV_DIST_LABEL_CCOMP )
|
||||||
{
|
{
|
||||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
|
||||||
if( maskSize == CV_DIST_MASK_5 )
|
|
||||||
{
|
|
||||||
IppiSize roi = { src.cols, src.rows };
|
|
||||||
if( ippiDistanceTransform_5x5_8u32f_C1R(
|
|
||||||
src.ptr<uchar>(), (int)src.step,
|
|
||||||
dst.ptr<float>(), (int)dst.step, roi, _mask) >= 0 )
|
|
||||||
return;
|
|
||||||
setIppErrorStatus();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
Mat zpix = src == 0;
|
Mat zpix = src == 0;
|
||||||
connectedComponents(zpix, labels, 8, CV_32S);
|
connectedComponents(zpix, labels, 8, CV_32S);
|
||||||
}
|
}
|
||||||
@ -772,17 +817,19 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
distanceTransformEx_5x5( src, temp, dst, labels, _mask );
|
distanceTransformEx_5x5( src, temp, dst, labels, _mask );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void cv::distanceTransform( InputArray _src, OutputArray _dst,
|
void cv::distanceTransform( InputArray _src, OutputArray _dst,
|
||||||
int distanceType, int maskSize )
|
int distanceType, int maskSize, int dstType)
|
||||||
{
|
{
|
||||||
distanceTransform(_src, _dst, noArray(), distanceType, maskSize, DIST_LABEL_PIXEL);
|
if (distanceType == CV_DIST_L1 && dstType==CV_8U)
|
||||||
}
|
distanceTransform_L1_8U(_src, _dst);
|
||||||
|
else
|
||||||
|
distanceTransform(_src, _dst, noArray(), distanceType, maskSize, DIST_LABEL_PIXEL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
CV_IMPL void
|
CV_IMPL void
|
||||||
cvDistTransform( const void* srcarr, void* dstarr,
|
cvDistTransform( const void* srcarr, void* dstarr,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user