1
0
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:
Pavel Vlasov
2017-04-13 15:50:23 +03:00
parent 1c728258e0
commit 35c7216846
27 changed files with 2087 additions and 1848 deletions
+170 -105
View File
@@ -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);