refactor cudaarithm reductions:
* remove overloads with explicit buffer, now BufferPool is used * added async versions for all reduce functions
This commit is contained in:
@@ -50,47 +50,64 @@
|
||||
|
||||
#include "opencv2/cudaarithm.hpp"
|
||||
#include "opencv2/cudev.hpp"
|
||||
#include "opencv2/core/private.cuda.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::cuda;
|
||||
using namespace cv::cudev;
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T>
|
||||
int countNonZeroImpl(const GpuMat& _src, GpuMat& _buf)
|
||||
template <typename T, typename D>
|
||||
void countNonZeroImpl(const GpuMat& _src, GpuMat& _dst, Stream& stream)
|
||||
{
|
||||
const GpuMat_<T>& src = (const GpuMat_<T>&) _src;
|
||||
GpuMat_<int>& buf = (GpuMat_<int>&) _buf;
|
||||
GpuMat_<D>& dst = (GpuMat_<D>&) _dst;
|
||||
|
||||
gridCountNonZero(src, buf);
|
||||
|
||||
int data;
|
||||
buf.download(cv::Mat(1, 1, buf.type(), &data));
|
||||
|
||||
return data;
|
||||
gridCountNonZero(src, dst, stream);
|
||||
}
|
||||
}
|
||||
|
||||
int cv::cuda::countNonZero(InputArray _src, GpuMat& buf)
|
||||
void cv::cuda::countNonZero(InputArray _src, OutputArray _dst, Stream& stream)
|
||||
{
|
||||
typedef int (*func_t)(const GpuMat& _src, GpuMat& _buf);
|
||||
typedef void (*func_t)(const GpuMat& src, GpuMat& dst, Stream& stream);
|
||||
static const func_t funcs[] =
|
||||
{
|
||||
countNonZeroImpl<uchar>,
|
||||
countNonZeroImpl<schar>,
|
||||
countNonZeroImpl<ushort>,
|
||||
countNonZeroImpl<short>,
|
||||
countNonZeroImpl<int>,
|
||||
countNonZeroImpl<float>,
|
||||
countNonZeroImpl<double>
|
||||
countNonZeroImpl<uchar, int>,
|
||||
countNonZeroImpl<schar, int>,
|
||||
countNonZeroImpl<ushort, int>,
|
||||
countNonZeroImpl<short, int>,
|
||||
countNonZeroImpl<int, int>,
|
||||
countNonZeroImpl<float, int>,
|
||||
countNonZeroImpl<double, int>,
|
||||
};
|
||||
|
||||
GpuMat src = _src.getGpuMat();
|
||||
GpuMat src = getInputMat(_src, stream);
|
||||
|
||||
CV_Assert( src.depth() <= CV_64F );
|
||||
CV_Assert( src.channels() == 1 );
|
||||
|
||||
const func_t func = funcs[src.depth()];
|
||||
GpuMat dst = getOutputMat(_dst, 1, 1, CV_32SC1, stream);
|
||||
|
||||
return func(src, buf);
|
||||
const func_t func = funcs[src.depth()];
|
||||
func(src, dst, stream);
|
||||
|
||||
syncOutput(dst, _dst, stream);
|
||||
}
|
||||
|
||||
int cv::cuda::countNonZero(InputArray _src)
|
||||
{
|
||||
Stream& stream = Stream::Null();
|
||||
|
||||
BufferPool pool(stream);
|
||||
GpuMat buf = pool.getBuffer(1, 1, CV_32SC1);
|
||||
|
||||
countNonZero(_src, buf, stream);
|
||||
|
||||
int data;
|
||||
buf.download(Mat(1, 1, CV_32SC1, &data));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -50,62 +50,140 @@
|
||||
|
||||
#include "opencv2/cudaarithm.hpp"
|
||||
#include "opencv2/cudev.hpp"
|
||||
#include "opencv2/core/private.cuda.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::cuda;
|
||||
using namespace cv::cudev;
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T>
|
||||
void minMaxImpl(const GpuMat& _src, const GpuMat& mask, GpuMat& _buf, double* minVal, double* maxVal)
|
||||
template <typename T, typename R>
|
||||
void minMaxImpl(const GpuMat& _src, const GpuMat& mask, GpuMat& _dst, Stream& stream)
|
||||
{
|
||||
typedef typename SelectIf<
|
||||
TypesEquals<T, double>::value,
|
||||
double,
|
||||
typename SelectIf<TypesEquals<T, float>::value, float, int>::type
|
||||
>::type work_type;
|
||||
|
||||
const GpuMat_<T>& src = (const GpuMat_<T>&) _src;
|
||||
GpuMat_<work_type>& buf = (GpuMat_<work_type>&) _buf;
|
||||
GpuMat_<R>& dst = (GpuMat_<R>&) _dst;
|
||||
|
||||
if (mask.empty())
|
||||
gridFindMinMaxVal(src, buf);
|
||||
gridFindMinMaxVal(src, dst, stream);
|
||||
else
|
||||
gridFindMinMaxVal(src, buf, globPtr<uchar>(mask));
|
||||
gridFindMinMaxVal(src, dst, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
|
||||
work_type data[2];
|
||||
buf.download(cv::Mat(1, 2, buf.type(), data));
|
||||
template <typename T, typename R>
|
||||
void minMaxImpl(const GpuMat& src, const GpuMat& mask, double* minVal, double* maxVal)
|
||||
{
|
||||
BufferPool pool(Stream::Null());
|
||||
GpuMat buf(pool.getBuffer(1, 2, DataType<R>::type));
|
||||
|
||||
if (minVal)
|
||||
*minVal = data[0];
|
||||
minMaxImpl<T, R>(src, mask, buf, Stream::Null());
|
||||
|
||||
R data[2];
|
||||
buf.download(Mat(1, 2, buf.type(), data));
|
||||
|
||||
if (maxVal)
|
||||
*maxVal = data[1];
|
||||
}
|
||||
}
|
||||
|
||||
void cv::cuda::minMax(InputArray _src, double* minVal, double* maxVal, InputArray _mask, GpuMat& buf)
|
||||
void cv::cuda::findMinMax(InputArray _src, OutputArray _dst, InputArray _mask, Stream& stream)
|
||||
{
|
||||
typedef void (*func_t)(const GpuMat& _src, const GpuMat& mask, GpuMat& _buf, double* minVal, double* maxVal);
|
||||
typedef void (*func_t)(const GpuMat& _src, const GpuMat& mask, GpuMat& _dst, Stream& stream);
|
||||
static const func_t funcs[] =
|
||||
{
|
||||
minMaxImpl<uchar>,
|
||||
minMaxImpl<schar>,
|
||||
minMaxImpl<ushort>,
|
||||
minMaxImpl<short>,
|
||||
minMaxImpl<int>,
|
||||
minMaxImpl<float>,
|
||||
minMaxImpl<double>
|
||||
minMaxImpl<uchar, int>,
|
||||
minMaxImpl<schar, int>,
|
||||
minMaxImpl<ushort, int>,
|
||||
minMaxImpl<short, int>,
|
||||
minMaxImpl<int, int>,
|
||||
minMaxImpl<float, float>,
|
||||
minMaxImpl<double, double>
|
||||
};
|
||||
|
||||
GpuMat src = _src.getGpuMat();
|
||||
GpuMat mask = _mask.getGpuMat();
|
||||
const GpuMat src = getInputMat(_src, stream);
|
||||
const GpuMat mask = getInputMat(_mask, stream);
|
||||
|
||||
CV_Assert( src.channels() == 1 );
|
||||
CV_DbgAssert( mask.empty() || (mask.size() == src.size() && mask.type() == CV_8U) );
|
||||
CV_Assert( mask.empty() || (mask.size() == src.size() && mask.type() == CV_8U) );
|
||||
|
||||
const int src_depth = src.depth();
|
||||
const int dst_depth = src_depth < CV_32F ? CV_32S : src_depth;
|
||||
|
||||
GpuMat dst = getOutputMat(_dst, 1, 2, dst_depth, stream);
|
||||
|
||||
const func_t func = funcs[src.depth()];
|
||||
func(src, mask, dst, stream);
|
||||
|
||||
func(src, mask, buf, minVal, maxVal);
|
||||
syncOutput(dst, _dst, stream);
|
||||
}
|
||||
|
||||
void cv::cuda::minMax(InputArray _src, double* minVal, double* maxVal, InputArray _mask)
|
||||
{
|
||||
Stream& stream = Stream::Null();
|
||||
|
||||
HostMem dst;
|
||||
findMinMax(_src, dst, _mask, stream);
|
||||
|
||||
stream.waitForCompletion();
|
||||
|
||||
double vals[2];
|
||||
dst.createMatHeader().convertTo(Mat(1, 2, CV_64FC1, &vals[0]), CV_64F);
|
||||
|
||||
if (minVal)
|
||||
*minVal = vals[0];
|
||||
|
||||
if (maxVal)
|
||||
*maxVal = vals[1];
|
||||
}
|
||||
|
||||
namespace cv { namespace cuda { namespace internal {
|
||||
|
||||
void findMaxAbs(InputArray _src, OutputArray _dst, InputArray _mask, Stream& stream);
|
||||
|
||||
}}}
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T, typename R>
|
||||
void findMaxAbsImpl(const GpuMat& _src, const GpuMat& mask, GpuMat& _dst, Stream& stream)
|
||||
{
|
||||
const GpuMat_<T>& src = (const GpuMat_<T>&) _src;
|
||||
GpuMat_<R>& dst = (GpuMat_<R>&) _dst;
|
||||
|
||||
if (mask.empty())
|
||||
gridFindMaxVal(abs_(src), dst, stream);
|
||||
else
|
||||
gridFindMaxVal(abs_(src), dst, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
}
|
||||
|
||||
void cv::cuda::internal::findMaxAbs(InputArray _src, OutputArray _dst, InputArray _mask, Stream& stream)
|
||||
{
|
||||
typedef void (*func_t)(const GpuMat& _src, const GpuMat& mask, GpuMat& _dst, Stream& stream);
|
||||
static const func_t funcs[] =
|
||||
{
|
||||
findMaxAbsImpl<uchar, int>,
|
||||
findMaxAbsImpl<schar, int>,
|
||||
findMaxAbsImpl<ushort, int>,
|
||||
findMaxAbsImpl<short, int>,
|
||||
findMaxAbsImpl<int, int>,
|
||||
findMaxAbsImpl<float, float>,
|
||||
findMaxAbsImpl<double, double>
|
||||
};
|
||||
|
||||
const GpuMat src = getInputMat(_src, stream);
|
||||
const GpuMat mask = getInputMat(_mask, stream);
|
||||
|
||||
CV_Assert( src.channels() == 1 );
|
||||
CV_Assert( mask.empty() || (mask.size() == src.size() && mask.type() == CV_8U) );
|
||||
|
||||
const int src_depth = src.depth();
|
||||
const int dst_depth = src_depth < CV_32F ? CV_32S : src_depth;
|
||||
|
||||
GpuMat dst = getOutputMat(_dst, 1, 1, dst_depth, stream);
|
||||
|
||||
const func_t func = funcs[src.depth()];
|
||||
func(src, mask, dst, stream);
|
||||
|
||||
syncOutput(dst, _dst, stream);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -50,78 +50,110 @@
|
||||
|
||||
#include "opencv2/cudaarithm.hpp"
|
||||
#include "opencv2/cudev.hpp"
|
||||
#include "opencv2/core/private.cuda.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::cuda;
|
||||
using namespace cv::cudev;
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T>
|
||||
void minMaxLocImpl(const GpuMat& _src, const GpuMat& mask, GpuMat& _valBuf, GpuMat& _locBuf, double* minVal, double* maxVal, cv::Point* minLoc, cv::Point* maxLoc)
|
||||
template <typename T, typename R>
|
||||
void minMaxLocImpl(const GpuMat& _src, const GpuMat& mask, GpuMat& _valBuf, GpuMat& _locBuf, Stream& stream)
|
||||
{
|
||||
typedef typename SelectIf<
|
||||
TypesEquals<T, double>::value,
|
||||
double,
|
||||
typename SelectIf<TypesEquals<T, float>::value, float, int>::type
|
||||
>::type work_type;
|
||||
|
||||
const GpuMat_<T>& src = (const GpuMat_<T>&) _src;
|
||||
GpuMat_<work_type>& valBuf = (GpuMat_<work_type>&) _valBuf;
|
||||
GpuMat_<R>& valBuf = (GpuMat_<R>&) _valBuf;
|
||||
GpuMat_<int>& locBuf = (GpuMat_<int>&) _locBuf;
|
||||
|
||||
if (mask.empty())
|
||||
gridMinMaxLoc(src, valBuf, locBuf);
|
||||
gridMinMaxLoc(src, valBuf, locBuf, stream);
|
||||
else
|
||||
gridMinMaxLoc(src, valBuf, locBuf, globPtr<uchar>(mask));
|
||||
|
||||
cv::Mat_<work_type> h_valBuf;
|
||||
cv::Mat_<int> h_locBuf;
|
||||
|
||||
valBuf.download(h_valBuf);
|
||||
locBuf.download(h_locBuf);
|
||||
|
||||
if (minVal)
|
||||
*minVal = h_valBuf(0, 0);
|
||||
|
||||
if (maxVal)
|
||||
*maxVal = h_valBuf(1, 0);
|
||||
|
||||
if (minLoc)
|
||||
{
|
||||
const int idx = h_locBuf(0, 0);
|
||||
*minLoc = cv::Point(idx % src.cols, idx / src.cols);
|
||||
}
|
||||
|
||||
if (maxLoc)
|
||||
{
|
||||
const int idx = h_locBuf(1, 0);
|
||||
*maxLoc = cv::Point(idx % src.cols, idx / src.cols);
|
||||
}
|
||||
gridMinMaxLoc(src, valBuf, locBuf, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
}
|
||||
|
||||
void cv::cuda::minMaxLoc(InputArray _src, double* minVal, double* maxVal, Point* minLoc, Point* maxLoc, InputArray _mask, GpuMat& valBuf, GpuMat& locBuf)
|
||||
void cv::cuda::findMinMaxLoc(InputArray _src, OutputArray _minMaxVals, OutputArray _loc, InputArray _mask, Stream& stream)
|
||||
{
|
||||
typedef void (*func_t)(const GpuMat& _src, const GpuMat& mask, GpuMat& _valBuf, GpuMat& _locBuf, double* minVal, double* maxVal, cv::Point* minLoc, cv::Point* maxLoc);
|
||||
typedef void (*func_t)(const GpuMat& _src, const GpuMat& mask, GpuMat& _valBuf, GpuMat& _locBuf, Stream& stream);
|
||||
static const func_t funcs[] =
|
||||
{
|
||||
minMaxLocImpl<uchar>,
|
||||
minMaxLocImpl<schar>,
|
||||
minMaxLocImpl<ushort>,
|
||||
minMaxLocImpl<short>,
|
||||
minMaxLocImpl<int>,
|
||||
minMaxLocImpl<float>,
|
||||
minMaxLocImpl<double>
|
||||
minMaxLocImpl<uchar, int>,
|
||||
minMaxLocImpl<schar, int>,
|
||||
minMaxLocImpl<ushort, int>,
|
||||
minMaxLocImpl<short, int>,
|
||||
minMaxLocImpl<int, int>,
|
||||
minMaxLocImpl<float, float>,
|
||||
minMaxLocImpl<double, double>
|
||||
};
|
||||
|
||||
GpuMat src = _src.getGpuMat();
|
||||
GpuMat mask = _mask.getGpuMat();
|
||||
const GpuMat src = getInputMat(_src, stream);
|
||||
const GpuMat mask = getInputMat(_mask, stream);
|
||||
|
||||
CV_Assert( src.channels() == 1 );
|
||||
CV_DbgAssert( mask.empty() || (mask.size() == src.size() && mask.type() == CV_8U) );
|
||||
CV_Assert( mask.empty() || (mask.size() == src.size() && mask.type() == CV_8U) );
|
||||
|
||||
const func_t func = funcs[src.depth()];
|
||||
const int src_depth = src.depth();
|
||||
|
||||
func(src, mask, valBuf, locBuf, minVal, maxVal, minLoc, maxLoc);
|
||||
BufferPool pool(stream);
|
||||
GpuMat valBuf(pool.getAllocator());
|
||||
GpuMat locBuf(pool.getAllocator());
|
||||
|
||||
const func_t func = funcs[src_depth];
|
||||
func(src, mask, valBuf, locBuf, stream);
|
||||
|
||||
GpuMat minMaxVals = valBuf.colRange(0, 1);
|
||||
GpuMat loc = locBuf.colRange(0, 1);
|
||||
|
||||
if (_minMaxVals.kind() == _InputArray::CUDA_GPU_MAT)
|
||||
{
|
||||
minMaxVals.copyTo(_minMaxVals, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
minMaxVals.download(_minMaxVals, stream);
|
||||
}
|
||||
|
||||
if (_loc.kind() == _InputArray::CUDA_GPU_MAT)
|
||||
{
|
||||
loc.copyTo(_loc, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
loc.download(_loc, stream);
|
||||
}
|
||||
}
|
||||
|
||||
void cv::cuda::minMaxLoc(InputArray _src, double* minVal, double* maxVal, Point* minLoc, Point* maxLoc, InputArray _mask)
|
||||
{
|
||||
Stream& stream = Stream::Null();
|
||||
|
||||
HostMem minMaxVals, locVals;
|
||||
findMinMaxLoc(_src, minMaxVals, locVals, _mask, stream);
|
||||
|
||||
stream.waitForCompletion();
|
||||
|
||||
double vals[2];
|
||||
minMaxVals.createMatHeader().convertTo(Mat(minMaxVals.size(), CV_64FC1, &vals[0]), CV_64F);
|
||||
|
||||
int locs[2];
|
||||
locVals.createMatHeader().copyTo(Mat(locVals.size(), CV_32SC1, &locs[0]));
|
||||
Size size = _src.size();
|
||||
cv::Point locs2D[] = {
|
||||
cv::Point(locs[0] % size.width, locs[0] / size.width),
|
||||
cv::Point(locs[1] % size.width, locs[1] / size.width),
|
||||
};
|
||||
|
||||
if (minVal)
|
||||
*minVal = vals[0];
|
||||
|
||||
if (maxVal)
|
||||
*maxVal = vals[1];
|
||||
|
||||
if (minLoc)
|
||||
*minLoc = locs2D[0];
|
||||
|
||||
if (maxLoc)
|
||||
*maxLoc = locs2D[1];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -50,70 +50,140 @@
|
||||
|
||||
#include "opencv2/cudaarithm.hpp"
|
||||
#include "opencv2/cudev.hpp"
|
||||
#include "opencv2/core/private.cuda.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::cuda;
|
||||
using namespace cv::cudev;
|
||||
|
||||
namespace
|
||||
{
|
||||
double normDiffInf(const GpuMat& _src1, const GpuMat& _src2, GpuMat& _buf)
|
||||
void normDiffInf(const GpuMat& _src1, const GpuMat& _src2, GpuMat& _dst, Stream& stream)
|
||||
{
|
||||
const GpuMat_<uchar>& src1 = (const GpuMat_<uchar>&) _src1;
|
||||
const GpuMat_<uchar>& src2 = (const GpuMat_<uchar>&) _src2;
|
||||
GpuMat_<int>& buf = (GpuMat_<int>&) _buf;
|
||||
GpuMat_<int>& dst = (GpuMat_<int>&) _dst;
|
||||
|
||||
gridFindMinMaxVal(abs_(cvt_<int>(src1) - cvt_<int>(src2)), buf);
|
||||
|
||||
int data[2];
|
||||
buf.download(cv::Mat(1, 2, buf.type(), data));
|
||||
|
||||
return data[1];
|
||||
gridFindMaxVal(abs_(cvt_<int>(src1) - cvt_<int>(src2)), dst, stream);
|
||||
}
|
||||
|
||||
double normDiffL1(const GpuMat& _src1, const GpuMat& _src2, GpuMat& _buf)
|
||||
void normDiffL1(const GpuMat& _src1, const GpuMat& _src2, GpuMat& _dst, Stream& stream)
|
||||
{
|
||||
const GpuMat_<uchar>& src1 = (const GpuMat_<uchar>&) _src1;
|
||||
const GpuMat_<uchar>& src2 = (const GpuMat_<uchar>&) _src2;
|
||||
GpuMat_<int>& buf = (GpuMat_<int>&) _buf;
|
||||
GpuMat_<int>& dst = (GpuMat_<int>&) _dst;
|
||||
|
||||
gridCalcSum(abs_(cvt_<int>(src1) - cvt_<int>(src2)), buf);
|
||||
|
||||
int data;
|
||||
buf.download(cv::Mat(1, 1, buf.type(), &data));
|
||||
|
||||
return data;
|
||||
gridCalcSum(abs_(cvt_<int>(src1) - cvt_<int>(src2)), dst, stream);
|
||||
}
|
||||
|
||||
double normDiffL2(const GpuMat& _src1, const GpuMat& _src2, GpuMat& _buf)
|
||||
void normDiffL2(const GpuMat& _src1, const GpuMat& _src2, GpuMat& _dst, Stream& stream)
|
||||
{
|
||||
const GpuMat_<uchar>& src1 = (const GpuMat_<uchar>&) _src1;
|
||||
const GpuMat_<uchar>& src2 = (const GpuMat_<uchar>&) _src2;
|
||||
GpuMat_<double>& buf = (GpuMat_<double>&) _buf;
|
||||
GpuMat_<double>& dst = (GpuMat_<double>&) _dst;
|
||||
|
||||
gridCalcSum(sqr_(cvt_<double>(src1) - cvt_<double>(src2)), buf);
|
||||
BufferPool pool(stream);
|
||||
GpuMat_<double> buf(1, 1, pool.getAllocator());
|
||||
|
||||
double data;
|
||||
buf.download(cv::Mat(1, 1, buf.type(), &data));
|
||||
|
||||
return std::sqrt(data);
|
||||
gridCalcSum(sqr_(cvt_<double>(src1) - cvt_<double>(src2)), buf, stream);
|
||||
gridTransformUnary(buf, dst, sqrt_func<double>(), stream);
|
||||
}
|
||||
}
|
||||
|
||||
double cv::cuda::norm(InputArray _src1, InputArray _src2, GpuMat& buf, int normType)
|
||||
void cv::cuda::calcNormDiff(InputArray _src1, InputArray _src2, OutputArray _dst, int normType, Stream& stream)
|
||||
{
|
||||
typedef double (*func_t)(const GpuMat& _src1, const GpuMat& _src2, GpuMat& _buf);
|
||||
typedef void (*func_t)(const GpuMat& _src1, const GpuMat& _src2, GpuMat& _dst, Stream& stream);
|
||||
static const func_t funcs[] =
|
||||
{
|
||||
0, normDiffInf, normDiffL1, 0, normDiffL2
|
||||
};
|
||||
|
||||
GpuMat src1 = _src1.getGpuMat();
|
||||
GpuMat src2 = _src2.getGpuMat();
|
||||
GpuMat src1 = getInputMat(_src1, stream);
|
||||
GpuMat src2 = getInputMat(_src2, stream);
|
||||
|
||||
CV_Assert( src1.type() == CV_8UC1 );
|
||||
CV_Assert( src1.size() == src2.size() && src1.type() == src2.type() );
|
||||
CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 );
|
||||
|
||||
return funcs[normType](src1, src2, buf);
|
||||
GpuMat dst = getOutputMat(_dst, 1, 1, normType == NORM_L2 ? CV_64FC1 : CV_32SC1, stream);
|
||||
|
||||
const func_t func = funcs[normType];
|
||||
func(src1, src2, dst, stream);
|
||||
|
||||
syncOutput(dst, _dst, stream);
|
||||
}
|
||||
|
||||
double cv::cuda::norm(InputArray _src1, InputArray _src2, int normType)
|
||||
{
|
||||
Stream& stream = Stream::Null();
|
||||
|
||||
HostMem dst;
|
||||
calcNormDiff(_src1, _src2, dst, normType, stream);
|
||||
|
||||
stream.waitForCompletion();
|
||||
|
||||
double val;
|
||||
dst.createMatHeader().convertTo(Mat(1, 1, CV_64FC1, &val), CV_64F);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
namespace cv { namespace cuda { namespace internal {
|
||||
|
||||
void normL2(cv::InputArray _src, cv::OutputArray _dst, cv::InputArray _mask, Stream& stream);
|
||||
|
||||
}}}
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T, typename R>
|
||||
void normL2Impl(const GpuMat& _src, const GpuMat& mask, GpuMat& _dst, Stream& stream)
|
||||
{
|
||||
const GpuMat_<T>& src = (const GpuMat_<T>&) _src;
|
||||
GpuMat_<R>& dst = (GpuMat_<R>&) _dst;
|
||||
|
||||
BufferPool pool(stream);
|
||||
GpuMat_<double> buf(1, 1, pool.getAllocator());
|
||||
|
||||
if (mask.empty())
|
||||
{
|
||||
gridCalcSum(sqr_(cvt_<double>(src)), buf, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
gridCalcSum(sqr_(cvt_<double>(src)), buf, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
|
||||
gridTransformUnary(buf, dst, sqrt_func<double>(), stream);
|
||||
}
|
||||
}
|
||||
|
||||
void cv::cuda::internal::normL2(InputArray _src, OutputArray _dst, InputArray _mask, Stream& stream)
|
||||
{
|
||||
typedef void (*func_t)(const GpuMat& _src, const GpuMat& mask, GpuMat& _dst, Stream& stream);
|
||||
static const func_t funcs[] =
|
||||
{
|
||||
normL2Impl<uchar, double>,
|
||||
normL2Impl<schar, double>,
|
||||
normL2Impl<ushort, double>,
|
||||
normL2Impl<short, double>,
|
||||
normL2Impl<int, double>,
|
||||
normL2Impl<float, double>,
|
||||
normL2Impl<double, double>
|
||||
};
|
||||
|
||||
const GpuMat src = getInputMat(_src, stream);
|
||||
const GpuMat mask = getInputMat(_mask, stream);
|
||||
|
||||
CV_Assert( src.channels() == 1 );
|
||||
CV_Assert( mask.empty() || (mask.size() == src.size() && mask.type() == CV_8U) );
|
||||
|
||||
GpuMat dst = getOutputMat(_dst, 1, 1, CV_64FC1, stream);
|
||||
|
||||
const func_t func = funcs[src.depth()];
|
||||
func(src, mask, dst, stream);
|
||||
|
||||
syncOutput(dst, _dst, stream);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
290
modules/cudaarithm/src/cuda/normalize.cu
Normal file
290
modules/cudaarithm/src/cuda/normalize.cu
Normal file
@@ -0,0 +1,290 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "opencv2/opencv_modules.hpp"
|
||||
|
||||
#ifndef HAVE_OPENCV_CUDEV
|
||||
|
||||
#error "opencv_cudev is required"
|
||||
|
||||
#else
|
||||
|
||||
#include "opencv2/cudaarithm.hpp"
|
||||
#include "opencv2/cudev.hpp"
|
||||
#include "opencv2/core/private.cuda.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::cuda;
|
||||
using namespace cv::cudev;
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T, typename R, typename I>
|
||||
struct ConvertorMinMax : unary_function<T, R>
|
||||
{
|
||||
typedef typename LargerType<T, R>::type larger_type1;
|
||||
typedef typename LargerType<larger_type1, I>::type larger_type2;
|
||||
typedef typename LargerType<larger_type2, float>::type scalar_type;
|
||||
|
||||
scalar_type dmin, dmax;
|
||||
const I* minMaxVals;
|
||||
|
||||
__device__ R operator ()(typename TypeTraits<T>::parameter_type src) const
|
||||
{
|
||||
const scalar_type smin = minMaxVals[0];
|
||||
const scalar_type smax = minMaxVals[1];
|
||||
|
||||
const scalar_type scale = (dmax - dmin) * (smax - smin > numeric_limits<scalar_type>::epsilon() ? 1.0 / (smax - smin) : 0.0);
|
||||
const scalar_type shift = dmin - smin * scale;
|
||||
|
||||
return cudev::saturate_cast<R>(scale * src + shift);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename R, typename I>
|
||||
void normalizeMinMax(const GpuMat& _src, GpuMat& _dst, double a, double b, const GpuMat& mask, Stream& stream)
|
||||
{
|
||||
const GpuMat_<T>& src = (const GpuMat_<T>&)_src;
|
||||
GpuMat_<R>& dst = (GpuMat_<R>&)_dst;
|
||||
|
||||
BufferPool pool(stream);
|
||||
GpuMat_<I> minMaxVals(1, 2, pool.getAllocator());
|
||||
|
||||
if (mask.empty())
|
||||
{
|
||||
gridFindMinMaxVal(src, minMaxVals, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
gridFindMinMaxVal(src, minMaxVals, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
|
||||
ConvertorMinMax<T, R, I> cvt;
|
||||
cvt.dmin = std::min(a, b);
|
||||
cvt.dmax = std::max(a, b);
|
||||
cvt.minMaxVals = minMaxVals[0];
|
||||
|
||||
if (mask.empty())
|
||||
{
|
||||
gridTransformUnary(src, dst, cvt, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst.setTo(Scalar::all(0), stream);
|
||||
gridTransformUnary(src, dst, cvt, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename R, typename I, bool normL2>
|
||||
struct ConvertorNorm : unary_function<T, R>
|
||||
{
|
||||
typedef typename LargerType<T, R>::type larger_type1;
|
||||
typedef typename LargerType<larger_type1, I>::type larger_type2;
|
||||
typedef typename LargerType<larger_type2, float>::type scalar_type;
|
||||
|
||||
scalar_type a;
|
||||
const I* normVal;
|
||||
|
||||
__device__ R operator ()(typename TypeTraits<T>::parameter_type src) const
|
||||
{
|
||||
sqrt_func<scalar_type> sqrt;
|
||||
|
||||
scalar_type scale = normL2 ? sqrt(*normVal) : *normVal;
|
||||
scale = scale > numeric_limits<scalar_type>::epsilon() ? a / scale : 0.0;
|
||||
|
||||
return cudev::saturate_cast<R>(scale * src);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename R, typename I>
|
||||
void normalizeNorm(const GpuMat& _src, GpuMat& _dst, double a, int normType, const GpuMat& mask, Stream& stream)
|
||||
{
|
||||
const GpuMat_<T>& src = (const GpuMat_<T>&)_src;
|
||||
GpuMat_<R>& dst = (GpuMat_<R>&)_dst;
|
||||
|
||||
BufferPool pool(stream);
|
||||
GpuMat_<I> normVal(1, 1, pool.getAllocator());
|
||||
|
||||
if (normType == NORM_L1)
|
||||
{
|
||||
if (mask.empty())
|
||||
{
|
||||
gridCalcSum(abs_(cvt_<I>(src)), normVal, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
gridCalcSum(abs_(cvt_<I>(src)), normVal, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
}
|
||||
else if (normType == NORM_L2)
|
||||
{
|
||||
if (mask.empty())
|
||||
{
|
||||
gridCalcSum(sqr_(cvt_<I>(src)), normVal, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
gridCalcSum(sqr_(cvt_<I>(src)), normVal, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
}
|
||||
else // NORM_INF
|
||||
{
|
||||
if (mask.empty())
|
||||
{
|
||||
gridFindMaxVal(abs_(cvt_<I>(src)), normVal, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
gridFindMaxVal(abs_(cvt_<I>(src)), normVal, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
}
|
||||
|
||||
if (normType == NORM_L2)
|
||||
{
|
||||
ConvertorNorm<T, R, I, true> cvt;
|
||||
cvt.a = a;
|
||||
cvt.normVal = normVal[0];
|
||||
|
||||
if (mask.empty())
|
||||
{
|
||||
gridTransformUnary(src, dst, cvt, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst.setTo(Scalar::all(0), stream);
|
||||
gridTransformUnary(src, dst, cvt, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConvertorNorm<T, R, I, false> cvt;
|
||||
cvt.a = a;
|
||||
cvt.normVal = normVal[0];
|
||||
|
||||
if (mask.empty())
|
||||
{
|
||||
gridTransformUnary(src, dst, cvt, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst.setTo(Scalar::all(0), stream);
|
||||
gridTransformUnary(src, dst, cvt, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void cv::cuda::normalize(InputArray _src, OutputArray _dst, double a, double b, int normType, int dtype, InputArray _mask, Stream& stream)
|
||||
{
|
||||
typedef void (*func_minmax_t)(const GpuMat& _src, GpuMat& _dst, double a, double b, const GpuMat& mask, Stream& stream);
|
||||
typedef void (*func_norm_t)(const GpuMat& _src, GpuMat& _dst, double a, int normType, const GpuMat& mask, Stream& stream);
|
||||
|
||||
static const func_minmax_t funcs_minmax[] =
|
||||
{
|
||||
normalizeMinMax<uchar, float, float>,
|
||||
normalizeMinMax<schar, float, float>,
|
||||
normalizeMinMax<ushort, float, float>,
|
||||
normalizeMinMax<short, float, float>,
|
||||
normalizeMinMax<int, float, float>,
|
||||
normalizeMinMax<float, float, float>,
|
||||
normalizeMinMax<double, double, double>
|
||||
};
|
||||
|
||||
static const func_norm_t funcs_norm[] =
|
||||
{
|
||||
normalizeNorm<uchar, float, float>,
|
||||
normalizeNorm<schar, float, float>,
|
||||
normalizeNorm<ushort, float, float>,
|
||||
normalizeNorm<short, float, float>,
|
||||
normalizeNorm<int, float, float>,
|
||||
normalizeNorm<float, float, float>,
|
||||
normalizeNorm<double, double, double>
|
||||
};
|
||||
|
||||
CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 || normType == NORM_MINMAX );
|
||||
|
||||
const GpuMat src = getInputMat(_src, stream);
|
||||
const GpuMat mask = getInputMat(_mask, stream);
|
||||
|
||||
CV_Assert( src.channels() == 1 );
|
||||
CV_Assert( mask.empty() || (mask.size() == src.size() && mask.type() == CV_8U) );
|
||||
|
||||
dtype = CV_MAT_DEPTH(dtype);
|
||||
|
||||
const int src_depth = src.depth();
|
||||
const int tmp_depth = src_depth <= CV_32F ? CV_32F : src_depth;
|
||||
|
||||
GpuMat dst;
|
||||
if (dtype == tmp_depth)
|
||||
{
|
||||
_dst.create(src.size(), tmp_depth);
|
||||
dst = getOutputMat(_dst, src.size(), tmp_depth, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
BufferPool pool(stream);
|
||||
dst = pool.getBuffer(src.size(), tmp_depth);
|
||||
}
|
||||
|
||||
if (normType == NORM_MINMAX)
|
||||
{
|
||||
const func_minmax_t func = funcs_minmax[src_depth];
|
||||
func(src, dst, a, b, mask, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
const func_norm_t func = funcs_norm[src_depth];
|
||||
func(src, dst, a, normType, mask, stream);
|
||||
}
|
||||
|
||||
if (dtype == tmp_depth)
|
||||
{
|
||||
syncOutput(dst, _dst, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst.convertTo(_dst, dtype, stream);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -50,126 +50,153 @@
|
||||
|
||||
#include "opencv2/cudaarithm.hpp"
|
||||
#include "opencv2/cudev.hpp"
|
||||
#include "opencv2/core/private.cuda.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::cuda;
|
||||
using namespace cv::cudev;
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T, typename R, int cn>
|
||||
cv::Scalar sumImpl(const GpuMat& _src, const GpuMat& mask, GpuMat& _buf)
|
||||
void sumImpl(const GpuMat& _src, GpuMat& _dst, const GpuMat& mask, Stream& stream)
|
||||
{
|
||||
typedef typename MakeVec<T, cn>::type src_type;
|
||||
typedef typename MakeVec<R, cn>::type res_type;
|
||||
|
||||
const GpuMat_<src_type>& src = (const GpuMat_<src_type>&) _src;
|
||||
GpuMat_<res_type>& buf = (GpuMat_<res_type>&) _buf;
|
||||
GpuMat_<res_type>& dst = (GpuMat_<res_type>&) _dst;
|
||||
|
||||
if (mask.empty())
|
||||
gridCalcSum(src, buf);
|
||||
gridCalcSum(src, dst, stream);
|
||||
else
|
||||
gridCalcSum(src, buf, globPtr<uchar>(mask));
|
||||
|
||||
cv::Scalar_<R> res;
|
||||
cv::Mat res_mat(buf.size(), buf.type(), res.val);
|
||||
buf.download(res_mat);
|
||||
|
||||
return res;
|
||||
gridCalcSum(src, dst, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
|
||||
template <typename T, typename R, int cn>
|
||||
cv::Scalar sumAbsImpl(const GpuMat& _src, const GpuMat& mask, GpuMat& _buf)
|
||||
void sumAbsImpl(const GpuMat& _src, GpuMat& _dst, const GpuMat& mask, Stream& stream)
|
||||
{
|
||||
typedef typename MakeVec<T, cn>::type src_type;
|
||||
typedef typename MakeVec<R, cn>::type res_type;
|
||||
|
||||
const GpuMat_<src_type>& src = (const GpuMat_<src_type>&) _src;
|
||||
GpuMat_<res_type>& buf = (GpuMat_<res_type>&) _buf;
|
||||
GpuMat_<res_type>& dst = (GpuMat_<res_type>&) _dst;
|
||||
|
||||
if (mask.empty())
|
||||
gridCalcSum(abs_(cvt_<res_type>(src)), buf);
|
||||
gridCalcSum(abs_(cvt_<res_type>(src)), dst, stream);
|
||||
else
|
||||
gridCalcSum(abs_(cvt_<res_type>(src)), buf, globPtr<uchar>(mask));
|
||||
|
||||
cv::Scalar_<R> res;
|
||||
cv::Mat res_mat(buf.size(), buf.type(), res.val);
|
||||
buf.download(res_mat);
|
||||
|
||||
return res;
|
||||
gridCalcSum(abs_(cvt_<res_type>(src)), dst, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
|
||||
template <typename T, typename R, int cn>
|
||||
cv::Scalar sumSqrImpl(const GpuMat& _src, const GpuMat& mask, GpuMat& _buf)
|
||||
void sumSqrImpl(const GpuMat& _src, GpuMat& _dst, const GpuMat& mask, Stream& stream)
|
||||
{
|
||||
typedef typename MakeVec<T, cn>::type src_type;
|
||||
typedef typename MakeVec<R, cn>::type res_type;
|
||||
|
||||
const GpuMat_<src_type>& src = (const GpuMat_<src_type>&) _src;
|
||||
GpuMat_<res_type>& buf = (GpuMat_<res_type>&) _buf;
|
||||
GpuMat_<res_type>& dst = (GpuMat_<res_type>&) _dst;
|
||||
|
||||
if (mask.empty())
|
||||
gridCalcSum(sqr_(cvt_<res_type>(src)), buf);
|
||||
gridCalcSum(sqr_(cvt_<res_type>(src)), dst, stream);
|
||||
else
|
||||
gridCalcSum(sqr_(cvt_<res_type>(src)), buf, globPtr<uchar>(mask));
|
||||
|
||||
cv::Scalar_<R> res;
|
||||
cv::Mat res_mat(buf.size(), buf.type(), res.val);
|
||||
buf.download(res_mat);
|
||||
|
||||
return res;
|
||||
gridCalcSum(sqr_(cvt_<res_type>(src)), dst, globPtr<uchar>(mask), stream);
|
||||
}
|
||||
}
|
||||
|
||||
cv::Scalar cv::cuda::sum(InputArray _src, InputArray _mask, GpuMat& buf)
|
||||
void cv::cuda::calcSum(InputArray _src, OutputArray _dst, InputArray _mask, Stream& stream)
|
||||
{
|
||||
typedef cv::Scalar (*func_t)(const GpuMat& _src, const GpuMat& mask, GpuMat& _buf);
|
||||
typedef void (*func_t)(const GpuMat& _src, GpuMat& _dst, const GpuMat& mask, Stream& stream);
|
||||
static const func_t funcs[7][4] =
|
||||
{
|
||||
{sumImpl<uchar , uint , 1>, sumImpl<uchar , uint , 2>, sumImpl<uchar , uint , 3>, sumImpl<uchar , uint , 4>},
|
||||
{sumImpl<schar , int , 1>, sumImpl<schar , int , 2>, sumImpl<schar , int , 3>, sumImpl<schar , int , 4>},
|
||||
{sumImpl<ushort, uint , 1>, sumImpl<ushort, uint , 2>, sumImpl<ushort, uint , 3>, sumImpl<ushort, uint , 4>},
|
||||
{sumImpl<short , int , 1>, sumImpl<short , int , 2>, sumImpl<short , int , 3>, sumImpl<short , int , 4>},
|
||||
{sumImpl<int , int , 1>, sumImpl<int , int , 2>, sumImpl<int , int , 3>, sumImpl<int , int , 4>},
|
||||
{sumImpl<float , float , 1>, sumImpl<float , float , 2>, sumImpl<float , float , 3>, sumImpl<float , float , 4>},
|
||||
{sumImpl<uchar , double, 1>, sumImpl<uchar , double, 2>, sumImpl<uchar , double, 3>, sumImpl<uchar , double, 4>},
|
||||
{sumImpl<schar , double, 1>, sumImpl<schar , double, 2>, sumImpl<schar , double, 3>, sumImpl<schar , double, 4>},
|
||||
{sumImpl<ushort, double, 1>, sumImpl<ushort, double, 2>, sumImpl<ushort, double, 3>, sumImpl<ushort, double, 4>},
|
||||
{sumImpl<short , double, 1>, sumImpl<short , double, 2>, sumImpl<short , double, 3>, sumImpl<short , double, 4>},
|
||||
{sumImpl<int , double, 1>, sumImpl<int , double, 2>, sumImpl<int , double, 3>, sumImpl<int , double, 4>},
|
||||
{sumImpl<float , double, 1>, sumImpl<float , double, 2>, sumImpl<float , double, 3>, sumImpl<float , double, 4>},
|
||||
{sumImpl<double, double, 1>, sumImpl<double, double, 2>, sumImpl<double, double, 3>, sumImpl<double, double, 4>}
|
||||
};
|
||||
|
||||
GpuMat src = _src.getGpuMat();
|
||||
GpuMat mask = _mask.getGpuMat();
|
||||
const GpuMat src = getInputMat(_src, stream);
|
||||
const GpuMat mask = getInputMat(_mask, stream);
|
||||
|
||||
CV_DbgAssert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == src.size()) );
|
||||
CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == src.size()) );
|
||||
|
||||
const func_t func = funcs[src.depth()][src.channels() - 1];
|
||||
const int src_depth = src.depth();
|
||||
const int channels = src.channels();
|
||||
|
||||
return func(src, mask, buf);
|
||||
GpuMat dst = getOutputMat(_dst, 1, 1, CV_64FC(channels), stream);
|
||||
|
||||
const func_t func = funcs[src_depth][channels - 1];
|
||||
func(src, dst, mask, stream);
|
||||
|
||||
syncOutput(dst, _dst, stream);
|
||||
}
|
||||
|
||||
cv::Scalar cv::cuda::absSum(InputArray _src, InputArray _mask, GpuMat& buf)
|
||||
cv::Scalar cv::cuda::sum(InputArray _src, InputArray _mask)
|
||||
{
|
||||
typedef cv::Scalar (*func_t)(const GpuMat& _src, const GpuMat& mask, GpuMat& _buf);
|
||||
Stream& stream = Stream::Null();
|
||||
|
||||
HostMem dst;
|
||||
calcSum(_src, dst, _mask, stream);
|
||||
|
||||
stream.waitForCompletion();
|
||||
|
||||
cv::Scalar val;
|
||||
dst.createMatHeader().convertTo(cv::Mat(dst.size(), CV_64FC(dst.channels()), val.val), CV_64F);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void cv::cuda::calcAbsSum(InputArray _src, OutputArray _dst, InputArray _mask, Stream& stream)
|
||||
{
|
||||
typedef void (*func_t)(const GpuMat& _src, GpuMat& _dst, const GpuMat& mask, Stream& stream);
|
||||
static const func_t funcs[7][4] =
|
||||
{
|
||||
{sumAbsImpl<uchar , uint , 1>, sumAbsImpl<uchar , uint , 2>, sumAbsImpl<uchar , uint , 3>, sumAbsImpl<uchar , uint , 4>},
|
||||
{sumAbsImpl<schar , int , 1>, sumAbsImpl<schar , int , 2>, sumAbsImpl<schar , int , 3>, sumAbsImpl<schar , int , 4>},
|
||||
{sumAbsImpl<ushort, uint , 1>, sumAbsImpl<ushort, uint , 2>, sumAbsImpl<ushort, uint , 3>, sumAbsImpl<ushort, uint , 4>},
|
||||
{sumAbsImpl<short , int , 1>, sumAbsImpl<short , int , 2>, sumAbsImpl<short , int , 3>, sumAbsImpl<short , int , 4>},
|
||||
{sumAbsImpl<int , int , 1>, sumAbsImpl<int , int , 2>, sumAbsImpl<int , int , 3>, sumAbsImpl<int , int , 4>},
|
||||
{sumAbsImpl<float , float , 1>, sumAbsImpl<float , float , 2>, sumAbsImpl<float , float , 3>, sumAbsImpl<float , float , 4>},
|
||||
{sumAbsImpl<uchar , double, 1>, sumAbsImpl<uchar , double, 2>, sumAbsImpl<uchar , double, 3>, sumAbsImpl<uchar , double, 4>},
|
||||
{sumAbsImpl<schar , double, 1>, sumAbsImpl<schar , double, 2>, sumAbsImpl<schar , double, 3>, sumAbsImpl<schar , double, 4>},
|
||||
{sumAbsImpl<ushort, double, 1>, sumAbsImpl<ushort, double, 2>, sumAbsImpl<ushort, double, 3>, sumAbsImpl<ushort, double, 4>},
|
||||
{sumAbsImpl<short , double, 1>, sumAbsImpl<short , double, 2>, sumAbsImpl<short , double, 3>, sumAbsImpl<short , double, 4>},
|
||||
{sumAbsImpl<int , double, 1>, sumAbsImpl<int , double, 2>, sumAbsImpl<int , double, 3>, sumAbsImpl<int , double, 4>},
|
||||
{sumAbsImpl<float , double, 1>, sumAbsImpl<float , double, 2>, sumAbsImpl<float , double, 3>, sumAbsImpl<float , double, 4>},
|
||||
{sumAbsImpl<double, double, 1>, sumAbsImpl<double, double, 2>, sumAbsImpl<double, double, 3>, sumAbsImpl<double, double, 4>}
|
||||
};
|
||||
|
||||
GpuMat src = _src.getGpuMat();
|
||||
GpuMat mask = _mask.getGpuMat();
|
||||
const GpuMat src = getInputMat(_src, stream);
|
||||
const GpuMat mask = getInputMat(_mask, stream);
|
||||
|
||||
CV_DbgAssert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == src.size()) );
|
||||
CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == src.size()) );
|
||||
|
||||
const func_t func = funcs[src.depth()][src.channels() - 1];
|
||||
const int src_depth = src.depth();
|
||||
const int channels = src.channels();
|
||||
|
||||
return func(src, mask, buf);
|
||||
GpuMat dst = getOutputMat(_dst, 1, 1, CV_64FC(channels), stream);
|
||||
|
||||
const func_t func = funcs[src_depth][channels - 1];
|
||||
func(src, dst, mask, stream);
|
||||
|
||||
syncOutput(dst, _dst, stream);
|
||||
}
|
||||
|
||||
cv::Scalar cv::cuda::sqrSum(InputArray _src, InputArray _mask, GpuMat& buf)
|
||||
cv::Scalar cv::cuda::absSum(InputArray _src, InputArray _mask)
|
||||
{
|
||||
typedef cv::Scalar (*func_t)(const GpuMat& _src, const GpuMat& mask, GpuMat& _buf);
|
||||
Stream& stream = Stream::Null();
|
||||
|
||||
HostMem dst;
|
||||
calcAbsSum(_src, dst, _mask, stream);
|
||||
|
||||
stream.waitForCompletion();
|
||||
|
||||
cv::Scalar val;
|
||||
dst.createMatHeader().convertTo(cv::Mat(dst.size(), CV_64FC(dst.channels()), val.val), CV_64F);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void cv::cuda::calcSqrSum(InputArray _src, OutputArray _dst, InputArray _mask, Stream& stream)
|
||||
{
|
||||
typedef void (*func_t)(const GpuMat& _src, GpuMat& _dst, const GpuMat& mask, Stream& stream);
|
||||
static const func_t funcs[7][4] =
|
||||
{
|
||||
{sumSqrImpl<uchar , double, 1>, sumSqrImpl<uchar , double, 2>, sumSqrImpl<uchar , double, 3>, sumSqrImpl<uchar , double, 4>},
|
||||
@@ -181,14 +208,35 @@ cv::Scalar cv::cuda::sqrSum(InputArray _src, InputArray _mask, GpuMat& buf)
|
||||
{sumSqrImpl<double, double, 1>, sumSqrImpl<double, double, 2>, sumSqrImpl<double, double, 3>, sumSqrImpl<double, double, 4>}
|
||||
};
|
||||
|
||||
GpuMat src = _src.getGpuMat();
|
||||
GpuMat mask = _mask.getGpuMat();
|
||||
const GpuMat src = getInputMat(_src, stream);
|
||||
const GpuMat mask = getInputMat(_mask, stream);
|
||||
|
||||
CV_DbgAssert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == src.size()) );
|
||||
CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == src.size()) );
|
||||
|
||||
const func_t func = funcs[src.depth()][src.channels() - 1];
|
||||
const int src_depth = src.depth();
|
||||
const int channels = src.channels();
|
||||
|
||||
return func(src, mask, buf);
|
||||
GpuMat dst = getOutputMat(_dst, 1, 1, CV_64FC(channels), stream);
|
||||
|
||||
const func_t func = funcs[src_depth][channels - 1];
|
||||
func(src, dst, mask, stream);
|
||||
|
||||
syncOutput(dst, _dst, stream);
|
||||
}
|
||||
|
||||
cv::Scalar cv::cuda::sqrSum(InputArray _src, InputArray _mask)
|
||||
{
|
||||
Stream& stream = Stream::Null();
|
||||
|
||||
HostMem dst;
|
||||
calcSqrSum(_src, dst, _mask, stream);
|
||||
|
||||
stream.waitForCompletion();
|
||||
|
||||
cv::Scalar val;
|
||||
dst.createMatHeader().convertTo(cv::Mat(dst.size(), CV_64FC(dst.channels()), val.val), CV_64F);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -47,110 +47,106 @@ using namespace cv::cuda;
|
||||
|
||||
#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER)
|
||||
|
||||
double cv::cuda::norm(InputArray, int, InputArray, GpuMat&) { throw_no_cuda(); return 0.0; }
|
||||
double cv::cuda::norm(InputArray, InputArray, GpuMat&, int) { throw_no_cuda(); return 0.0; }
|
||||
double cv::cuda::norm(InputArray, int, InputArray) { throw_no_cuda(); return 0.0; }
|
||||
void cv::cuda::calcNorm(InputArray, OutputArray, int, InputArray, Stream&) { throw_no_cuda(); }
|
||||
double cv::cuda::norm(InputArray, InputArray, int) { throw_no_cuda(); return 0.0; }
|
||||
void cv::cuda::calcNormDiff(InputArray, InputArray, OutputArray, int, Stream&) { throw_no_cuda(); }
|
||||
|
||||
Scalar cv::cuda::sum(InputArray, InputArray, GpuMat&) { throw_no_cuda(); return Scalar(); }
|
||||
Scalar cv::cuda::absSum(InputArray, InputArray, GpuMat&) { throw_no_cuda(); return Scalar(); }
|
||||
Scalar cv::cuda::sqrSum(InputArray, InputArray, GpuMat&) { throw_no_cuda(); return Scalar(); }
|
||||
Scalar cv::cuda::sum(InputArray, InputArray) { throw_no_cuda(); return Scalar(); }
|
||||
void cv::cuda::calcSum(InputArray, OutputArray, InputArray, Stream&) { throw_no_cuda(); }
|
||||
Scalar cv::cuda::absSum(InputArray, InputArray) { throw_no_cuda(); return Scalar(); }
|
||||
void cv::cuda::calcAbsSum(InputArray, OutputArray, InputArray, Stream&) { throw_no_cuda(); }
|
||||
Scalar cv::cuda::sqrSum(InputArray, InputArray) { throw_no_cuda(); return Scalar(); }
|
||||
void cv::cuda::calcSqrSum(InputArray, OutputArray, InputArray, Stream&) { throw_no_cuda(); }
|
||||
|
||||
void cv::cuda::minMax(InputArray, double*, double*, InputArray, GpuMat&) { throw_no_cuda(); }
|
||||
void cv::cuda::minMaxLoc(InputArray, double*, double*, Point*, Point*, InputArray, GpuMat&, GpuMat&) { throw_no_cuda(); }
|
||||
void cv::cuda::minMax(InputArray, double*, double*, InputArray) { throw_no_cuda(); }
|
||||
void cv::cuda::findMinMax(InputArray, OutputArray, InputArray, Stream&) { throw_no_cuda(); }
|
||||
void cv::cuda::minMaxLoc(InputArray, double*, double*, Point*, Point*, InputArray) { throw_no_cuda(); }
|
||||
void cv::cuda::findMinMaxLoc(InputArray, OutputArray, OutputArray, InputArray, Stream&) { throw_no_cuda(); }
|
||||
|
||||
int cv::cuda::countNonZero(InputArray, GpuMat&) { throw_no_cuda(); return 0; }
|
||||
int cv::cuda::countNonZero(InputArray) { throw_no_cuda(); return 0; }
|
||||
void cv::cuda::countNonZero(InputArray, OutputArray, Stream&) { throw_no_cuda(); }
|
||||
|
||||
void cv::cuda::reduce(InputArray, OutputArray, int, int, int, Stream&) { throw_no_cuda(); }
|
||||
|
||||
void cv::cuda::meanStdDev(InputArray, Scalar&, Scalar&, GpuMat&) { throw_no_cuda(); }
|
||||
void cv::cuda::meanStdDev(InputArray, Scalar&, Scalar&) { throw_no_cuda(); }
|
||||
void cv::cuda::meanStdDev(InputArray, OutputArray, Stream&) { throw_no_cuda(); }
|
||||
|
||||
void cv::cuda::rectStdDev(InputArray, InputArray, OutputArray, Rect, Stream&) { throw_no_cuda(); }
|
||||
|
||||
void cv::cuda::normalize(InputArray, OutputArray, double, double, int, int, InputArray, GpuMat&, GpuMat&) { throw_no_cuda(); }
|
||||
void cv::cuda::normalize(InputArray, OutputArray, double, double, int, int, InputArray, Stream&) { throw_no_cuda(); }
|
||||
|
||||
void cv::cuda::integral(InputArray, OutputArray, GpuMat&, Stream&) { throw_no_cuda(); }
|
||||
void cv::cuda::sqrIntegral(InputArray, OutputArray, GpuMat&, Stream&) { throw_no_cuda(); }
|
||||
void cv::cuda::integral(InputArray, OutputArray, Stream&) { throw_no_cuda(); }
|
||||
void cv::cuda::sqrIntegral(InputArray, OutputArray, Stream&) { throw_no_cuda(); }
|
||||
|
||||
#else
|
||||
|
||||
namespace
|
||||
{
|
||||
class DeviceBuffer
|
||||
{
|
||||
public:
|
||||
explicit DeviceBuffer(int count_ = 1) : count(count_)
|
||||
{
|
||||
cudaSafeCall( cudaMalloc(&pdev, count * sizeof(double)) );
|
||||
}
|
||||
~DeviceBuffer()
|
||||
{
|
||||
cudaSafeCall( cudaFree(pdev) );
|
||||
}
|
||||
|
||||
operator double*() {return pdev;}
|
||||
|
||||
void download(double* hptr)
|
||||
{
|
||||
double hbuf;
|
||||
cudaSafeCall( cudaMemcpy(&hbuf, pdev, sizeof(double), cudaMemcpyDeviceToHost) );
|
||||
*hptr = hbuf;
|
||||
}
|
||||
void download(double** hptrs)
|
||||
{
|
||||
AutoBuffer<double, 2 * sizeof(double)> hbuf(count);
|
||||
cudaSafeCall( cudaMemcpy((void*)hbuf, pdev, count * sizeof(double), cudaMemcpyDeviceToHost) );
|
||||
for (int i = 0; i < count; ++i)
|
||||
*hptrs[i] = hbuf[i];
|
||||
}
|
||||
|
||||
private:
|
||||
double* pdev;
|
||||
int count;
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// norm
|
||||
|
||||
double cv::cuda::norm(InputArray _src, int normType, InputArray _mask, GpuMat& buf)
|
||||
{
|
||||
GpuMat src = _src.getGpuMat();
|
||||
GpuMat mask = _mask.getGpuMat();
|
||||
namespace cv { namespace cuda { namespace internal {
|
||||
|
||||
void normL2(cv::InputArray _src, cv::OutputArray _dst, cv::InputArray _mask, Stream& stream);
|
||||
|
||||
void findMaxAbs(cv::InputArray _src, cv::OutputArray _dst, cv::InputArray _mask, Stream& stream);
|
||||
|
||||
}}}
|
||||
|
||||
void cv::cuda::calcNorm(InputArray _src, OutputArray dst, int normType, InputArray mask, Stream& stream)
|
||||
{
|
||||
CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 );
|
||||
CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == src.size() && src.channels() == 1) );
|
||||
|
||||
GpuMat src = getInputMat(_src, stream);
|
||||
|
||||
GpuMat src_single_channel = src.reshape(1);
|
||||
|
||||
if (normType == NORM_L1)
|
||||
return cuda::absSum(src_single_channel, mask, buf)[0];
|
||||
{
|
||||
calcAbsSum(src_single_channel, dst, mask, stream);
|
||||
}
|
||||
else if (normType == NORM_L2)
|
||||
{
|
||||
internal::normL2(src_single_channel, dst, mask, stream);
|
||||
}
|
||||
else // NORM_INF
|
||||
{
|
||||
internal::findMaxAbs(src_single_channel, dst, mask, stream);
|
||||
}
|
||||
}
|
||||
|
||||
if (normType == NORM_L2)
|
||||
return std::sqrt(cuda::sqrSum(src_single_channel, mask, buf)[0]);
|
||||
double cv::cuda::norm(InputArray _src, int normType, InputArray _mask)
|
||||
{
|
||||
Stream& stream = Stream::Null();
|
||||
|
||||
// NORM_INF
|
||||
double min_val, max_val;
|
||||
cuda::minMax(src_single_channel, &min_val, &max_val, mask, buf);
|
||||
return std::max(std::abs(min_val), std::abs(max_val));
|
||||
HostMem dst;
|
||||
calcNorm(_src, dst, normType, _mask, stream);
|
||||
|
||||
stream.waitForCompletion();
|
||||
|
||||
double val;
|
||||
dst.createMatHeader().convertTo(Mat(1, 1, CV_64FC1, &val), CV_64F);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// meanStdDev
|
||||
|
||||
void cv::cuda::meanStdDev(InputArray _src, Scalar& mean, Scalar& stddev, GpuMat& buf)
|
||||
void cv::cuda::meanStdDev(InputArray _src, OutputArray _dst, Stream& stream)
|
||||
{
|
||||
GpuMat src = _src.getGpuMat();
|
||||
if (!deviceSupports(FEATURE_SET_COMPUTE_13))
|
||||
CV_Error(cv::Error::StsNotImplemented, "Not sufficient compute capebility");
|
||||
|
||||
const GpuMat src = getInputMat(_src, stream);
|
||||
|
||||
CV_Assert( src.type() == CV_8UC1 );
|
||||
|
||||
if (!deviceSupports(FEATURE_SET_COMPUTE_13))
|
||||
CV_Error(cv::Error::StsNotImplemented, "Not sufficient compute capebility");
|
||||
GpuMat dst = getOutputMat(_dst, 1, 2, CV_64FC1, stream);
|
||||
|
||||
NppiSize sz;
|
||||
sz.width = src.cols;
|
||||
sz.height = src.rows;
|
||||
|
||||
DeviceBuffer dbuf(2);
|
||||
|
||||
int bufSize;
|
||||
#if (CUDA_VERSION <= 4020)
|
||||
nppSafeCall( nppiMeanStdDev8uC1RGetBufferHostSize(sz, &bufSize) );
|
||||
@@ -158,14 +154,30 @@ void cv::cuda::meanStdDev(InputArray _src, Scalar& mean, Scalar& stddev, GpuMat&
|
||||
nppSafeCall( nppiMeanStdDevGetBufferHostSize_8u_C1R(sz, &bufSize) );
|
||||
#endif
|
||||
|
||||
ensureSizeIsEnough(1, bufSize, CV_8UC1, buf);
|
||||
BufferPool pool(stream);
|
||||
GpuMat buf = pool.getBuffer(1, bufSize, CV_8UC1);
|
||||
|
||||
nppSafeCall( nppiMean_StdDev_8u_C1R(src.ptr<Npp8u>(), static_cast<int>(src.step), sz, buf.ptr<Npp8u>(), dbuf, (double*)dbuf + 1) );
|
||||
NppStreamHandler h(StreamAccessor::getStream(stream));
|
||||
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
nppSafeCall( nppiMean_StdDev_8u_C1R(src.ptr<Npp8u>(), static_cast<int>(src.step), sz, buf.ptr<Npp8u>(), dst.ptr<Npp64f>(), dst.ptr<Npp64f>() + 1) );
|
||||
|
||||
double* ptrs[2] = {mean.val, stddev.val};
|
||||
dbuf.download(ptrs);
|
||||
syncOutput(dst, _dst, stream);
|
||||
}
|
||||
|
||||
void cv::cuda::meanStdDev(InputArray _src, Scalar& mean, Scalar& stddev)
|
||||
{
|
||||
Stream& stream = Stream::Null();
|
||||
|
||||
HostMem dst;
|
||||
meanStdDev(_src, dst, stream);
|
||||
|
||||
stream.waitForCompletion();
|
||||
|
||||
double vals[2];
|
||||
dst.createMatHeader().copyTo(Mat(1, 2, CV_64FC1, &vals[0]));
|
||||
|
||||
mean = Scalar(vals[0]);
|
||||
stddev = Scalar(vals[1]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -173,13 +185,12 @@ void cv::cuda::meanStdDev(InputArray _src, Scalar& mean, Scalar& stddev, GpuMat&
|
||||
|
||||
void cv::cuda::rectStdDev(InputArray _src, InputArray _sqr, OutputArray _dst, Rect rect, Stream& _stream)
|
||||
{
|
||||
GpuMat src = _src.getGpuMat();
|
||||
GpuMat sqr = _sqr.getGpuMat();
|
||||
GpuMat src = getInputMat(_src, _stream);
|
||||
GpuMat sqr = getInputMat(_sqr, _stream);
|
||||
|
||||
CV_Assert( src.type() == CV_32SC1 && sqr.type() == CV_64FC1 );
|
||||
|
||||
_dst.create(src.size(), CV_32FC1);
|
||||
GpuMat dst = _dst.getGpuMat();
|
||||
GpuMat dst = getOutputMat(_dst, src.size(), CV_32FC1, _stream);
|
||||
|
||||
NppiSize sz;
|
||||
sz.width = src.cols;
|
||||
@@ -200,45 +211,8 @@ void cv::cuda::rectStdDev(InputArray _src, InputArray _sqr, OutputArray _dst, Re
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// normalize
|
||||
|
||||
void cv::cuda::normalize(InputArray _src, OutputArray dst, double a, double b, int norm_type, int dtype, InputArray mask, GpuMat& norm_buf, GpuMat& cvt_buf)
|
||||
{
|
||||
GpuMat src = _src.getGpuMat();
|
||||
|
||||
double scale = 1, shift = 0;
|
||||
|
||||
if (norm_type == NORM_MINMAX)
|
||||
{
|
||||
double smin = 0, smax = 0;
|
||||
double dmin = std::min(a, b), dmax = std::max(a, b);
|
||||
cuda::minMax(src, &smin, &smax, mask, norm_buf);
|
||||
scale = (dmax - dmin) * (smax - smin > std::numeric_limits<double>::epsilon() ? 1.0 / (smax - smin) : 0.0);
|
||||
shift = dmin - smin * scale;
|
||||
}
|
||||
else if (norm_type == NORM_L2 || norm_type == NORM_L1 || norm_type == NORM_INF)
|
||||
{
|
||||
scale = cuda::norm(src, norm_type, mask, norm_buf);
|
||||
scale = scale > std::numeric_limits<double>::epsilon() ? a / scale : 0.0;
|
||||
shift = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, "Unknown/unsupported norm type");
|
||||
}
|
||||
|
||||
if (mask.empty())
|
||||
{
|
||||
src.convertTo(dst, dtype, scale, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
src.convertTo(cvt_buf, dtype, scale, shift);
|
||||
cvt_buf.copyTo(dst, mask);
|
||||
}
|
||||
syncOutput(dst, _dst, _stream);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user