diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 09f790182d..29eb938bff 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -2241,6 +2241,53 @@ static bool openvx_gaussianBlur(InputArray _src, OutputArray _dst, Size ksize, #endif #ifdef HAVE_IPP +#define IPP_GAUSSIANBLUR_PARALLEL 1 + +#ifdef HAVE_IPP_IW + +class ipp_gaussianBlurParallel: public ParallelLoopBody +{ +public: + ipp_gaussianBlurParallel(::ipp::IwiImage &src, ::ipp::IwiImage &dst, int kernelSize, float sigma, ::ipp::IwiBorderType &border, bool *pOk): + m_src(src), m_dst(dst), m_kernelSize(kernelSize), m_sigma(sigma), m_border(border), m_pOk(pOk) { + *m_pOk = true; + } + ~ipp_gaussianBlurParallel() + { + } + + virtual void operator() (const Range& range) const + { + CV_INSTRUMENT_REGION_IPP() + + if(!*m_pOk) + return; + + try + { + ::ipp::IwiRoi roi = ::ipp::IwiRect(0, range.start, m_dst.m_size.width, range.end - range.start); + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterGaussian, &m_src, &m_dst, m_kernelSize, m_sigma, m_border, &roi); + } + catch(::ipp::IwException e) + { + *m_pOk = false; + return; + } + } +private: + ::ipp::IwiImage &m_src; + ::ipp::IwiImage &m_dst; + + int m_kernelSize; + float m_sigma; + ::ipp::IwiBorderType &m_border; + + volatile bool *m_pOk; + const ipp_gaussianBlurParallel& operator= (const ipp_gaussianBlurParallel&); +}; + +#endif + static bool ipp_GaussianBlur(InputArray _src, OutputArray _dst, Size ksize, double sigma1, double sigma2, int borderType ) { @@ -2272,7 +2319,26 @@ static bool ipp_GaussianBlur(InputArray _src, OutputArray _dst, Size ksize, if(!ippBorder.m_borderType) return false; - CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterGaussian, &iwSrc, &iwDst, ksize.width, (float)sigma1, ippBorder); + // IW 2017u2 has bug which doesn't allow use of partial inMem with tiling + if((((ippBorder.m_borderFlags)&ippBorderInMem) && ((ippBorder.m_borderFlags)&ippBorderInMem) != ippBorderInMem)) { + return false; + } + + bool ok; + ipp_gaussianBlurParallel invoker(iwSrc, iwDst, ksize.width, (float) sigma1, ippBorder, &ok); + + if(!ok) + return false; + + const Range range(0, (int) iwDst.m_size.height); + const int threads = ippiSuggestThreadsNum(iwDst, 2); + if(IPP_GAUSSIANBLUR_PARALLEL && threads > 1) + parallel_for_(range, invoker, threads*4); + else + invoker(range); + + if(!ok) + return false; } catch (::ipp::IwException ex) {