}
}
+#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY
+
+class IPPCalcHistInvoker :
+ public ParallelLoopBody
+{
+public:
+ IPPCalcHistInvoker(const Mat & _src, Mat & _hist, AutoBuffer<Ipp32s> & _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<Ipp32s> * levels;
+ Ipp32s histSize, low, high;
+ bool * ok;
+
+ const IPPCalcHistInvoker & operator = (const IPPCalcHistInvoker & );
+};
+
+#endif
+
}
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;
-#ifdef HAVE_IPP
+#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)
{
- hist.setTo(Scalar::all(0));
+ ihist.setTo(Scalar::all(0));
AutoBuffer<Ipp32s> levels(histSize[0] + 1);
- IppStatus status =
- ippiHistogramEven_8u_C1R(
- (const Ipp8u *)images[0].data, (int)images[0].step, ippiSize(images[0].size()),
- (Ipp32s *)ihist.data, (Ipp32s *)levels, histSize[0] + 1, (Ipp32s)ranges[0][0], (Ipp32s)ranges[0][1]);
- if (status >= 0)
+ bool ok = true;
+ const Mat & src = images[0];
+ int nstripes = std::min<int>(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;