mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 07:43:03 +04:00
IPP for OpenCV 2017u2 initial enabling patch;
This commit is contained in:
+170
-105
@@ -1178,86 +1178,150 @@ calcHist_8u( std::vector<uchar*>& _ptrs, const std::vector<int>& _deltas,
|
||||
}
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
class IPPCalcHistInvoker :
|
||||
public ParallelLoopBody
|
||||
|
||||
typedef IppStatus(CV_STDCALL * IppiHistogram_C1)(const void* pSrc, int srcStep,
|
||||
IppiSize roiSize, Ipp32u* pHist, const IppiHistogramSpec* pSpec, Ipp8u* pBuffer);
|
||||
|
||||
static IppiHistogram_C1 getIppiHistogramFunction_C1(int type)
|
||||
{
|
||||
IppiHistogram_C1 ippFunction =
|
||||
(type == CV_8UC1) ? (IppiHistogram_C1)ippiHistogram_8u_C1R :
|
||||
#if IPP_VERSION_X100 >= 201700 || !(defined HAVE_IPP_ICV_ONLY)
|
||||
(type == CV_16UC1) ? (IppiHistogram_C1)ippiHistogram_16u_C1R :
|
||||
(type == CV_32FC1) ? (IppiHistogram_C1)ippiHistogram_32f_C1R :
|
||||
#endif
|
||||
NULL;
|
||||
|
||||
return ippFunction;
|
||||
}
|
||||
|
||||
class ipp_calcHistParallelTLS
|
||||
{
|
||||
public:
|
||||
IPPCalcHistInvoker(const Mat & _src, Mat & _hist, AutoBuffer<Ipp32f> & _levels, Ipp32s _histSize, Ipp32f _low, Ipp32f _high, bool * _ok) :
|
||||
ParallelLoopBody(), src(&_src), hist(&_hist), levels(&_levels), histSize(_histSize), low(_low), high(_high), ok(_ok)
|
||||
ipp_calcHistParallelTLS() {}
|
||||
|
||||
IppAutoBuffer<IppiHistogramSpec> spec;
|
||||
IppAutoBuffer<Ipp8u> buffer;
|
||||
IppAutoBuffer<Ipp32u> thist;
|
||||
};
|
||||
|
||||
class ipp_calcHistParallel: public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
ipp_calcHistParallel(const Mat &src, Mat &hist, Ipp32s histSize, const float *ranges, bool uniform, bool &ok):
|
||||
ParallelLoopBody(), m_src(src), m_hist(hist), m_ok(ok)
|
||||
{
|
||||
*ok = true;
|
||||
ok = true;
|
||||
|
||||
m_uniform = uniform;
|
||||
m_ranges = ranges;
|
||||
m_histSize = histSize;
|
||||
m_type = ippiGetDataType(src.type());
|
||||
m_levelsNum = histSize+1;
|
||||
ippiHistogram_C1 = getIppiHistogramFunction_C1(src.type());
|
||||
if(!ippiHistogram_C1)
|
||||
{
|
||||
ok = false;
|
||||
return;
|
||||
}
|
||||
|
||||
m_fullRoi = ippiSize(src.size());
|
||||
m_bufferSize = 0;
|
||||
m_specSize = 0;
|
||||
|
||||
if(ippiHistogramGetBufferSize(m_type, m_fullRoi, &m_levelsNum, 1, 1, &m_specSize, &m_bufferSize) < 0)
|
||||
{
|
||||
ok = false;
|
||||
return;
|
||||
}
|
||||
|
||||
hist.setTo(0);
|
||||
}
|
||||
|
||||
virtual void operator() (const Range & range) const
|
||||
{
|
||||
Ipp32s levelNum = histSize + 1;
|
||||
Mat phist(hist->size(), hist->type(), Scalar::all(0));
|
||||
#if IPP_VERSION_X100 >= 900
|
||||
IppiSize roi = {src->cols, range.end - range.start};
|
||||
int bufferSize = 0;
|
||||
int specSize = 0;
|
||||
IppiHistogramSpec *pSpec = NULL;
|
||||
Ipp8u *pBuffer = NULL;
|
||||
CV_INSTRUMENT_REGION_IPP()
|
||||
|
||||
if(ippiHistogramGetBufferSize(ipp8u, roi, &levelNum, 1, 1, &specSize, &bufferSize) < 0)
|
||||
if(!m_ok)
|
||||
return;
|
||||
|
||||
ipp_calcHistParallelTLS *pTls = m_tls.get();
|
||||
|
||||
IppiSize roi = {m_src.cols, range.end - range.start };
|
||||
bool mtLoop = false;
|
||||
if(m_fullRoi.height != roi.height)
|
||||
mtLoop = true;
|
||||
|
||||
if(!pTls->spec)
|
||||
{
|
||||
*ok = false;
|
||||
pTls->spec.allocate(m_specSize);
|
||||
if(!pTls->spec.get())
|
||||
{
|
||||
m_ok = false;
|
||||
return;
|
||||
}
|
||||
|
||||
pTls->buffer.allocate(m_bufferSize);
|
||||
if(!pTls->buffer.get() && m_bufferSize)
|
||||
{
|
||||
m_ok = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_uniform)
|
||||
{
|
||||
if(ippiHistogramUniformInit(m_type, (Ipp32f*)&m_ranges[0], (Ipp32f*)&m_ranges[1], (Ipp32s*)&m_levelsNum, 1, pTls->spec) < 0)
|
||||
{
|
||||
m_ok = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ippiHistogramInit(m_type, (const Ipp32f**)&m_ranges, (Ipp32s*)&m_levelsNum, 1, pTls->spec) < 0)
|
||||
{
|
||||
m_ok = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pTls->thist.allocate(m_histSize*sizeof(Ipp32u));
|
||||
}
|
||||
|
||||
if(CV_INSTRUMENT_FUN_IPP(ippiHistogram_C1, m_src.ptr(range.start), (int)m_src.step, roi, pTls->thist, pTls->spec, pTls->buffer) < 0)
|
||||
{
|
||||
m_ok = false;
|
||||
return;
|
||||
}
|
||||
|
||||
pBuffer = (Ipp8u*)ippMalloc(bufferSize);
|
||||
if(!pBuffer && bufferSize)
|
||||
if(mtLoop)
|
||||
{
|
||||
*ok = false;
|
||||
return;
|
||||
for(int i = 0; i < m_histSize; i++)
|
||||
CV_XADD((int*)(m_hist.ptr(i)), *(int*)((Ipp32u*)pTls->thist + i));
|
||||
}
|
||||
|
||||
pSpec = (IppiHistogramSpec*)ippMalloc(specSize);
|
||||
if(!pSpec && specSize)
|
||||
{
|
||||
if(pBuffer) ippFree(pBuffer);
|
||||
*ok = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if(ippiHistogramUniformInit(ipp8u, (Ipp32f*)&low, (Ipp32f*)&high, (Ipp32s*)&levelNum, 1, pSpec) < 0)
|
||||
{
|
||||
if(pSpec) ippFree(pSpec);
|
||||
if(pBuffer) ippFree(pBuffer);
|
||||
*ok = false;
|
||||
return;
|
||||
}
|
||||
|
||||
IppStatus status = CV_INSTRUMENT_FUN_IPP(ippiHistogram_8u_C1R, src->ptr(range.start), (int)src->step, ippiSize(src->cols, range.end - range.start),
|
||||
phist.ptr<Ipp32u>(), pSpec, pBuffer);
|
||||
|
||||
if(pSpec) ippFree(pSpec);
|
||||
if(pBuffer) ippFree(pBuffer);
|
||||
#else
|
||||
CV_SUPPRESS_DEPRECATED_START
|
||||
IppStatus status = ippiHistogramEven_8u_C1R(src->ptr(range.start), (int)src->step, ippiSize(src->cols, range.end - range.start),
|
||||
phist.ptr<Ipp32s>(), (Ipp32s*)(Ipp32f*)*levels, levelNum, (Ipp32s)low, (Ipp32s)high);
|
||||
CV_SUPPRESS_DEPRECATED_END
|
||||
#endif
|
||||
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));
|
||||
else
|
||||
ippiCopy_32s_C1R((Ipp32s*)pTls->thist.get(), sizeof(Ipp32u), (Ipp32s*)m_hist.ptr(), (int)m_hist.step, ippiSize(1, m_histSize));
|
||||
}
|
||||
|
||||
private:
|
||||
const Mat * src;
|
||||
Mat * hist;
|
||||
AutoBuffer<Ipp32f> * levels;
|
||||
Ipp32s histSize;
|
||||
Ipp32f low, high;
|
||||
bool * ok;
|
||||
const Mat &m_src;
|
||||
Mat &m_hist;
|
||||
Ipp32s m_histSize;
|
||||
const float *m_ranges;
|
||||
bool m_uniform;
|
||||
|
||||
const IPPCalcHistInvoker & operator = (const IPPCalcHistInvoker & );
|
||||
IppiHistogram_C1 ippiHistogram_C1;
|
||||
IppiSize m_fullRoi;
|
||||
IppDataType m_type;
|
||||
Ipp32s m_levelsNum;
|
||||
int m_bufferSize;
|
||||
int m_specSize;
|
||||
|
||||
mutable Mutex m_syncMutex;
|
||||
TLSData<ipp_calcHistParallelTLS> m_tls;
|
||||
|
||||
volatile bool &m_ok;
|
||||
const ipp_calcHistParallel & operator = (const ipp_calcHistParallel & );
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1319,49 +1383,49 @@ namespace cv
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_IPP)
|
||||
#ifdef HAVE_IPP
|
||||
#define IPP_HISTOGRAM_PARALLEL 1
|
||||
namespace cv
|
||||
{
|
||||
static bool ipp_calchist(const Mat* images, int nimages, const int* channels,
|
||||
InputArray _mask, OutputArray _hist, int dims, const int* histSize,
|
||||
const float** ranges, bool uniform, bool accumulate )
|
||||
static bool ipp_calchist(const Mat &image, Mat &hist, int histSize, const float** ranges, bool uniform, bool accumulate)
|
||||
{
|
||||
CV_INSTRUMENT_REGION_IPP()
|
||||
|
||||
Mat mask = _mask.getMat();
|
||||
|
||||
CV_Assert(dims > 0 && histSize);
|
||||
|
||||
_hist.create(dims, histSize, CV_32F);
|
||||
Mat hist = _hist.getMat(), ihist = hist;
|
||||
ihist.flags = (ihist.flags & ~CV_MAT_TYPE_MASK)|CV_32S;
|
||||
|
||||
{
|
||||
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<Ipp32f> levels(histSize[0]);
|
||||
|
||||
bool ok = true;
|
||||
const Mat & src = images[0];
|
||||
int nstripes = std::min<int>(8, static_cast<int>(src.total() / (1 << 16)));
|
||||
#ifdef HAVE_CONCURRENCY
|
||||
nstripes = 1;
|
||||
// No SSE42 optimization for uniform 32f
|
||||
#if IPP_DISABLE_PERF_HISTU32F_SSE42
|
||||
if(uniform && image.depth() == CV_32F && !(ipp::getIppFeatures()&ippCPUID_AVX))
|
||||
return false;
|
||||
#endif
|
||||
IPPCalcHistInvoker invoker(src, ihist, levels, histSize[0], ranges[0][0], ranges[0][1], &ok);
|
||||
Range range(0, src.rows);
|
||||
parallel_for_(range, invoker, nstripes);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
ihist.convertTo(hist, CV_32F);
|
||||
return true;
|
||||
}
|
||||
Mat ihist = hist;
|
||||
if(accumulate)
|
||||
ihist.create(1, &histSize, CV_32S);
|
||||
|
||||
bool ok = true;
|
||||
int threads = ippiSuggestThreadsNum(image, (1+((double)ihist.total()/image.total()))*2);
|
||||
Range range(0, image.rows);
|
||||
ipp_calcHistParallel invoker(image, ihist, histSize, ranges[0], uniform, ok);
|
||||
if(!ok)
|
||||
return false;
|
||||
|
||||
if(IPP_HISTOGRAM_PARALLEL && threads > 1)
|
||||
parallel_for_(range, invoker, threads*2);
|
||||
else
|
||||
invoker(range);
|
||||
|
||||
if(ok)
|
||||
{
|
||||
if(accumulate)
|
||||
{
|
||||
IppiSize histRoi = ippiSize(1, histSize);
|
||||
IppAutoBuffer<Ipp32f> fhist(histSize*sizeof(Ipp32f));
|
||||
CV_INSTRUMENT_FUN_IPP(ippiConvert_32s32f_C1R, (Ipp32s*)ihist.ptr(), (int)ihist.step, (Ipp32f*)fhist, sizeof(Ipp32f), histRoi);
|
||||
CV_INSTRUMENT_FUN_IPP(ippiAdd_32f_C1IR, (Ipp32f*)fhist, sizeof(Ipp32f), (Ipp32f*)hist.ptr(), (int)hist.step, histRoi);
|
||||
}
|
||||
else
|
||||
CV_INSTRUMENT_FUN_IPP(ippiConvert_32s32f_C1R, (Ipp32s*)ihist.ptr(), (int)ihist.step, (Ipp32f*)hist.ptr(), (int)hist.step, ippiSize(1, histSize));
|
||||
}
|
||||
return false;
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1379,23 +1443,24 @@ void cv::calcHist( const Mat* images, int nimages, const int* channels,
|
||||
ranges && ranges[0],
|
||||
openvx_calchist(images[0], _hist, histSize[0], ranges[0]))
|
||||
|
||||
CV_IPP_RUN(nimages == 1 && images[0].type() == CV_8UC1 && dims == 1 && channels &&
|
||||
channels[0] == 0 && _mask.getMat().empty() && images[0].dims <= 2 &&
|
||||
!accumulate && uniform,
|
||||
ipp_calchist(images, nimages, channels,
|
||||
_mask, _hist, dims, histSize,
|
||||
ranges, uniform, accumulate));
|
||||
|
||||
Mat mask = _mask.getMat();
|
||||
|
||||
CV_Assert(dims > 0 && histSize);
|
||||
|
||||
const uchar* const histdata = _hist.getMat().ptr();
|
||||
_hist.create(dims, histSize, CV_32F);
|
||||
Mat hist = _hist.getMat(), ihist = hist;
|
||||
Mat hist = _hist.getMat();
|
||||
|
||||
if(histdata != hist.data)
|
||||
accumulate = false;
|
||||
|
||||
CV_IPP_RUN(nimages == 1 && dims == 1 && channels && channels[0] == 0 && _mask.empty() && images[0].dims <= 2,
|
||||
ipp_calchist(images[0], hist, histSize[0], ranges, uniform, accumulate));
|
||||
|
||||
Mat ihist = hist;
|
||||
ihist.flags = (ihist.flags & ~CV_MAT_TYPE_MASK)|CV_32S;
|
||||
|
||||
if( !accumulate || histdata != hist.data )
|
||||
if(!accumulate)
|
||||
hist = Scalar(0.);
|
||||
else
|
||||
hist.convertTo(ihist, CV_32S);
|
||||
|
||||
Reference in New Issue
Block a user