diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 04dc7e2824e0d4820b469cde96e9a9a4f524ad61..8e8484d6b7176ac0d1a56a301a40782353e4bb3e 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -1175,6 +1175,48 @@ calcHist_8u( std::vector& _ptrs, const std::vector& _deltas, } } +#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY + +class IPPCalcHistInvoker : + public ParallelLoopBody +{ +public: + IPPCalcHistInvoker(const Mat & _src, Mat & _hist, AutoBuffer & _levels, Ipp32s _histSize, Ipp32s _low, Ipp32s _high, bool * _ok) : + ParallelLoopBody(), src(&_src), hist(&_hist), levels(&_levels), histSize(_histSize), low(_low), high(_high), ok(_ok) + { + *ok = true; + } + + virtual void operator() (const Range & range) const + { + Mat phist(hist->size(), hist->type(), Scalar::all(0)); + + IppStatus status = ippiHistogramEven_8u_C1R( + src->data + src->step * range.start, (int)src->step, ippiSize(src->cols, range.end - range.start), + (Ipp32s *)phist.data, (Ipp32s *)*levels, histSize, low, high); + + if (status < 0) + { + *ok = false; + return; + } + + for (int i = 0; i < histSize; ++i) + CV_XADD((int *)(hist->data + i * hist->step), *(int *)(phist.data + i * phist.step)); + } + +private: + const Mat * src; + Mat * hist; + AutoBuffer * levels; + Ipp32s histSize, low, high; + bool * ok; + + const IPPCalcHistInvoker & operator = (const IPPCalcHistInvoker & ); +}; + +#endif + } void cv::calcHist( const Mat* images, int nimages, const int* channels, @@ -1190,6 +1232,32 @@ void cv::calcHist( const Mat* images, int nimages, const int* channels, Mat hist = _hist.getMat(), ihist = hist; ihist.flags = (ihist.flags & ~CV_MAT_TYPE_MASK)|CV_32S; +#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY + if (nimages == 1 && images[0].type() == CV_8UC1 && dims == 1 && channels && + channels[0] == 0 && mask.empty() && images[0].dims <= 2 && + !accumulate && uniform) + { + ihist.setTo(Scalar::all(0)); + AutoBuffer levels(histSize[0] + 1); + + bool ok = true; + const Mat & src = images[0]; + int nstripes = std::min(8, src.total() / (1 << 16)); +#ifdef HAVE_CONCURRENCY + nstripes = 1; +#endif + IPPCalcHistInvoker invoker(src, ihist, levels, histSize[0] + 1, (Ipp32s)ranges[0][0], (Ipp32s)ranges[0][1], &ok); + Range range(0, src.rows); + parallel_for_(range, invoker, nstripes); + + if (ok) + { + ihist.convertTo(hist, CV_32F); + return; + } + } +#endif + if( !accumulate || histdata != hist.data ) hist = Scalar(0.); else @@ -1477,7 +1545,7 @@ void cv::calcHist( InputArrayOfArrays images, const std::vector& channels, CV_OCL_RUN(images.total() == 1 && channels.size() == 1 && images.channels(0) == 1 && channels[0] == 0 && images.isUMatVector() && mask.empty() && !accumulate && histSize.size() == 1 && histSize[0] == BINS && ranges.size() == 2 && - ranges[0] == 0 && ranges[1] == 256, + ranges[0] == 0 && ranges[1] == BINS, ocl_calcHist(images, hist)) int i, dims = (int)histSize.size(), rsz = (int)ranges.size(), csz = (int)channels.size();