Commit cd01d705 authored by Andrey Pavlenko's avatar Andrey Pavlenko Committed by OpenCV Buildbot

Merge pull request #2627 from akarsakov:ipp_pyramids

parents 580559e1 4f4a9529
......@@ -8,12 +8,14 @@ using std::tr1::get;
PERF_TEST_P(Size_MatType, pyrDown, testing::Combine(
testing::Values(sz1080p, sz720p, szVGA, szQVGA, szODD),
testing::Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_16SC1, CV_16SC3, CV_16SC4)
testing::Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_16SC1, CV_16SC3, CV_16SC4, CV_32FC1, CV_32FC3, CV_32FC4)
)
)
{
Size sz = get<0>(GetParam());
int matType = get<1>(GetParam());
const double eps = CV_MAT_DEPTH(matType) <= CV_32S ? 1 : 1e-5;
perf::ERROR_TYPE error_type = CV_MAT_DEPTH(matType) <= CV_32S ? ERROR_ABSOLUTE : ERROR_RELATIVE;
Mat src(sz, matType);
Mat dst((sz.height + 1)/2, (sz.width + 1)/2, matType);
......@@ -22,17 +24,19 @@ PERF_TEST_P(Size_MatType, pyrDown, testing::Combine(
TEST_CYCLE() pyrDown(src, dst);
SANITY_CHECK(dst);
SANITY_CHECK(dst, eps, error_type);
}
PERF_TEST_P(Size_MatType, pyrUp, testing::Combine(
testing::Values(sz720p, szVGA, szQVGA, szODD),
testing::Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_16SC1, CV_16SC3, CV_16SC4)
testing::Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_16SC1, CV_16SC3, CV_16SC4, CV_32FC1, CV_32FC3, CV_32FC4)
)
)
{
Size sz = get<0>(GetParam());
int matType = get<1>(GetParam());
const double eps = CV_MAT_DEPTH(matType) <= CV_32S ? 1 : 1e-5;
perf::ERROR_TYPE error_type = CV_MAT_DEPTH(matType) <= CV_32S ? ERROR_ABSOLUTE : ERROR_RELATIVE;
Mat src(sz, matType);
Mat dst(sz.height*2, sz.width*2, matType);
......@@ -41,5 +45,32 @@ PERF_TEST_P(Size_MatType, pyrUp, testing::Combine(
TEST_CYCLE() pyrUp(src, dst);
SANITY_CHECK(dst);
SANITY_CHECK(dst, eps, error_type);
}
PERF_TEST_P(Size_MatType, buildPyramid, testing::Combine(
testing::Values(sz1080p, sz720p, szVGA, szQVGA, szODD),
testing::Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4)
)
)
{
Size sz = get<0>(GetParam());
int matType = get<1>(GetParam());
int maxLevel = 5;
const double eps = CV_MAT_DEPTH(matType) <= CV_32S ? 1 : 1e-5;
perf::ERROR_TYPE error_type = CV_MAT_DEPTH(matType) <= CV_32S ? ERROR_ABSOLUTE : ERROR_RELATIVE;
Mat src(sz, matType);
std::vector<Mat> dst(maxLevel);
declare.in(src, WARMUP_RNG);
TEST_CYCLE() buildPyramid(src, dst, maxLevel);
Mat dst0 = dst[0], dst1 = dst[1], dst2 = dst[2], dst3 = dst[3], dst4 = dst[4];
SANITY_CHECK(dst0, eps, error_type);
SANITY_CHECK(dst1, eps, error_type);
SANITY_CHECK(dst2, eps, error_type);
SANITY_CHECK(dst3, eps, error_type);
SANITY_CHECK(dst4, eps, error_type);
}
......@@ -501,13 +501,49 @@ void cv::pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borde
Size dsz = _dsz.area() == 0 ? Size((src.cols + 1)/2, (src.rows + 1)/2) : _dsz;
_dst.create( dsz, src.type() );
Mat dst = _dst.getMat();
int depth = src.depth();
#ifdef HAVE_TEGRA_OPTIMIZATION
if(borderType == BORDER_DEFAULT && tegra::pyrDown(src, dst))
return;
#endif
int depth = src.depth();
#if (defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 801)
bool isolated = (borderType & BORDER_ISOLATED) != 0;
int borderTypeNI = borderType & ~BORDER_ISOLATED;
if (borderTypeNI == BORDER_DEFAULT && (!src.isSubmatrix() || isolated))
{
typedef IppStatus (CV_STDCALL * ippiPyrDown)(const void* pSrc, int srcStep, void* pDst, int dstStep, IppiSize srcRoi, Ipp8u* buffer);
int type = src.type();
CV_SUPPRESS_DEPRECATED_START
ippiPyrDown pyrDownFunc = type == CV_8UC1 ? (ippiPyrDown) ippiPyrDown_Gauss5x5_8u_C1R :
type == CV_8UC3 ? (ippiPyrDown) ippiPyrDown_Gauss5x5_8u_C3R :
type == CV_32FC1 ? (ippiPyrDown) ippiPyrDown_Gauss5x5_32f_C1R :
type == CV_32FC3 ? (ippiPyrDown) ippiPyrDown_Gauss5x5_32f_C3R : 0;
CV_SUPPRESS_DEPRECATED_END
if (pyrDownFunc)
{
int bufferSize;
IppiSize srcRoi = { src.cols, src.rows };
IppDataType dataType = depth == CV_8U ? ipp8u : ipp32f;
CV_SUPPRESS_DEPRECATED_START
IppStatus ok = ippiPyrDownGetBufSize_Gauss5x5(srcRoi.width, dataType, src.channels(), &bufferSize);
CV_SUPPRESS_DEPRECATED_END
if (ok >= 0)
{
Ipp8u* buffer = ippsMalloc_8u(bufferSize);
ok = pyrDownFunc(src.data, (int) src.step, dst.data, (int) dst.step, srcRoi, buffer);
ippsFree(buffer);
if (ok >= 0)
return;
setIppErrorStatus();
}
}
}
#endif
PyrFunc func = 0;
if( depth == CV_8U )
func = pyrDown_<FixPtCast<uchar, 8>, PyrDownVec_32s8u>;
......@@ -534,13 +570,49 @@ void cv::pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int borderT
Size dsz = _dsz.area() == 0 ? Size(src.cols*2, src.rows*2) : _dsz;
_dst.create( dsz, src.type() );
Mat dst = _dst.getMat();
int depth = src.depth();
#ifdef HAVE_TEGRA_OPTIMIZATION
if(borderType == BORDER_DEFAULT && tegra::pyrUp(src, dst))
return;
#endif
int depth = src.depth();
#if (defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 801)
bool isolated = (borderType & BORDER_ISOLATED) != 0;
int borderTypeNI = borderType & ~BORDER_ISOLATED;
if (borderTypeNI == BORDER_DEFAULT && (!src.isSubmatrix() || isolated))
{
typedef IppStatus (CV_STDCALL * ippiPyrUp)(const void* pSrc, int srcStep, void* pDst, int dstStep, IppiSize srcRoi, Ipp8u* buffer);
int type = src.type();
CV_SUPPRESS_DEPRECATED_START
ippiPyrUp pyrUpFunc = type == CV_8UC1 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_8u_C1R :
type == CV_8UC3 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_8u_C3R :
type == CV_32FC1 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_32f_C1R :
type == CV_32FC3 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_32f_C3R : 0;
CV_SUPPRESS_DEPRECATED_END
if (pyrUpFunc)
{
int bufferSize;
IppiSize srcRoi = { src.cols, src.rows };
IppDataType dataType = depth == CV_8U ? ipp8u : ipp32f;
CV_SUPPRESS_DEPRECATED_START
IppStatus ok = ippiPyrUpGetBufSize_Gauss5x5(srcRoi.width, dataType, src.channels(), &bufferSize);
CV_SUPPRESS_DEPRECATED_END
if (ok >= 0)
{
Ipp8u* buffer = ippsMalloc_8u(bufferSize);
ok = pyrUpFunc(src.data, (int) src.step, dst.data, (int) dst.step, srcRoi, buffer);
ippsFree(buffer);
if (ok >= 0)
return;
setIppErrorStatus();
}
}
}
#endif
PyrFunc func = 0;
if( depth == CV_8U )
func = pyrUp_<FixPtCast<uchar, 6>, NoVec<int, uchar> >;
......@@ -573,7 +645,92 @@ void cv::buildPyramid( InputArray _src, OutputArrayOfArrays _dst, int maxlevel,
Mat src = _src.getMat();
_dst.create( maxlevel + 1, 1, 0 );
_dst.getMatRef(0) = src;
for( int i = 1; i <= maxlevel; i++ )
int i=1;
#if (defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 801)
bool isolated = (borderType & BORDER_ISOLATED) != 0;
int borderTypeNI = borderType & ~BORDER_ISOLATED;
if (borderTypeNI == BORDER_DEFAULT && (!src.isSubmatrix() || isolated))
{
typedef IppStatus (CV_STDCALL * ippiPyramidLayerDownInitAlloc)(void** ppState, IppiSize srcRoi, Ipp32f rate, void* pKernel, int kerSize, int mode);
typedef IppStatus (CV_STDCALL * ippiPyramidLayerDown)(void* pSrc, int srcStep, IppiSize srcRoiSize, void* pDst, int dstStep, IppiSize dstRoiSize, void* pState);
typedef IppStatus (CV_STDCALL * ippiPyramidLayerDownFree)(void* pState);
int type = src.type();
int depth = src.depth();
ippiPyramidLayerDownInitAlloc pyrInitAllocFunc = 0;
ippiPyramidLayerDown pyrDownFunc = 0;
ippiPyramidLayerDownFree pyrFreeFunc = 0;
if (type == CV_8UC1)
{
pyrInitAllocFunc = (ippiPyramidLayerDownInitAlloc) ippiPyramidLayerDownInitAlloc_8u_C1R;
pyrDownFunc = (ippiPyramidLayerDown) ippiPyramidLayerDown_8u_C1R;
pyrFreeFunc = (ippiPyramidLayerDownFree) ippiPyramidLayerDownFree_8u_C1R;
} else if (type == CV_8UC3)
{
pyrInitAllocFunc = (ippiPyramidLayerDownInitAlloc) ippiPyramidLayerDownInitAlloc_8u_C3R;
pyrDownFunc = (ippiPyramidLayerDown) ippiPyramidLayerDown_8u_C3R;
pyrFreeFunc = (ippiPyramidLayerDownFree) ippiPyramidLayerDownFree_8u_C3R;
} else if (type == CV_32FC1)
{
pyrInitAllocFunc = (ippiPyramidLayerDownInitAlloc) ippiPyramidLayerDownInitAlloc_32f_C1R;
pyrDownFunc = (ippiPyramidLayerDown) ippiPyramidLayerDown_32f_C1R;
pyrFreeFunc = (ippiPyramidLayerDownFree) ippiPyramidLayerDownFree_32f_C1R;
} else if (type == CV_32FC3)
{
pyrInitAllocFunc = (ippiPyramidLayerDownInitAlloc) ippiPyramidLayerDownInitAlloc_32f_C3R;
pyrDownFunc = (ippiPyramidLayerDown) ippiPyramidLayerDown_32f_C3R;
pyrFreeFunc = (ippiPyramidLayerDownFree) ippiPyramidLayerDownFree_32f_C3R;
}
if (pyrInitAllocFunc && pyrDownFunc && pyrFreeFunc)
{
float rate = 2.f;
IppiSize srcRoi = { src.cols, src.rows };
IppiPyramid *gPyr;
IppStatus ok = ippiPyramidInitAlloc(&gPyr, maxlevel + 1, srcRoi, rate);
Ipp16s iKernel[5] = { 1, 4, 6, 4, 1 };
Ipp32f fKernel[5] = { 1.f, 4.f, 6.f, 4.f, 1.f };
void* kernel = depth >= CV_32F ? (void*) fKernel : (void*) iKernel;
if (ok >= 0) ok = pyrInitAllocFunc((void**) &(gPyr->pState), srcRoi, rate, kernel, 5, IPPI_INTER_LINEAR);
if (ok >= 0)
{
gPyr->pImage[0] = src.data;
gPyr->pStep[0] = (int) src.step;
gPyr->pRoi[0] = srcRoi;
for( ; i <= maxlevel; i++ )
{
IppiSize dstRoi;
ok = ippiGetPyramidDownROI(gPyr->pRoi[i-1], &dstRoi, rate);
Mat& dst = _dst.getMatRef(i);
dst.create(Size(dstRoi.width, dstRoi.height), type);
gPyr->pImage[i] = dst.data;
gPyr->pStep[i] = (int) dst.step;
gPyr->pRoi[i] = dstRoi;
if (ok >= 0) ok = pyrDownFunc(gPyr->pImage[i-1], gPyr->pStep[i-1], gPyr->pRoi[i-1],
gPyr->pImage[i], gPyr->pStep[i], gPyr->pRoi[i], gPyr->pState);
if (ok < 0)
{
setIppErrorStatus();
break;
}
}
pyrFreeFunc(gPyr->pState);
} else
{
setIppErrorStatus();
}
ippiPyramidFree(gPyr);
}
}
#endif
for( ; i <= maxlevel; i++ )
pyrDown( _dst.getMatRef(i-1), _dst.getMatRef(i), Size(), borderType );
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment