diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index dc8d601903..22b65fa53b 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -168,7 +168,7 @@ inline Mat::Mat(Size _sz, int _type, void* _data, size_t _step) dataend = datalimit - _step + minstep; } - + inline Mat::Mat(const CvMat* m, bool copyData) : flags(MAGIC_VAL + (m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG))), dims(2), rows(m->rows), cols(m->cols), data(m->data.ptr), refcount(0), diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index 29e29fa532..bf6dde9f9f 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -268,6 +268,16 @@ typedef NoVec VXor8u; #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +struct IPPArithmInitializer +{ + IPPArithmInitializer(void) + { + IppStatus status = ippStaticInit(); + } +}; + +IPPArithmInitializer ippArithmInitializer; + struct ippAdd8u { int operator()(const Ipp8u* src1, const Ipp8u* src2, Ipp8u* dst, int len) const diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index cbfbd9709b..3f5bfbbc90 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -40,7 +40,9 @@ //M*/ #include "precomp.hpp" - +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +static IppStatus sts = ippInit(); +#endif /****************************************************************************************/ /* lightweight convolution with 3x3 kernel */ @@ -237,9 +239,245 @@ Ptr createDerivFilter(int srcType, int dstType, } +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + +static bool IPPDerivScharr(const Mat& src, Mat& dst, int ddepth, int dx, int dy, double scale) +{ + int bufSize = 0; + cv::AutoBuffer buffer; + IppiSize roi = ippiSize(src.cols, src.rows); + + if( ddepth < 0 ) + ddepth = src.depth(); + + dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); + + switch(src.type()) + { + case CV_8U: + { + if(scale != 1) + return false; + + switch(dst.type()) + { + case CV_16S: + { + if((dx == 1) && (dy == 0)) + { + ippiFilterScharrVertGetBufferSize_8u16s_C1R(roi,&bufSize); + buffer.allocate(bufSize); + + ippiFilterScharrVertBorder_8u16s_C1R((const Ipp8u*)src.data, src.step, + (Ipp16s*)dst.data, dst.step, roi, ippBorderRepl, 0, (Ipp8u*)(char*)buffer); + + return true; + } + + if((dx == 0) && (dy == 1)) + { + ippiFilterScharrHorizGetBufferSize_8u16s_C1R(roi,&bufSize); + buffer.allocate(bufSize); + + ippiFilterScharrHorizBorder_8u16s_C1R((const Ipp8u*)src.data, src.step, + (Ipp16s*)dst.data, dst.step, roi, ippBorderRepl, 0, (Ipp8u*)(char*)buffer); + + return true; + } + } + + default: + return false; + } + } + + case CV_32F: + { + switch(dst.type()) + { + case CV_32F: + if((dx == 1) && (dy == 0)) + { + ippiFilterScharrVertGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows),&bufSize); + buffer.allocate(bufSize); + + ippiFilterScharrVertBorder_32f_C1R((const Ipp32f*)src.data, src.step, + (Ipp32f*)dst.data, dst.step, ippiSize(src.cols, src.rows), + ippBorderRepl, 0, (Ipp8u*)(char*)buffer); + if(scale != 1) + /* IPP is fast, so MulC produce very little perf degradation */ + ippiMulC_32f_C1IR((Ipp32f)scale,(Ipp32f*)dst.data,dst.step,ippiSize(dst.cols*dst.channels(),dst.rows)); + + return true; + } + + if((dx == 0) && (dy == 1)) + { + ippiFilterScharrHorizGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows),&bufSize); + buffer.allocate(bufSize); + + ippiFilterScharrHorizBorder_32f_C1R((const Ipp32f*)src.data, src.step, + (Ipp32f*)dst.data, dst.step, ippiSize(src.cols, src.rows), + ippBorderRepl, 0, (Ipp8u*)(char*)buffer); + if(scale != 1) + ippiMulC_32f_C1IR((Ipp32f)scale,(Ipp32f *)dst.data,dst.step,ippiSize(dst.cols*dst.channels(),dst.rows)); + + return true; + } + + default: + return false; + } + } + + default: + return false; + } +} + + +static bool IPPDeriv(const Mat& src, Mat& dst, int ddepth, int dx, int dy, int ksize, double scale) +{ + int bufSize = 0; + cv::AutoBuffer buffer; + + if(ksize == 3 || ksize == 5) + { + if( ddepth < 0 ) + ddepth = src.depth(); + + dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); + + if(src.type() == CV_8U && dst.type() == CV_16S && scale == 1) + { + if((dx == 1) && (dy == 0)) + { + ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); + buffer.allocate(bufSize); + + ippiFilterSobelNegVertBorder_8u16s_C1R((const Ipp8u*)src.data, src.step, + (Ipp16s*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + ippBorderRepl, 0, (Ipp8u*)(char*)buffer); + return true; + } + + if((dx == 0) && (dy == 1)) + { + ippiFilterSobelHorizGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); + buffer.allocate(bufSize); + + ippiFilterSobelHorizBorder_8u16s_C1R((const Ipp8u*)src.data, src.step, + (Ipp16s*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + ippBorderRepl, 0, (Ipp8u*)(char*)buffer); + + return true; + } + + if((dx == 2) && (dy == 0)) + { + ippiFilterSobelVertSecondGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); + buffer.allocate(bufSize); + + ippiFilterSobelVertSecondBorder_8u16s_C1R((const Ipp8u*)src.data, src.step, + (Ipp16s*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + ippBorderRepl, 0, (Ipp8u*)(char*)buffer); + + return true; + } + + if((dx == 0) && (dy == 2)) + { + ippiFilterSobelHorizSecondGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); + buffer.allocate(bufSize); + + ippiFilterSobelHorizSecondBorder_8u16s_C1R((const Ipp8u*)src.data, src.step, + (Ipp16s*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + ippBorderRepl, 0, (Ipp8u*)(char*)buffer); + + return true; + } + } + + if(src.type() == CV_32F && dst.type() == CV_32F) + { + if((dx == 1) && (dy == 0)) + { + ippiFilterSobelNegVertGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); + buffer.allocate(bufSize); + + ippiFilterSobelNegVertBorder_32f_C1R((const Ipp32f*)src.data, src.step, + (Ipp32f*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + ippBorderRepl, 0, (Ipp8u*)(char*)buffer); + if(scale != 1) + ippiMulC_32f_C1IR((Ipp32f)scale,(Ipp32f *)dst.data,dst.step,ippiSize(dst.cols*dst.channels(),dst.rows)); + + return true; + } + + if((dx == 0) && (dy == 1)) + { + ippiFilterSobelHorizGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); + buffer.allocate(bufSize); + + ippiFilterSobelHorizBorder_32f_C1R((const Ipp32f*)src.data, src.step, + (Ipp32f*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + ippBorderRepl, 0, (Ipp8u*)(char*)buffer); + if(scale != 1) + ippiMulC_32f_C1IR((Ipp32f)scale,(Ipp32f *)dst.data,dst.step,ippiSize(dst.cols*dst.channels(),dst.rows)); + + return true; + } + + if((dx == 2) && (dy == 0)) + { + ippiFilterSobelVertSecondGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); + buffer.allocate(bufSize); + + ippiFilterSobelVertSecondBorder_32f_C1R((const Ipp32f*)src.data, src.step, + (Ipp32f*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + ippBorderRepl, 0, (Ipp8u*)(char*)buffer); + if(scale != 1) + ippiMulC_32f_C1IR((Ipp32f)scale,(Ipp32f *)dst.data,dst.step,ippiSize(dst.cols*dst.channels(),dst.rows)); + + return true; + } + + if((dx == 0) && (dy == 2)) + { + ippiFilterSobelHorizSecondGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); + buffer.allocate(bufSize); + + ippiFilterSobelHorizSecondBorder_32f_C1R((const Ipp32f*)src.data, src.step, + (Ipp32f*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + ippBorderRepl, 0, (Ipp8u*)(char*)buffer); + if(scale != 1) + ippiMulC_32f_C1IR((Ipp32f)scale,(Ipp32f *)dst.data,dst.step,ippiSize(dst.cols*dst.channels(),dst.rows)); + + return true; + } + } + } + + if(ksize <= 0) + return IPPDerivScharr(src, dst, ddepth, dx, dy, scale); + + return false; + +} + +#endif + + void Sobel( const Mat& src, Mat& dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType ) { +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + if(dx < 3 && dy < 3 && src.channels() == 1 && borderType == 1) + { + if(IPPDeriv(src, dst, ddepth, dx, dy, ksize,scale) == true) + return; + } +#endif int ktype = std::max(CV_32F, std::max(ddepth, src.depth())); Mat kx, ky; @@ -260,6 +498,13 @@ void Sobel( const Mat& src, Mat& dst, int ddepth, int dx, int dy, void Scharr( const Mat& src, Mat& dst, int ddepth, int dx, int dy, double scale, double delta, int borderType ) { +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + if(dx < 2 && dy < 2 && src.channels() == 1 && borderType == 1) + { + if(IPPDerivScharr(src, dst, ddepth, dx, dy, scale) == true) + return; + } +#endif int ktype = std::max(CV_32F, std::max(ddepth, src.depth())); Mat kx, ky;