mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 08:13:04 +04:00
Merge branch 'master' of https://github.com/Itseez/opencv
Conflicts: modules/features2d/include/opencv2/features2d.hpp modules/features2d/src/freak.cpp modules/features2d/src/stardetector.cpp
This commit is contained in:
+105
-23
@@ -41,6 +41,7 @@
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
@@ -352,15 +353,83 @@ inline int getAccTabIdx(int sdepth, int ddepth)
|
||||
sdepth == CV_64F && ddepth == CV_64F ? 6 : -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
enum
|
||||
{
|
||||
ACCUMULATE = 0,
|
||||
ACCUMULATE_SQUARE = 1,
|
||||
ACCUMULATE_PRODUCT = 2,
|
||||
ACCUMULATE_WEIGHTED = 3
|
||||
};
|
||||
|
||||
static bool ocl_accumulate( InputArray _src, InputArray _src2, InputOutputArray _dst, double alpha,
|
||||
InputArray _mask, int op_type )
|
||||
{
|
||||
CV_Assert(op_type == ACCUMULATE || op_type == ACCUMULATE_SQUARE ||
|
||||
op_type == ACCUMULATE_PRODUCT || op_type == ACCUMULATE_WEIGHTED);
|
||||
|
||||
int stype = _src.type(), cn = CV_MAT_CN(stype);
|
||||
int sdepth = CV_MAT_DEPTH(stype), ddepth = _dst.depth();
|
||||
|
||||
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0,
|
||||
haveMask = !_mask.empty();
|
||||
|
||||
if (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F))
|
||||
return false;
|
||||
|
||||
const char * const opMap[4] = { "ACCUMULATE", "ACCUMULATE_SQUARE", "ACCUMULATE_PRODUCT",
|
||||
"ACCUMULATE_WEIGHTED" };
|
||||
|
||||
ocl::Kernel k("accumulate", ocl::imgproc::accumulate_oclsrc,
|
||||
format("-D %s%s -D srcT=%s -D cn=%d -D dstT=%s%s",
|
||||
opMap[op_type], haveMask ? " -D HAVE_MASK" : "",
|
||||
ocl::typeToStr(sdepth), cn, ocl::typeToStr(ddepth),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : ""));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat src = _src.getUMat(), src2 = _src2.getUMat(), dst = _dst.getUMat(), mask = _mask.getUMat();
|
||||
|
||||
ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
|
||||
src2arg = ocl::KernelArg::ReadOnlyNoSize(src2),
|
||||
dstarg = ocl::KernelArg::ReadWrite(dst),
|
||||
maskarg = ocl::KernelArg::ReadOnlyNoSize(mask);
|
||||
|
||||
int argidx = k.set(0, srcarg);
|
||||
if (op_type == ACCUMULATE_PRODUCT)
|
||||
argidx = k.set(argidx, src2arg);
|
||||
argidx = k.set(argidx, dstarg);
|
||||
if (op_type == ACCUMULATE_WEIGHTED)
|
||||
{
|
||||
if (ddepth == CV_32F)
|
||||
argidx = k.set(argidx, (float)alpha);
|
||||
else
|
||||
argidx = k.set(argidx, alpha);
|
||||
}
|
||||
if (haveMask)
|
||||
k.set(argidx, maskarg);
|
||||
|
||||
size_t globalsize[2] = { src.cols, src.rows };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void cv::accumulate( InputArray _src, InputOutputArray _dst, InputArray _mask )
|
||||
{
|
||||
Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
|
||||
int sdepth = src.depth(), ddepth = dst.depth(), cn = src.channels();
|
||||
int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype);
|
||||
int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype);
|
||||
|
||||
CV_Assert( dst.size == src.size && dst.channels() == cn );
|
||||
CV_Assert( mask.empty() || (mask.size == src.size && mask.type() == CV_8U) );
|
||||
CV_Assert( _src.sameSize(_dst) && dcn == scn );
|
||||
CV_Assert( _mask.empty() || (_src.sameSize(_mask) && _mask.type() == CV_8U) );
|
||||
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_accumulate(_src, noArray(), _dst, 0.0, _mask, ACCUMULATE))
|
||||
|
||||
Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
|
||||
|
||||
int fidx = getAccTabIdx(sdepth, ddepth);
|
||||
AccFunc func = fidx >= 0 ? accTab[fidx] : 0;
|
||||
@@ -372,17 +441,21 @@ void cv::accumulate( InputArray _src, InputOutputArray _dst, InputArray _mask )
|
||||
int len = (int)it.size;
|
||||
|
||||
for( size_t i = 0; i < it.nplanes; i++, ++it )
|
||||
func(ptrs[0], ptrs[1], ptrs[2], len, cn);
|
||||
func(ptrs[0], ptrs[1], ptrs[2], len, scn);
|
||||
}
|
||||
|
||||
|
||||
void cv::accumulateSquare( InputArray _src, InputOutputArray _dst, InputArray _mask )
|
||||
{
|
||||
Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
|
||||
int sdepth = src.depth(), ddepth = dst.depth(), cn = src.channels();
|
||||
int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype);
|
||||
int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype);
|
||||
|
||||
CV_Assert( dst.size == src.size && dst.channels() == cn );
|
||||
CV_Assert( mask.empty() || (mask.size == src.size && mask.type() == CV_8U) );
|
||||
CV_Assert( _src.sameSize(_dst) && dcn == scn );
|
||||
CV_Assert( _mask.empty() || (_src.sameSize(_mask) && _mask.type() == CV_8U) );
|
||||
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_accumulate(_src, noArray(), _dst, 0.0, _mask, ACCUMULATE_SQUARE))
|
||||
|
||||
Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
|
||||
|
||||
int fidx = getAccTabIdx(sdepth, ddepth);
|
||||
AccFunc func = fidx >= 0 ? accSqrTab[fidx] : 0;
|
||||
@@ -394,18 +467,23 @@ void cv::accumulateSquare( InputArray _src, InputOutputArray _dst, InputArray _m
|
||||
int len = (int)it.size;
|
||||
|
||||
for( size_t i = 0; i < it.nplanes; i++, ++it )
|
||||
func(ptrs[0], ptrs[1], ptrs[2], len, cn);
|
||||
func(ptrs[0], ptrs[1], ptrs[2], len, scn);
|
||||
}
|
||||
|
||||
void cv::accumulateProduct( InputArray _src1, InputArray _src2,
|
||||
InputOutputArray _dst, InputArray _mask )
|
||||
{
|
||||
Mat src1 = _src1.getMat(), src2 = _src2.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
|
||||
int sdepth = src1.depth(), ddepth = dst.depth(), cn = src1.channels();
|
||||
int stype = _src1.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype);
|
||||
int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype);
|
||||
|
||||
CV_Assert( src2.size && src1.size && src2.type() == src1.type() );
|
||||
CV_Assert( dst.size == src1.size && dst.channels() == cn );
|
||||
CV_Assert( mask.empty() || (mask.size == src1.size && mask.type() == CV_8U) );
|
||||
CV_Assert( _src1.sameSize(_src2) && stype == _src2.type() );
|
||||
CV_Assert( _src1.sameSize(_dst) && dcn == scn );
|
||||
CV_Assert( _mask.empty() || (_src1.sameSize(_mask) && _mask.type() == CV_8U) );
|
||||
|
||||
CV_OCL_RUN(_src1.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_accumulate(_src1, _src2, _dst, 0.0, _mask, ACCUMULATE_PRODUCT))
|
||||
|
||||
Mat src1 = _src1.getMat(), src2 = _src2.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
|
||||
|
||||
int fidx = getAccTabIdx(sdepth, ddepth);
|
||||
AccProdFunc func = fidx >= 0 ? accProdTab[fidx] : 0;
|
||||
@@ -417,18 +495,22 @@ void cv::accumulateProduct( InputArray _src1, InputArray _src2,
|
||||
int len = (int)it.size;
|
||||
|
||||
for( size_t i = 0; i < it.nplanes; i++, ++it )
|
||||
func(ptrs[0], ptrs[1], ptrs[2], ptrs[3], len, cn);
|
||||
func(ptrs[0], ptrs[1], ptrs[2], ptrs[3], len, scn);
|
||||
}
|
||||
|
||||
|
||||
void cv::accumulateWeighted( InputArray _src, InputOutputArray _dst,
|
||||
double alpha, InputArray _mask )
|
||||
{
|
||||
Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
|
||||
int sdepth = src.depth(), ddepth = dst.depth(), cn = src.channels();
|
||||
int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype);
|
||||
int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype);
|
||||
|
||||
CV_Assert( dst.size == src.size && dst.channels() == cn );
|
||||
CV_Assert( mask.empty() || (mask.size == src.size && mask.type() == CV_8U) );
|
||||
CV_Assert( _src.sameSize(_dst) && dcn == scn );
|
||||
CV_Assert( _mask.empty() || (_src.sameSize(_mask) && _mask.type() == CV_8U) );
|
||||
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_accumulate(_src, noArray(), _dst, alpha, _mask, ACCUMULATE_WEIGHTED))
|
||||
|
||||
Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
|
||||
|
||||
int fidx = getAccTabIdx(sdepth, ddepth);
|
||||
AccWFunc func = fidx >= 0 ? accWTab[fidx] : 0;
|
||||
@@ -440,7 +522,7 @@ void cv::accumulateWeighted( InputArray _src, InputOutputArray _dst,
|
||||
int len = (int)it.size;
|
||||
|
||||
for( size_t i = 0; i < it.nplanes; i++, ++it )
|
||||
func(ptrs[0], ptrs[1], ptrs[2], len, cn, alpha);
|
||||
func(ptrs[0], ptrs[1], ptrs[2], len, scn, alpha);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -91,6 +91,8 @@ private:
|
||||
Mat * dst;
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_blendLinear( InputArray _src1, InputArray _src2, InputArray _weights1, InputArray _weights2, OutputArray _dst )
|
||||
{
|
||||
int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
@@ -113,6 +115,8 @@ static bool ocl_blendLinear( InputArray _src1, InputArray _src2, InputArray _wei
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void cv::blendLinear( InputArray _src1, InputArray _src2, InputArray _weights1, InputArray _weights2, OutputArray _dst )
|
||||
@@ -126,8 +130,8 @@ void cv::blendLinear( InputArray _src1, InputArray _src2, InputArray _weights1,
|
||||
|
||||
_dst.create(size, type);
|
||||
|
||||
if (ocl::useOpenCL() && _dst.isUMat() && ocl_blendLinear(_src1, _src2, _weights1, _weights2, _dst))
|
||||
return;
|
||||
CV_OCL_RUN(_dst.isUMat(),
|
||||
ocl_blendLinear(_src1, _src2, _weights1, _weights2, _dst))
|
||||
|
||||
Mat src1 = _src1.getMat(), src2 = _src2.getMat(), weights1 = _weights1.getMat(),
|
||||
weights2 = _weights2.getMat(), dst = _dst.getMat();
|
||||
|
||||
+165
-10
@@ -40,16 +40,20 @@
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
/*
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
#define USE_IPP_CANNY 1
|
||||
#else
|
||||
#undef USE_IPP_CANNY
|
||||
#endif
|
||||
*/
|
||||
|
||||
#ifdef USE_IPP_CANNY
|
||||
namespace cv
|
||||
{
|
||||
|
||||
#ifdef USE_IPP_CANNY
|
||||
static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high)
|
||||
{
|
||||
int size = 0, size1 = 0;
|
||||
@@ -82,22 +86,169 @@ static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float high_thresh,
|
||||
int aperture_size, bool L2gradient, int cn, const Size & size)
|
||||
{
|
||||
UMat dx(size, CV_16SC(cn)), dy(size, CV_16SC(cn));
|
||||
|
||||
if (L2gradient)
|
||||
{
|
||||
low_thresh = std::min(32767.0f, low_thresh);
|
||||
high_thresh = std::min(32767.0f, high_thresh);
|
||||
|
||||
if (low_thresh > 0) low_thresh *= low_thresh;
|
||||
if (high_thresh > 0) high_thresh *= high_thresh;
|
||||
}
|
||||
int low = cvFloor(low_thresh), high = cvFloor(high_thresh);
|
||||
Size esize(size.width + 2, size.height + 2);
|
||||
|
||||
UMat mag;
|
||||
size_t globalsize[2] = { size.width * cn, size.height }, localsize[2] = { 16, 16 };
|
||||
|
||||
if (aperture_size == 3 && !_src.isSubmatrix())
|
||||
{
|
||||
// Sobel calculation
|
||||
ocl::Kernel calcSobelRowPassKernel("calcSobelRowPass", ocl::imgproc::canny_oclsrc);
|
||||
if (calcSobelRowPassKernel.empty())
|
||||
return false;
|
||||
|
||||
UMat src = _src.getUMat(), dxBuf(size, CV_16SC(cn)), dyBuf(size, CV_16SC(cn));
|
||||
calcSobelRowPassKernel.args(ocl::KernelArg::ReadOnly(src),
|
||||
ocl::KernelArg::WriteOnlyNoSize(dxBuf),
|
||||
ocl::KernelArg::WriteOnlyNoSize(dyBuf));
|
||||
|
||||
if (!calcSobelRowPassKernel.run(2, globalsize, localsize, false))
|
||||
return false;
|
||||
|
||||
// magnitude calculation
|
||||
ocl::Kernel magnitudeKernel("calcMagnitude_buf", ocl::imgproc::canny_oclsrc,
|
||||
L2gradient ? " -D L2GRAD" : "");
|
||||
if (magnitudeKernel.empty())
|
||||
return false;
|
||||
|
||||
mag = UMat(esize, CV_32SC(cn), Scalar::all(0));
|
||||
dx.create(size, CV_16SC(cn));
|
||||
dy.create(size, CV_16SC(cn));
|
||||
|
||||
magnitudeKernel.args(ocl::KernelArg::ReadOnlyNoSize(dxBuf), ocl::KernelArg::ReadOnlyNoSize(dyBuf),
|
||||
ocl::KernelArg::WriteOnlyNoSize(dx), ocl::KernelArg::WriteOnlyNoSize(dy),
|
||||
ocl::KernelArg::WriteOnlyNoSize(mag, cn), size.height, size.width);
|
||||
|
||||
if (!magnitudeKernel.run(2, globalsize, localsize, false))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
dx.create(size, CV_16SC(cn));
|
||||
dy.create(size, CV_16SC(cn));
|
||||
|
||||
Sobel(_src, dx, CV_16SC1, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
Sobel(_src, dy, CV_16SC1, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
|
||||
// magnitude calculation
|
||||
ocl::Kernel magnitudeKernel("calcMagnitude", ocl::imgproc::canny_oclsrc,
|
||||
L2gradient ? " -D L2GRAD" : "");
|
||||
if (magnitudeKernel.empty())
|
||||
return false;
|
||||
|
||||
mag = UMat(esize, CV_32SC(cn), Scalar::all(0));
|
||||
magnitudeKernel.args(ocl::KernelArg::ReadOnlyNoSize(dx), ocl::KernelArg::ReadOnlyNoSize(dy),
|
||||
ocl::KernelArg::WriteOnlyNoSize(mag, cn), size.height, size.width);
|
||||
|
||||
if (!magnitudeKernel.run(2, globalsize, NULL, false))
|
||||
return false;
|
||||
}
|
||||
|
||||
// map calculation
|
||||
ocl::Kernel calcMapKernel("calcMap", ocl::imgproc::canny_oclsrc);
|
||||
if (calcMapKernel.empty())
|
||||
return false;
|
||||
|
||||
UMat map(esize, CV_32SC(cn));
|
||||
calcMapKernel.args(ocl::KernelArg::ReadOnlyNoSize(dx), ocl::KernelArg::ReadOnlyNoSize(dy),
|
||||
ocl::KernelArg::ReadOnlyNoSize(mag), ocl::KernelArg::WriteOnlyNoSize(map, cn),
|
||||
size.height, size.width, low, high);
|
||||
|
||||
if (!calcMapKernel.run(2, globalsize, localsize, false))
|
||||
return false;
|
||||
|
||||
// local hysteresis thresholding
|
||||
ocl::Kernel edgesHysteresisLocalKernel("edgesHysteresisLocal", ocl::imgproc::canny_oclsrc);
|
||||
if (edgesHysteresisLocalKernel.empty())
|
||||
return false;
|
||||
|
||||
UMat stack(1, size.area(), CV_16UC2), counter(1, 1, CV_32SC1, Scalar::all(0));
|
||||
edgesHysteresisLocalKernel.args(ocl::KernelArg::ReadOnlyNoSize(map), ocl::KernelArg::PtrReadWrite(stack),
|
||||
ocl::KernelArg::PtrReadWrite(counter), size.height, size.width);
|
||||
if (!edgesHysteresisLocalKernel.run(2, globalsize, localsize, false))
|
||||
return false;
|
||||
|
||||
// global hysteresis thresholding
|
||||
UMat stack2(1, size.area(), CV_16UC2);
|
||||
int count;
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
ocl::Kernel edgesHysteresisGlobalKernel("edgesHysteresisGlobal", ocl::imgproc::canny_oclsrc);
|
||||
if (edgesHysteresisGlobalKernel.empty())
|
||||
return false;
|
||||
|
||||
{
|
||||
Mat _counter = counter.getMat(ACCESS_RW);
|
||||
count = _counter.at<int>(0, 0);
|
||||
if (count == 0)
|
||||
break;
|
||||
|
||||
_counter.at<int>(0, 0) = 0;
|
||||
}
|
||||
|
||||
edgesHysteresisGlobalKernel.args(ocl::KernelArg::ReadOnlyNoSize(map), ocl::KernelArg::PtrReadWrite(stack),
|
||||
ocl::KernelArg::PtrReadWrite(stack2), ocl::KernelArg::PtrReadWrite(counter),
|
||||
size.height, size.width, count);
|
||||
|
||||
#define divUp(total, grain) ((total + grain - 1) / grain)
|
||||
size_t localsize2[2] = { 128, 1 }, globalsize2[2] = { std::min(count, 65535) * 128, divUp(count, 65535) };
|
||||
#undef divUp
|
||||
|
||||
if (!edgesHysteresisGlobalKernel.run(2, globalsize2, localsize2, false))
|
||||
return false;
|
||||
|
||||
std::swap(stack, stack2);
|
||||
}
|
||||
|
||||
// get edges
|
||||
ocl::Kernel getEdgesKernel("getEdges", ocl::imgproc::canny_oclsrc);
|
||||
if (getEdgesKernel.empty())
|
||||
return false;
|
||||
|
||||
_dst.create(size, CV_8UC(cn));
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
getEdgesKernel.args(ocl::KernelArg::ReadOnlyNoSize(map), ocl::KernelArg::WriteOnly(dst));
|
||||
return getEdgesKernel.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void cv::Canny( InputArray _src, OutputArray _dst,
|
||||
double low_thresh, double high_thresh,
|
||||
int aperture_size, bool L2gradient )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
CV_Assert( src.depth() == CV_8U );
|
||||
const int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
const Size size = _src.size();
|
||||
|
||||
_dst.create(src.size(), CV_8U);
|
||||
Mat dst = _dst.getMat();
|
||||
CV_Assert( depth == CV_8U );
|
||||
_dst.create(size, CV_8U);
|
||||
|
||||
if (!L2gradient && (aperture_size & CV_CANNY_L2_GRADIENT) == CV_CANNY_L2_GRADIENT)
|
||||
{
|
||||
//backward compatibility
|
||||
// backward compatibility
|
||||
aperture_size &= ~CV_CANNY_L2_GRADIENT;
|
||||
L2gradient = true;
|
||||
}
|
||||
@@ -108,6 +259,11 @@ void cv::Canny( InputArray _src, OutputArray _dst,
|
||||
if (low_thresh > high_thresh)
|
||||
std::swap(low_thresh, high_thresh);
|
||||
|
||||
CV_OCL_RUN(_dst.isUMat() && cn == 1,
|
||||
ocl_Canny(_src, _dst, (float)low_thresh, (float)high_thresh, aperture_size, L2gradient, cn, size))
|
||||
|
||||
Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
if (tegra::canny(src, dst, low_thresh, high_thresh, aperture_size, L2gradient))
|
||||
return;
|
||||
@@ -119,12 +275,11 @@ void cv::Canny( InputArray _src, OutputArray _dst,
|
||||
return;
|
||||
#endif
|
||||
|
||||
const int cn = src.channels();
|
||||
Mat dx(src.rows, src.cols, CV_16SC(cn));
|
||||
Mat dy(src.rows, src.cols, CV_16SC(cn));
|
||||
|
||||
Sobel(src, dx, CV_16S, 1, 0, aperture_size, 1, 0, cv::BORDER_REPLICATE);
|
||||
Sobel(src, dy, CV_16S, 0, 1, aperture_size, 1, 0, cv::BORDER_REPLICATE);
|
||||
Sobel(src, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
Sobel(src, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE);
|
||||
|
||||
if (L2gradient)
|
||||
{
|
||||
|
||||
+126
-19
@@ -40,17 +40,97 @@
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// CLAHE
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace clahe
|
||||
{
|
||||
static bool calcLut(cv::InputArray _src, cv::OutputArray _dst,
|
||||
const int tilesX, const int tilesY, const cv::Size tileSize,
|
||||
const int clipLimit, const float lutScale)
|
||||
{
|
||||
cv::ocl::Kernel _k("calcLut", cv::ocl::imgproc::clahe_oclsrc);
|
||||
|
||||
bool is_cpu = cv::ocl::Device::getDefault().type() == cv::ocl::Device::TYPE_CPU;
|
||||
cv::String opts;
|
||||
if(is_cpu)
|
||||
opts = "-D CPU ";
|
||||
else
|
||||
opts = cv::format("-D WAVE_SIZE=%d", _k.preferedWorkGroupSizeMultiple());
|
||||
|
||||
cv::ocl::Kernel k("calcLut", cv::ocl::imgproc::clahe_oclsrc, opts);
|
||||
if(k.empty())
|
||||
return false;
|
||||
|
||||
cv::UMat src = _src.getUMat();
|
||||
_dst.create(tilesX * tilesY, 256, CV_8UC1);
|
||||
cv::UMat dst = _dst.getUMat();
|
||||
|
||||
int tile_size[2];
|
||||
tile_size[0] = tileSize.width;
|
||||
tile_size[1] = tileSize.height;
|
||||
|
||||
size_t localThreads[3] = { 32, 8, 1 };
|
||||
size_t globalThreads[3] = { tilesX * localThreads[0], tilesY * localThreads[1], 1 };
|
||||
|
||||
int idx = 0;
|
||||
idx = k.set(idx, cv::ocl::KernelArg::ReadOnlyNoSize(src));
|
||||
idx = k.set(idx, cv::ocl::KernelArg::WriteOnlyNoSize(dst));
|
||||
idx = k.set(idx, tile_size);
|
||||
idx = k.set(idx, tilesX);
|
||||
idx = k.set(idx, clipLimit);
|
||||
k.set(idx, lutScale);
|
||||
|
||||
return k.run(2, globalThreads, localThreads, false);
|
||||
}
|
||||
|
||||
static bool transform(cv::InputArray _src, cv::OutputArray _dst, cv::InputArray _lut,
|
||||
const int tilesX, const int tilesY, const cv::Size & tileSize)
|
||||
{
|
||||
|
||||
cv::ocl::Kernel k("transform", cv::ocl::imgproc::clahe_oclsrc);
|
||||
if(k.empty())
|
||||
return false;
|
||||
|
||||
int tile_size[2];
|
||||
tile_size[0] = tileSize.width;
|
||||
tile_size[1] = tileSize.height;
|
||||
|
||||
cv::UMat src = _src.getUMat();
|
||||
_dst.create(src.size(), src.type());
|
||||
cv::UMat dst = _dst.getUMat();
|
||||
cv::UMat lut = _lut.getUMat();
|
||||
|
||||
size_t localThreads[3] = { 32, 8, 1 };
|
||||
size_t globalThreads[3] = { src.cols, src.rows, 1 };
|
||||
|
||||
int idx = 0;
|
||||
idx = k.set(idx, cv::ocl::KernelArg::ReadOnlyNoSize(src));
|
||||
idx = k.set(idx, cv::ocl::KernelArg::WriteOnlyNoSize(dst));
|
||||
idx = k.set(idx, cv::ocl::KernelArg::ReadOnlyNoSize(lut));
|
||||
idx = k.set(idx, src.cols);
|
||||
idx = k.set(idx, src.rows);
|
||||
idx = k.set(idx, tile_size);
|
||||
idx = k.set(idx, tilesX);
|
||||
k.set(idx, tilesY);
|
||||
|
||||
return k.run(2, globalThreads, localThreads, false);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
class CLAHE_CalcLut_Body : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
CLAHE_CalcLut_Body(const cv::Mat& src, cv::Mat& lut, cv::Size tileSize, int tilesX, int tilesY, int clipLimit, float lutScale) :
|
||||
src_(src), lut_(lut), tileSize_(tileSize), tilesX_(tilesX), tilesY_(tilesY), clipLimit_(clipLimit), lutScale_(lutScale)
|
||||
CLAHE_CalcLut_Body(const cv::Mat& src, cv::Mat& lut, cv::Size tileSize, int tilesX, int clipLimit, float lutScale) :
|
||||
src_(src), lut_(lut), tileSize_(tileSize), tilesX_(tilesX), clipLimit_(clipLimit), lutScale_(lutScale)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -62,7 +142,6 @@ namespace
|
||||
|
||||
cv::Size tileSize_;
|
||||
int tilesX_;
|
||||
int tilesY_;
|
||||
int clipLimit_;
|
||||
float lutScale_;
|
||||
};
|
||||
@@ -242,6 +321,11 @@ namespace
|
||||
|
||||
cv::Mat srcExt_;
|
||||
cv::Mat lut_;
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
cv::UMat usrcExt_;
|
||||
cv::UMat ulut_;
|
||||
#endif
|
||||
};
|
||||
|
||||
CLAHE_Impl::CLAHE_Impl(double clipLimit, int tilesX, int tilesY) :
|
||||
@@ -256,31 +340,38 @@ namespace
|
||||
|
||||
void CLAHE_Impl::apply(cv::InputArray _src, cv::OutputArray _dst)
|
||||
{
|
||||
cv::Mat src = _src.getMat();
|
||||
CV_Assert( _src.type() == CV_8UC1 );
|
||||
|
||||
CV_Assert( src.type() == CV_8UC1 );
|
||||
|
||||
_dst.create( src.size(), src.type() );
|
||||
cv::Mat dst = _dst.getMat();
|
||||
#ifdef HAVE_OPENCL
|
||||
bool useOpenCL = cv::ocl::useOpenCL() && _src.isUMat() && _src.dims()<=2;
|
||||
#endif
|
||||
|
||||
const int histSize = 256;
|
||||
|
||||
lut_.create(tilesX_ * tilesY_, histSize, CV_8UC1);
|
||||
|
||||
cv::Size tileSize;
|
||||
cv::Mat srcForLut;
|
||||
cv::_InputArray _srcForLut;
|
||||
|
||||
if (src.cols % tilesX_ == 0 && src.rows % tilesY_ == 0)
|
||||
if (_src.size().width % tilesX_ == 0 && _src.size().height % tilesY_ == 0)
|
||||
{
|
||||
tileSize = cv::Size(src.cols / tilesX_, src.rows / tilesY_);
|
||||
srcForLut = src;
|
||||
tileSize = cv::Size(_src.size().width / tilesX_, _src.size().height / tilesY_);
|
||||
_srcForLut = _src;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::copyMakeBorder(src, srcExt_, 0, tilesY_ - (src.rows % tilesY_), 0, tilesX_ - (src.cols % tilesX_), cv::BORDER_REFLECT_101);
|
||||
|
||||
tileSize = cv::Size(srcExt_.cols / tilesX_, srcExt_.rows / tilesY_);
|
||||
srcForLut = srcExt_;
|
||||
#ifdef HAVE_OPENCL
|
||||
if(useOpenCL)
|
||||
{
|
||||
cv::copyMakeBorder(_src, usrcExt_, 0, tilesY_ - (_src.size().height % tilesY_), 0, tilesX_ - (_src.size().width % tilesX_), cv::BORDER_REFLECT_101);
|
||||
tileSize = cv::Size(usrcExt_.size().width / tilesX_, usrcExt_.size().height / tilesY_);
|
||||
_srcForLut = usrcExt_;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
cv::copyMakeBorder(_src, srcExt_, 0, tilesY_ - (_src.size().height % tilesY_), 0, tilesX_ - (_src.size().width % tilesX_), cv::BORDER_REFLECT_101);
|
||||
tileSize = cv::Size(srcExt_.size().width / tilesX_, srcExt_.size().height / tilesY_);
|
||||
_srcForLut = srcExt_;
|
||||
}
|
||||
}
|
||||
|
||||
const int tileSizeTotal = tileSize.area();
|
||||
@@ -293,7 +384,19 @@ namespace
|
||||
clipLimit = std::max(clipLimit, 1);
|
||||
}
|
||||
|
||||
CLAHE_CalcLut_Body calcLutBody(srcForLut, lut_, tileSize, tilesX_, tilesY_, clipLimit, lutScale);
|
||||
#ifdef HAVE_OPENCL
|
||||
if (useOpenCL && clahe::calcLut(_srcForLut, ulut_, tilesX_, tilesY_, tileSize, clipLimit, lutScale) )
|
||||
if( clahe::transform(_src, _dst, ulut_, tilesX_, tilesY_, tileSize) )
|
||||
return;
|
||||
#endif
|
||||
|
||||
cv::Mat src = _src.getMat();
|
||||
_dst.create( src.size(), src.type() );
|
||||
cv::Mat dst = _dst.getMat();
|
||||
cv::Mat srcForLut = _srcForLut.getMat();
|
||||
lut_.create(tilesX_ * tilesY_, histSize, CV_8UC1);
|
||||
|
||||
CLAHE_CalcLut_Body calcLutBody(srcForLut, lut_, tileSize, tilesX_, clipLimit, lutScale);
|
||||
cv::parallel_for_(cv::Range(0, tilesX_ * tilesY_), calcLutBody);
|
||||
|
||||
CLAHE_Interpolation_Body interpolationBody(src, dst, lut_, tileSize, tilesX_, tilesY_);
|
||||
@@ -325,6 +428,10 @@ namespace
|
||||
{
|
||||
srcExt_.release();
|
||||
lut_.release();
|
||||
#ifdef HAVE_OPENCL
|
||||
usrcExt_.release();
|
||||
ulut_.release();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+191
-32
@@ -1594,8 +1594,11 @@ struct RGB2Lab_b
|
||||
static volatile int _3 = 3;
|
||||
initLabTabs();
|
||||
|
||||
if(!_coeffs) _coeffs = sRGB2XYZ_D65;
|
||||
if(!_whitept) _whitept = D65;
|
||||
if (!_coeffs)
|
||||
_coeffs = sRGB2XYZ_D65;
|
||||
if (!_whitept)
|
||||
_whitept = D65;
|
||||
|
||||
float scale[] =
|
||||
{
|
||||
(1 << lab_shift)/_whitept[0],
|
||||
@@ -1699,10 +1702,6 @@ struct RGB2Lab_f
|
||||
float G = clip(src[1]);
|
||||
float B = clip(src[2]);
|
||||
|
||||
// CV_Assert(R >= 0.0f && R <= 1.0f);
|
||||
// CV_Assert(G >= 0.0f && G <= 1.0f);
|
||||
// CV_Assert(B >= 0.0f && B <= 1.0f);
|
||||
|
||||
if (gammaTab)
|
||||
{
|
||||
R = splineInterpolate(R * gscale, gammaTab, GAMMA_TAB_SIZE);
|
||||
@@ -1738,7 +1737,7 @@ struct Lab2RGB_f
|
||||
|
||||
Lab2RGB_f( int _dstcn, int blueIdx, const float* _coeffs,
|
||||
const float* _whitept, bool _srgb )
|
||||
: dstcn(_dstcn), srgb(_srgb), blueInd(blueIdx)
|
||||
: dstcn(_dstcn), srgb(_srgb)
|
||||
{
|
||||
initLabTabs();
|
||||
|
||||
@@ -1796,13 +1795,12 @@ struct Lab2RGB_f
|
||||
|
||||
|
||||
float x = fxz[0], z = fxz[1];
|
||||
float ro = clip(C0 * x + C1 * y + C2 * z);
|
||||
float go = clip(C3 * x + C4 * y + C5 * z);
|
||||
float bo = clip(C6 * x + C7 * y + C8 * z);
|
||||
|
||||
// CV_Assert(ro >= 0.0f && ro <= 1.0f);
|
||||
// CV_Assert(go >= 0.0f && go <= 1.0f);
|
||||
// CV_Assert(bo >= 0.0f && bo <= 1.0f);
|
||||
float ro = C0 * x + C1 * y + C2 * z;
|
||||
float go = C3 * x + C4 * y + C5 * z;
|
||||
float bo = C6 * x + C7 * y + C8 * z;
|
||||
ro = clip(ro);
|
||||
go = clip(go);
|
||||
bo = clip(bo);
|
||||
|
||||
if (gammaTab)
|
||||
{
|
||||
@@ -1820,7 +1818,6 @@ struct Lab2RGB_f
|
||||
int dstcn;
|
||||
float coeffs[9];
|
||||
bool srgb;
|
||||
int blueInd;
|
||||
};
|
||||
|
||||
#undef clip
|
||||
@@ -2275,7 +2272,7 @@ struct YUV420p2RGB888Invoker : ParallelLoopBody
|
||||
const int rangeBegin = range.start * 2;
|
||||
const int rangeEnd = range.end * 2;
|
||||
|
||||
size_t uvsteps[2] = {width/2, stride - width/2};
|
||||
int uvsteps[2] = {width/2, stride - width/2};
|
||||
int usIdx = ustepIdx, vsIdx = vstepIdx;
|
||||
|
||||
const uchar* y1 = my1 + rangeBegin * stride;
|
||||
@@ -2343,7 +2340,7 @@ struct YUV420p2RGBA8888Invoker : ParallelLoopBody
|
||||
int rangeBegin = range.start * 2;
|
||||
int rangeEnd = range.end * 2;
|
||||
|
||||
size_t uvsteps[2] = {width/2, stride - width/2};
|
||||
int uvsteps[2] = {width/2, stride - width/2};
|
||||
int usIdx = ustepIdx, vsIdx = vstepIdx;
|
||||
|
||||
const uchar* y1 = my1 + rangeBegin * stride;
|
||||
@@ -2688,6 +2685,7 @@ struct mRGBA2RGBA
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
{
|
||||
@@ -2699,7 +2697,7 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
size_t globalsize[] = { src.cols, src.rows };
|
||||
ocl::Kernel k;
|
||||
|
||||
if(depth != CV_8U && depth != CV_16U && depth != CV_32F)
|
||||
if (depth != CV_8U && depth != CV_16U && depth != CV_32F)
|
||||
return false;
|
||||
|
||||
switch (code)
|
||||
@@ -2878,6 +2876,8 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
|
||||
k.create("RGB2XYZ", ocl::imgproc::cvtcolor_oclsrc,
|
||||
format("-D depth=%d -D scn=%d -D dcn=3 -D bidx=%d", depth, scn, bidx));
|
||||
if (k.empty())
|
||||
return false;
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), ocl::KernelArg::PtrReadOnly(c));
|
||||
return k.run(2, globalsize, 0, false);
|
||||
}
|
||||
@@ -2927,6 +2927,8 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
|
||||
k.create("XYZ2RGB", ocl::imgproc::cvtcolor_oclsrc,
|
||||
format("-D depth=%d -D scn=3 -D dcn=%d -D bidx=%d", depth, dcn, bidx));
|
||||
if (k.empty())
|
||||
return false;
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), ocl::KernelArg::PtrReadOnly(c));
|
||||
return k.run(2, globalsize, 0, false);
|
||||
}
|
||||
@@ -2981,6 +2983,8 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
|
||||
k.create("RGB2HSV", ocl::imgproc::cvtcolor_oclsrc, format("-D depth=%d -D hrange=%d -D bidx=%d -D dcn=3 -D scn=%d",
|
||||
depth, hrange, bidx, scn));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst),
|
||||
ocl::KernelArg::PtrReadOnly(sdiv_data), hrange == 256 ? ocl::KernelArg::PtrReadOnly(hdiv_data256) :
|
||||
@@ -2990,7 +2994,7 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
}
|
||||
else
|
||||
k.create(kernelName.c_str(), ocl::imgproc::cvtcolor_oclsrc,
|
||||
format("-D depth=%d -D hscale=%f -D bidx=%d -D scn=%d -D dcn=3", depth, hrange*(1.f/360.f), bidx, scn));
|
||||
format("-D depth=%d -D hscale=%ff -D bidx=%d -D scn=%d -D dcn=3", depth, hrange*(1.f/360.f), bidx, scn));
|
||||
break;
|
||||
}
|
||||
case COLOR_HSV2BGR: case COLOR_HSV2RGB: case COLOR_HSV2BGR_FULL: case COLOR_HSV2RGB_FULL:
|
||||
@@ -3008,7 +3012,7 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
|
||||
String kernelName = String(is_hsv ? "HSV" : "HLS") + "2RGB";
|
||||
k.create(kernelName.c_str(), ocl::imgproc::cvtcolor_oclsrc,
|
||||
format("-D depth=%d -D dcn=%d -D scn=3 -D bidx=%d -D hrange=%d -D hscale=%f",
|
||||
format("-D depth=%d -D dcn=%d -D scn=3 -D bidx=%d -D hrange=%d -D hscale=%ff",
|
||||
depth, dcn, bidx, hrange, 6.f/hrange));
|
||||
break;
|
||||
}
|
||||
@@ -3021,8 +3025,162 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
format("-D depth=%d -D dcn=4 -D scn=4 -D bidx=3", depth));
|
||||
break;
|
||||
}
|
||||
case CV_BGR2Lab: case CV_RGB2Lab: case CV_LBGR2Lab: case CV_LRGB2Lab:
|
||||
{
|
||||
CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
|
||||
|
||||
bidx = code == CV_BGR2Lab || code == CV_LBGR2Lab ? 0 : 2;
|
||||
bool srgb = code == CV_BGR2Lab || code == CV_RGB2Lab;
|
||||
dcn = 3;
|
||||
|
||||
k.create("BGR2Lab", ocl::imgproc::cvtcolor_oclsrc,
|
||||
format("-D depth=%d -D dcn=3 -D scn=%d -D bidx=%d%s",
|
||||
depth, scn, bidx, srgb ? " -D SRGB" : ""));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
initLabTabs();
|
||||
|
||||
_dst.create(dstSz, CV_MAKETYPE(depth, dcn));
|
||||
dst = _dst.getUMat();
|
||||
|
||||
ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
|
||||
dstarg = ocl::KernelArg::WriteOnly(dst);
|
||||
|
||||
if (depth == CV_8U)
|
||||
{
|
||||
static UMat usRGBGammaTab, ulinearGammaTab, uLabCbrtTab, ucoeffs;
|
||||
|
||||
if (srgb && usRGBGammaTab.empty())
|
||||
Mat(1, 256, CV_16UC1, sRGBGammaTab_b).copyTo(usRGBGammaTab);
|
||||
else if (ulinearGammaTab.empty())
|
||||
Mat(1, 256, CV_16UC1, linearGammaTab_b).copyTo(ulinearGammaTab);
|
||||
if (uLabCbrtTab.empty())
|
||||
Mat(1, LAB_CBRT_TAB_SIZE_B, CV_16UC1, LabCbrtTab_b).copyTo(uLabCbrtTab);
|
||||
|
||||
{
|
||||
int coeffs[9];
|
||||
const float * const _coeffs = sRGB2XYZ_D65, * const _whitept = D65;
|
||||
const float scale[] =
|
||||
{
|
||||
(1 << lab_shift)/_whitept[0],
|
||||
(float)(1 << lab_shift),
|
||||
(1 << lab_shift)/_whitept[2]
|
||||
};
|
||||
|
||||
for (int i = 0; i < 3; i++ )
|
||||
{
|
||||
coeffs[i*3+(bidx^2)] = cvRound(_coeffs[i*3]*scale[i]);
|
||||
coeffs[i*3+1] = cvRound(_coeffs[i*3+1]*scale[i]);
|
||||
coeffs[i*3+bidx] = cvRound(_coeffs[i*3+2]*scale[i]);
|
||||
|
||||
CV_Assert( coeffs[i] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
|
||||
coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 2*(1 << lab_shift) );
|
||||
}
|
||||
Mat(1, 9, CV_32SC1, coeffs).copyTo(ucoeffs);
|
||||
}
|
||||
|
||||
const int Lscale = (116*255+50)/100;
|
||||
const int Lshift = -((16*255*(1 << lab_shift2) + 50)/100);
|
||||
|
||||
k.args(srcarg, dstarg,
|
||||
ocl::KernelArg::PtrReadOnly(srgb ? usRGBGammaTab : ulinearGammaTab),
|
||||
ocl::KernelArg::PtrReadOnly(uLabCbrtTab), ocl::KernelArg::PtrReadOnly(ucoeffs),
|
||||
Lscale, Lshift);
|
||||
}
|
||||
else
|
||||
{
|
||||
static UMat usRGBGammaTab, ucoeffs;
|
||||
|
||||
if (srgb && usRGBGammaTab.empty())
|
||||
Mat(1, GAMMA_TAB_SIZE * 4, CV_32FC1, sRGBGammaTab).copyTo(usRGBGammaTab);
|
||||
|
||||
{
|
||||
float coeffs[9];
|
||||
const float * const _coeffs = sRGB2XYZ_D65, * const _whitept = D65;
|
||||
float scale[] = { 1.0f / _whitept[0], 1.0f, 1.0f / _whitept[2] };
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
int j = i * 3;
|
||||
coeffs[j + (bidx ^ 2)] = _coeffs[j] * scale[i];
|
||||
coeffs[j + 1] = _coeffs[j + 1] * scale[i];
|
||||
coeffs[j + bidx] = _coeffs[j + 2] * scale[i];
|
||||
|
||||
CV_Assert( coeffs[j] >= 0 && coeffs[j + 1] >= 0 && coeffs[j + 2] >= 0 &&
|
||||
coeffs[j] + coeffs[j + 1] + coeffs[j + 2] < 1.5f*LabCbrtTabScale );
|
||||
}
|
||||
|
||||
Mat(1, 9, CV_32FC1, coeffs).copyTo(ucoeffs);
|
||||
}
|
||||
|
||||
float _1_3 = 1.0f / 3.0f, _a = 16.0f / 116.0f;
|
||||
ocl::KernelArg ucoeffsarg = ocl::KernelArg::PtrReadOnly(ucoeffs);
|
||||
|
||||
if (srgb)
|
||||
k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBGammaTab),
|
||||
ucoeffsarg, _1_3, _a);
|
||||
else
|
||||
k.args(srcarg, dstarg, ucoeffsarg, _1_3, _a);
|
||||
}
|
||||
|
||||
return k.run(dims, globalsize, NULL, false);
|
||||
}
|
||||
case CV_Lab2BGR: case CV_Lab2RGB: case CV_Lab2LBGR: case CV_Lab2LRGB:
|
||||
{
|
||||
if( dcn <= 0 )
|
||||
dcn = 3;
|
||||
CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
|
||||
|
||||
bidx = code == CV_Lab2BGR || code == CV_Lab2LBGR ? 0 : 2;
|
||||
bool srgb = code == CV_Lab2BGR || code == CV_Lab2RGB;
|
||||
|
||||
k.create("Lab2BGR", ocl::imgproc::cvtcolor_oclsrc,
|
||||
format("-D depth=%d -D dcn=%d -D scn=3 -D bidx=%d%s",
|
||||
depth, dcn, bidx, srgb ? " -D SRGB" : ""));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
initLabTabs();
|
||||
static UMat ucoeffs, usRGBInvGammaTab;
|
||||
|
||||
if (srgb && usRGBInvGammaTab.empty())
|
||||
Mat(1, GAMMA_TAB_SIZE*4, CV_32FC1, sRGBInvGammaTab).copyTo(usRGBInvGammaTab);
|
||||
|
||||
{
|
||||
float coeffs[9];
|
||||
const float * const _coeffs = XYZ2sRGB_D65, * const _whitept = D65;
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
coeffs[i+(bidx^2)*3] = _coeffs[i]*_whitept[i];
|
||||
coeffs[i+3] = _coeffs[i+3]*_whitept[i];
|
||||
coeffs[i+bidx*3] = _coeffs[i+6]*_whitept[i];
|
||||
}
|
||||
|
||||
Mat(1, 9, CV_32FC1, coeffs).copyTo(ucoeffs);
|
||||
}
|
||||
|
||||
_dst.create(sz, CV_MAKETYPE(depth, dcn));
|
||||
dst = _dst.getUMat();
|
||||
|
||||
float lThresh = 0.008856f * 903.3f;
|
||||
float fThresh = 7.787f * 0.008856f + 16.0f / 116.0f;
|
||||
|
||||
ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
|
||||
dstarg = ocl::KernelArg::WriteOnly(dst),
|
||||
coeffsarg = ocl::KernelArg::PtrReadOnly(ucoeffs);
|
||||
|
||||
if (srgb)
|
||||
k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBInvGammaTab),
|
||||
coeffsarg, lThresh, fThresh);
|
||||
else
|
||||
k.args(srcarg, dstarg, coeffsarg, lThresh, fThresh);
|
||||
|
||||
return k.run(dims, globalsize, NULL, false);
|
||||
}
|
||||
default:
|
||||
;
|
||||
break;
|
||||
}
|
||||
|
||||
if( !k.empty() )
|
||||
@@ -3030,11 +3188,13 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
_dst.create(dstSz, CV_MAKETYPE(depth, dcn));
|
||||
dst = _dst.getUMat();
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst));
|
||||
ok = k.run(dims, globalsize, 0, false);
|
||||
ok = k.run(dims, globalsize, NULL, false);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}//namespace cv
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -3043,12 +3203,11 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
|
||||
void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
{
|
||||
bool use_opencl = ocl::useOpenCL() && _dst.kind() == _InputArray::UMAT;
|
||||
int stype = _src.type();
|
||||
int scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype), bidx;
|
||||
|
||||
if( use_opencl && ocl_cvtColor(_src, _dst, code, dcn) )
|
||||
return;
|
||||
CV_OCL_RUN( _src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_cvtColor(_src, _dst, code, dcn) )
|
||||
|
||||
Mat src = _src.getMat(), dst;
|
||||
Size sz = src.size();
|
||||
@@ -3151,7 +3310,7 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
CV_Assert( scn == 3 || scn == 4 );
|
||||
_dst.create(sz, CV_MAKETYPE(depth, 1));
|
||||
dst = _dst.getMat();
|
||||
|
||||
/*
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
if( code == CV_BGR2GRAY )
|
||||
{
|
||||
@@ -3174,7 +3333,7 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
*/
|
||||
bidx = code == CV_BGR2GRAY || code == CV_BGRA2GRAY ? 0 : 2;
|
||||
|
||||
if( depth == CV_8U )
|
||||
@@ -3652,7 +3811,7 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
int ustepIdx = 0;
|
||||
int vstepIdx = dstSz.height % 4 == 2 ? 1 : 0;
|
||||
|
||||
if(uIdx == 1) { std::swap(u ,v), std::swap(ustepIdx, vstepIdx); };
|
||||
if(uIdx == 1) { std::swap(u ,v), std::swap(ustepIdx, vstepIdx); }
|
||||
|
||||
switch(dcn*10 + bIdx)
|
||||
{
|
||||
@@ -3763,9 +3922,9 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
dst = _dst.getMat();
|
||||
|
||||
if( depth == CV_8U )
|
||||
{
|
||||
CvtColorLoop(src, dst, RGBA2mRGBA<uchar>());
|
||||
} else {
|
||||
else
|
||||
{
|
||||
CV_Error( CV_StsBadArg, "Unsupported image depth" );
|
||||
}
|
||||
}
|
||||
@@ -3779,9 +3938,9 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
dst = _dst.getMat();
|
||||
|
||||
if( depth == CV_8U )
|
||||
{
|
||||
CvtColorLoop(src, dst, mRGBA2RGBA<uchar>());
|
||||
} else {
|
||||
else
|
||||
{
|
||||
CV_Error( CV_StsBadArg, "Unsupported image depth" );
|
||||
}
|
||||
}
|
||||
|
||||
+114
-13
@@ -41,14 +41,12 @@
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
static void
|
||||
calcMinEigenVal( const Mat& _cov, Mat& _dst )
|
||||
static void calcMinEigenVal( const Mat& _cov, Mat& _dst )
|
||||
{
|
||||
int i, j;
|
||||
Size size = _cov.size();
|
||||
@@ -104,8 +102,7 @@ calcMinEigenVal( const Mat& _cov, Mat& _dst )
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calcHarris( const Mat& _cov, Mat& _dst, double k )
|
||||
static void calcHarris( const Mat& _cov, Mat& _dst, double k )
|
||||
{
|
||||
int i, j;
|
||||
Size size = _cov.size();
|
||||
@@ -219,8 +216,7 @@ static void eigen2x2( const float* cov, float* dst, int n )
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
calcEigenValsVecs( const Mat& _cov, Mat& _dst )
|
||||
static void calcEigenValsVecs( const Mat& _cov, Mat& _dst )
|
||||
{
|
||||
Size size = _cov.size();
|
||||
if( _cov.isContinuous() && _dst.isContinuous() )
|
||||
@@ -306,12 +302,110 @@ cornerEigenValsVecs( const Mat& src, Mat& eigenv, int block_size,
|
||||
calcEigenValsVecs( cov, eigenv );
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_cornerMinEigenValVecs(InputArray _src, OutputArray _dst, int block_size,
|
||||
int aperture_size, double k, int borderType, int op_type)
|
||||
{
|
||||
CV_Assert(op_type == HARRIS || op_type == MINEIGENVAL);
|
||||
|
||||
if ( !(borderType == BORDER_CONSTANT || borderType == BORDER_REPLICATE ||
|
||||
borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101) )
|
||||
return false;
|
||||
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type);
|
||||
double scale = (double)(1 << ((aperture_size > 0 ? aperture_size : 3) - 1)) * block_size;
|
||||
if( aperture_size < 0 )
|
||||
scale *= 2.0;
|
||||
if( depth == CV_8U )
|
||||
scale *= 255.0;
|
||||
scale = 1.0 / scale;
|
||||
|
||||
if ( !(type == CV_8UC1 || type == CV_32FC1) )
|
||||
return false;
|
||||
|
||||
UMat Dx, Dy;
|
||||
if (aperture_size > 0)
|
||||
{
|
||||
Sobel(_src, Dx, CV_32F, 1, 0, aperture_size, scale, 0, borderType);
|
||||
Sobel(_src, Dy, CV_32F, 0, 1, aperture_size, scale, 0, borderType);
|
||||
}
|
||||
else
|
||||
{
|
||||
Scharr(_src, Dx, CV_32F, 1, 0, scale, 0, borderType);
|
||||
Scharr(_src, Dy, CV_32F, 0, 1, scale, 0, borderType);
|
||||
}
|
||||
|
||||
const char * const borderTypes[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT",
|
||||
0, "BORDER_REFLECT101" };
|
||||
const char * const cornerType[] = { "CORNER_MINEIGENVAL", "CORNER_HARRIS", 0 };
|
||||
|
||||
ocl::Kernel cornelKernel("corner", ocl::imgproc::corner_oclsrc,
|
||||
format("-D anX=%d -D anY=%d -D ksX=%d -D ksY=%d -D %s -D %s",
|
||||
block_size / 2, block_size / 2, block_size, block_size,
|
||||
borderTypes[borderType], cornerType[op_type]));
|
||||
if (cornelKernel.empty())
|
||||
return false;
|
||||
|
||||
_dst.createSameSize(_src, CV_32FC1);
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
cornelKernel.args(ocl::KernelArg::ReadOnly(Dx), ocl::KernelArg::ReadOnly(Dy),
|
||||
ocl::KernelArg::WriteOnly(dst), (float)k);
|
||||
|
||||
size_t blockSizeX = 256, blockSizeY = 1;
|
||||
size_t gSize = blockSizeX - block_size / 2 * 2;
|
||||
size_t globalSizeX = (Dx.cols) % gSize == 0 ? Dx.cols / gSize * blockSizeX : (Dx.cols / gSize + 1) * blockSizeX;
|
||||
size_t rows_per_thread = 2;
|
||||
size_t globalSizeY = ((Dx.rows + rows_per_thread - 1) / rows_per_thread) % blockSizeY == 0 ?
|
||||
((Dx.rows + rows_per_thread - 1) / rows_per_thread) :
|
||||
(((Dx.rows + rows_per_thread - 1) / rows_per_thread) / blockSizeY + 1) * blockSizeY;
|
||||
|
||||
size_t globalsize[2] = { globalSizeX, globalSizeY }, localsize[2] = { blockSizeX, blockSizeY };
|
||||
return cornelKernel.run(2, globalsize, localsize, false);
|
||||
}
|
||||
|
||||
static bool ocl_preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int borderType, int depth )
|
||||
{
|
||||
UMat Dx, Dy, D2x, D2y, Dxy;
|
||||
|
||||
Sobel( _src, Dx, CV_32F, 1, 0, ksize, 1, 0, borderType );
|
||||
Sobel( _src, Dy, CV_32F, 0, 1, ksize, 1, 0, borderType );
|
||||
Sobel( _src, D2x, CV_32F, 2, 0, ksize, 1, 0, borderType );
|
||||
Sobel( _src, D2y, CV_32F, 0, 2, ksize, 1, 0, borderType );
|
||||
Sobel( _src, Dxy, CV_32F, 1, 1, ksize, 1, 0, borderType );
|
||||
|
||||
_dst.create( _src.size(), CV_32FC1 );
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
double factor = 1 << (ksize - 1);
|
||||
if( depth == CV_8U )
|
||||
factor *= 255;
|
||||
factor = 1./(factor * factor * factor);
|
||||
|
||||
ocl::Kernel k("preCornerDetect", ocl::imgproc::precornerdetect_oclsrc);
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(Dx), ocl::KernelArg::ReadOnlyNoSize(Dy),
|
||||
ocl::KernelArg::ReadOnlyNoSize(D2x), ocl::KernelArg::ReadOnlyNoSize(D2y),
|
||||
ocl::KernelArg::ReadOnlyNoSize(Dxy), ocl::KernelArg::WriteOnly(dst), (float)factor);
|
||||
|
||||
size_t globalsize[2] = { dst.cols, dst.rows };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType )
|
||||
{
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, 0.0, borderType, MINEIGENVAL))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
_dst.create( src.size(), CV_32F );
|
||||
_dst.create( src.size(), CV_32FC1 );
|
||||
Mat dst = _dst.getMat();
|
||||
cornerEigenValsVecs( src, dst, blockSize, ksize, MINEIGENVAL, 0, borderType );
|
||||
}
|
||||
@@ -319,8 +413,11 @@ void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, in
|
||||
|
||||
void cv::cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksize, double k, int borderType )
|
||||
{
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, k, borderType, HARRIS))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
_dst.create( src.size(), CV_32F );
|
||||
_dst.create( src.size(), CV_32FC1 );
|
||||
Mat dst = _dst.getMat();
|
||||
cornerEigenValsVecs( src, dst, blockSize, ksize, HARRIS, k, borderType );
|
||||
}
|
||||
@@ -341,10 +438,14 @@ void cv::cornerEigenValsAndVecs( InputArray _src, OutputArray _dst, int blockSiz
|
||||
|
||||
void cv::preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int borderType )
|
||||
{
|
||||
Mat Dx, Dy, D2x, D2y, Dxy, src = _src.getMat();
|
||||
int type = _src.type();
|
||||
CV_Assert( type == CV_8UC1 || type == CV_32FC1 );
|
||||
|
||||
CV_Assert( src.type() == CV_8UC1 || src.type() == CV_32FC1 );
|
||||
_dst.create( src.size(), CV_32F );
|
||||
CV_OCL_RUN( _src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_preCornerDetect(_src, _dst, ksize, borderType, CV_MAT_DEPTH(type)))
|
||||
|
||||
Mat Dx, Dy, D2x, D2y, Dxy, src = _src.getMat();
|
||||
_dst.create( src.size(), CV_32FC1 );
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
Sobel( src, Dx, CV_32F, 1, 0, ksize, 1, 0, borderType );
|
||||
|
||||
@@ -472,7 +472,7 @@ void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy,
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
if(dx < 2 && dy < 2 && src.channels() == 1 && borderType == 1)
|
||||
if(dx < 2 && dy < 2 && _src.channels() == 1 && borderType == 1)
|
||||
{
|
||||
Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
if(IPPDerivScharr(src, dst, ddepth, dx, dy, scale))
|
||||
@@ -540,8 +540,6 @@ void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize,
|
||||
int wtype = CV_MAKETYPE(wdepth, src.channels());
|
||||
Mat kd, ks;
|
||||
getSobelKernels( kd, ks, 2, 0, ksize, false, ktype );
|
||||
if( ddepth < 0 )
|
||||
ddepth = src.depth();
|
||||
int dtype = CV_MAKETYPE(ddepth, src.channels());
|
||||
|
||||
int dy0 = std::min(std::max((int)(STRIPE_SIZE/(getElemSize(src.type())*src.cols)), 1), src.rows);
|
||||
|
||||
@@ -38,18 +38,184 @@
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
template<typename T> struct greaterThanPtr
|
||||
struct greaterThanPtr :
|
||||
public std::binary_function<const float *, const float *, bool>
|
||||
{
|
||||
bool operator()(const T* a, const T* b) const { return *a > *b; }
|
||||
bool operator () (const float * a, const float * b) const
|
||||
{ return *a > *b; }
|
||||
};
|
||||
|
||||
struct Corner
|
||||
{
|
||||
float val;
|
||||
short y;
|
||||
short x;
|
||||
|
||||
bool operator < (const Corner & c) const
|
||||
{ return val > c.val; }
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_goodFeaturesToTrack( InputArray _image, OutputArray _corners,
|
||||
int maxCorners, double qualityLevel, double minDistance,
|
||||
InputArray _mask, int blockSize,
|
||||
bool useHarrisDetector, double harrisK )
|
||||
{
|
||||
UMat eig, tmp;
|
||||
if( useHarrisDetector )
|
||||
cornerHarris( _image, eig, blockSize, 3, harrisK );
|
||||
else
|
||||
cornerMinEigenVal( _image, eig, blockSize, 3 );
|
||||
|
||||
double maxVal = 0;
|
||||
minMaxLoc( eig, NULL, &maxVal, NULL, NULL, _mask );
|
||||
threshold( eig, eig, maxVal*qualityLevel, 0, THRESH_TOZERO );
|
||||
dilate( eig, tmp, Mat());
|
||||
|
||||
Size imgsize = _image.size();
|
||||
std::vector<Corner> tmpCorners;
|
||||
size_t total, i, j, ncorners = 0, possibleCornersCount =
|
||||
std::max(1024, static_cast<int>(imgsize.area() * 0.1));
|
||||
bool haveMask = !_mask.empty();
|
||||
|
||||
// collect list of pointers to features - put them into temporary image
|
||||
{
|
||||
ocl::Kernel k("findCorners", ocl::imgproc::gftt_oclsrc,
|
||||
format(haveMask ? "-D HAVE_MASK" : ""));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat counter(1, 1, CV_32SC1, Scalar::all(0)),
|
||||
corners(1, (int)(possibleCornersCount * sizeof(Corner)), CV_8UC1);
|
||||
ocl::KernelArg eigarg = ocl::KernelArg::ReadOnlyNoSize(eig),
|
||||
tmparg = ocl::KernelArg::ReadOnlyNoSize(tmp),
|
||||
cornersarg = ocl::KernelArg::PtrWriteOnly(corners),
|
||||
counterarg = ocl::KernelArg::PtrReadWrite(counter);
|
||||
|
||||
if (!haveMask)
|
||||
k.args(eigarg, tmparg, cornersarg, counterarg,
|
||||
imgsize.height - 2, imgsize.width - 2);
|
||||
else
|
||||
{
|
||||
UMat mask = _mask.getUMat();
|
||||
k.args(eigarg, ocl::KernelArg::ReadOnlyNoSize(mask), tmparg,
|
||||
cornersarg, counterarg, imgsize.height - 2, imgsize.width - 2);
|
||||
}
|
||||
|
||||
size_t globalsize[2] = { imgsize.width - 2, imgsize.height - 2 };
|
||||
if (!k.run(2, globalsize, NULL, false))
|
||||
return false;
|
||||
|
||||
total = counter.getMat(ACCESS_READ).at<int>(0, 0);
|
||||
int totalb = (int)(sizeof(Corner) * total);
|
||||
|
||||
tmpCorners.resize(total);
|
||||
Mat mcorners(1, totalb, CV_8UC1, &tmpCorners[0]);
|
||||
corners.colRange(0, totalb).copyTo(mcorners);
|
||||
}
|
||||
|
||||
std::sort( tmpCorners.begin(), tmpCorners.end() );
|
||||
std::vector<Point2f> corners;
|
||||
corners.reserve(total);
|
||||
|
||||
if (minDistance >= 1)
|
||||
{
|
||||
// Partition the image into larger grids
|
||||
int w = imgsize.width, h = imgsize.height;
|
||||
|
||||
const int cell_size = cvRound(minDistance);
|
||||
const int grid_width = (w + cell_size - 1) / cell_size;
|
||||
const int grid_height = (h + cell_size - 1) / cell_size;
|
||||
|
||||
std::vector<std::vector<Point2f> > grid(grid_width*grid_height);
|
||||
minDistance *= minDistance;
|
||||
|
||||
for( i = 0; i < total; i++ )
|
||||
{
|
||||
const Corner & c = tmpCorners[i];
|
||||
bool good = true;
|
||||
|
||||
int x_cell = c.x / cell_size;
|
||||
int y_cell = c.y / cell_size;
|
||||
|
||||
int x1 = x_cell - 1;
|
||||
int y1 = y_cell - 1;
|
||||
int x2 = x_cell + 1;
|
||||
int y2 = y_cell + 1;
|
||||
|
||||
// boundary check
|
||||
x1 = std::max(0, x1);
|
||||
y1 = std::max(0, y1);
|
||||
x2 = std::min(grid_width-1, x2);
|
||||
y2 = std::min(grid_height-1, y2);
|
||||
|
||||
for( int yy = y1; yy <= y2; yy++ )
|
||||
for( int xx = x1; xx <= x2; xx++ )
|
||||
{
|
||||
std::vector<Point2f> &m = grid[yy*grid_width + xx];
|
||||
|
||||
if( m.size() )
|
||||
{
|
||||
for(j = 0; j < m.size(); j++)
|
||||
{
|
||||
float dx = c.x - m[j].x;
|
||||
float dy = c.y - m[j].y;
|
||||
|
||||
if( dx*dx + dy*dy < minDistance )
|
||||
{
|
||||
good = false;
|
||||
goto break_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break_out:
|
||||
|
||||
if (good)
|
||||
{
|
||||
grid[y_cell*grid_width + x_cell].push_back(Point2f((float)c.x, (float)c.y));
|
||||
|
||||
corners.push_back(Point2f((float)c.x, (float)c.y));
|
||||
++ncorners;
|
||||
|
||||
if( maxCorners > 0 && (int)ncorners == maxCorners )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < total; i++ )
|
||||
{
|
||||
const Corner & c = tmpCorners[i];
|
||||
|
||||
corners.push_back(Point2f((float)c.x, (float)c.y));
|
||||
++ncorners;
|
||||
if( maxCorners > 0 && (int)ncorners == maxCorners )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Mat(corners).convertTo(_corners, _corners.fixedType() ? _corners.type() : CV_32F);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners,
|
||||
@@ -57,27 +223,29 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners,
|
||||
InputArray _mask, int blockSize,
|
||||
bool useHarrisDetector, double harrisK )
|
||||
{
|
||||
Mat image = _image.getMat(), mask = _mask.getMat();
|
||||
|
||||
CV_Assert( qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0 );
|
||||
CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) );
|
||||
CV_Assert( _mask.empty() || (_mask.type() == CV_8UC1 && _mask.sameSize(_image)) );
|
||||
|
||||
Mat eig, tmp;
|
||||
CV_OCL_RUN(_image.dims() <= 2 && _image.isUMat(),
|
||||
ocl_goodFeaturesToTrack(_image, _corners, maxCorners, qualityLevel, minDistance,
|
||||
_mask, blockSize, useHarrisDetector, harrisK))
|
||||
|
||||
Mat image = _image.getMat(), eig, tmp;
|
||||
if( useHarrisDetector )
|
||||
cornerHarris( image, eig, blockSize, 3, harrisK );
|
||||
else
|
||||
cornerMinEigenVal( image, eig, blockSize, 3 );
|
||||
|
||||
double maxVal = 0;
|
||||
minMaxLoc( eig, 0, &maxVal, 0, 0, mask );
|
||||
minMaxLoc( eig, 0, &maxVal, 0, 0, _mask );
|
||||
threshold( eig, eig, maxVal*qualityLevel, 0, THRESH_TOZERO );
|
||||
dilate( eig, tmp, Mat());
|
||||
|
||||
Size imgsize = image.size();
|
||||
|
||||
std::vector<const float*> tmpCorners;
|
||||
|
||||
// collect list of pointers to features - put them into temporary image
|
||||
Mat mask = _mask.getMat();
|
||||
for( int y = 1; y < imgsize.height - 1; y++ )
|
||||
{
|
||||
const float* eig_data = (const float*)eig.ptr(y);
|
||||
@@ -92,11 +260,11 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners,
|
||||
}
|
||||
}
|
||||
|
||||
std::sort( tmpCorners.begin(), tmpCorners.end(), greaterThanPtr<float>() );
|
||||
std::sort( tmpCorners.begin(), tmpCorners.end(), greaterThanPtr() );
|
||||
std::vector<Point2f> corners;
|
||||
size_t i, j, total = tmpCorners.size(), ncorners = 0;
|
||||
|
||||
if(minDistance >= 1)
|
||||
if (minDistance >= 1)
|
||||
{
|
||||
// Partition the image into larger grids
|
||||
int w = image.cols;
|
||||
@@ -133,7 +301,6 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners,
|
||||
y2 = std::min(grid_height-1, y2);
|
||||
|
||||
for( int yy = y1; yy <= y2; yy++ )
|
||||
{
|
||||
for( int xx = x1; xx <= x2; xx++ )
|
||||
{
|
||||
std::vector <Point2f> &m = grid[yy*grid_width + xx];
|
||||
@@ -153,14 +320,11 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break_out:
|
||||
|
||||
if(good)
|
||||
if (good)
|
||||
{
|
||||
// printf("%d: %d %d -> %d %d, %d, %d -- %d %d %d %d, %d %d, c=%d\n",
|
||||
// i,x, y, x_cell, y_cell, (int)minDistance, cell_size,x1,y1,x2,y2, grid_width,grid_height,c);
|
||||
grid[y_cell*grid_width + x_cell].push_back(Point2f((float)x, (float)y));
|
||||
|
||||
corners.push_back(Point2f((float)x, (float)y));
|
||||
@@ -187,33 +351,6 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners,
|
||||
}
|
||||
|
||||
Mat(corners).convertTo(_corners, _corners.fixedType() ? _corners.type() : CV_32F);
|
||||
|
||||
/*
|
||||
for( i = 0; i < total; i++ )
|
||||
{
|
||||
int ofs = (int)((const uchar*)tmpCorners[i] - eig.data);
|
||||
int y = (int)(ofs / eig.step);
|
||||
int x = (int)((ofs - y*eig.step)/sizeof(float));
|
||||
|
||||
if( minDistance > 0 )
|
||||
{
|
||||
for( j = 0; j < ncorners; j++ )
|
||||
{
|
||||
float dx = x - corners[j].x;
|
||||
float dy = y - corners[j].y;
|
||||
if( dx*dx + dy*dy < minDistance )
|
||||
break;
|
||||
}
|
||||
if( j < ncorners )
|
||||
continue;
|
||||
}
|
||||
|
||||
corners.push_back(Point2f((float)x, (float)y));
|
||||
++ncorners;
|
||||
if( maxCorners > 0 && (int)ncorners == maxCorners )
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
CV_IMPL void
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels.hpp"
|
||||
#include <sstream>
|
||||
|
||||
/****************************************************************************************\
|
||||
Base Image Filter
|
||||
@@ -1404,7 +1405,11 @@ struct SymmColumnVec_32f16s
|
||||
|
||||
struct RowVec_32f
|
||||
{
|
||||
RowVec_32f() {}
|
||||
RowVec_32f()
|
||||
{
|
||||
haveSSE = checkHardwareSupport(CV_CPU_SSE);
|
||||
}
|
||||
|
||||
RowVec_32f( const Mat& _kernel )
|
||||
{
|
||||
kernel = _kernel;
|
||||
@@ -3114,10 +3119,7 @@ template<typename ST, class CastOp, class VecOp> struct Filter2D : public BaseFi
|
||||
VecOp vecOp;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace cv
|
||||
{
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
#define DIVUP(total, grain) (((total) + (grain) - 1) / (grain))
|
||||
#define ROUNDUP(sz, n) ((sz) + (n) - 1 - (((sz) + (n) - 1) % (n)))
|
||||
@@ -3314,6 +3316,247 @@ static bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth,
|
||||
}
|
||||
return kernel.run(2, globalsize, localsize, true);
|
||||
}
|
||||
|
||||
static bool ocl_sepRowFilter2D( UMat &src, UMat &buf, Mat &kernelX, int anchor, int borderType, bool sync)
|
||||
{
|
||||
int type = src.type();
|
||||
int cn = CV_MAT_CN(type);
|
||||
int sdepth = CV_MAT_DEPTH(type);
|
||||
Size bufSize = buf.size();
|
||||
|
||||
#ifdef ANDROID
|
||||
size_t localsize[2] = {16, 10};
|
||||
#else
|
||||
size_t localsize[2] = {16, 16};
|
||||
#endif
|
||||
size_t globalsize[2] = {DIVUP(bufSize.width, localsize[0]) * localsize[0], DIVUP(bufSize.height, localsize[1]) * localsize[1]};
|
||||
if (CV_8U == sdepth)
|
||||
{
|
||||
switch (cn)
|
||||
{
|
||||
case 1:
|
||||
globalsize[0] = DIVUP((bufSize.width + 3) >> 2, localsize[0]) * localsize[0];
|
||||
break;
|
||||
case 2:
|
||||
globalsize[0] = DIVUP((bufSize.width + 1) >> 1, localsize[0]) * localsize[0];
|
||||
break;
|
||||
case 4:
|
||||
globalsize[0] = DIVUP(bufSize.width, localsize[0]) * localsize[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int radiusX = anchor;
|
||||
int radiusY = (int)((buf.rows - src.rows) >> 1);
|
||||
|
||||
bool isIsolatedBorder = (borderType & BORDER_ISOLATED) != 0;
|
||||
const char* btype = NULL;
|
||||
switch (borderType & ~BORDER_ISOLATED)
|
||||
{
|
||||
case BORDER_CONSTANT:
|
||||
btype = "BORDER_CONSTANT";
|
||||
break;
|
||||
case BORDER_REPLICATE:
|
||||
btype = "BORDER_REPLICATE";
|
||||
break;
|
||||
case BORDER_REFLECT:
|
||||
btype = "BORDER_REFLECT";
|
||||
break;
|
||||
case BORDER_WRAP:
|
||||
btype = "BORDER_WRAP";
|
||||
break;
|
||||
case BORDER_REFLECT101:
|
||||
btype = "BORDER_REFLECT_101";
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool extra_extrapolation = src.rows < (int)((-radiusY + globalsize[1]) >> 1) + 1;
|
||||
extra_extrapolation |= src.rows < radiusY;
|
||||
extra_extrapolation |= src.cols < (int)((-radiusX + globalsize[0] + 8 * localsize[0] + 3) >> 1) + 1;
|
||||
extra_extrapolation |= src.cols < radiusX;
|
||||
|
||||
cv::String build_options = cv::format("-D RADIUSX=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D %s -D %s -D %s",
|
||||
radiusX, (int)localsize[0], (int)localsize[1], cn,
|
||||
btype,
|
||||
extra_extrapolation ? "EXTRA_EXTRAPOLATION" : "NO_EXTRA_EXTRAPOLATION",
|
||||
isIsolatedBorder ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED");
|
||||
build_options += ocl::kernelToStr(kernelX, CV_32F);
|
||||
|
||||
Size srcWholeSize; Point srcOffset;
|
||||
src.locateROI(srcWholeSize, srcOffset);
|
||||
|
||||
std::stringstream strKernel;
|
||||
strKernel << "row_filter";
|
||||
if (-1 != cn)
|
||||
strKernel << "_C" << cn;
|
||||
if (-1 != sdepth)
|
||||
strKernel << "_D" << sdepth;
|
||||
|
||||
ocl::Kernel kernelRow;
|
||||
if (!kernelRow.create(strKernel.str().c_str(), cv::ocl::imgproc::filterSepRow_oclsrc,
|
||||
build_options))
|
||||
return false;
|
||||
|
||||
int idxArg = 0;
|
||||
idxArg = kernelRow.set(idxArg, ocl::KernelArg::PtrReadOnly(src));
|
||||
idxArg = kernelRow.set(idxArg, (int)(src.step / src.elemSize()));
|
||||
|
||||
idxArg = kernelRow.set(idxArg, srcOffset.x);
|
||||
idxArg = kernelRow.set(idxArg, srcOffset.y);
|
||||
idxArg = kernelRow.set(idxArg, src.cols);
|
||||
idxArg = kernelRow.set(idxArg, src.rows);
|
||||
idxArg = kernelRow.set(idxArg, srcWholeSize.width);
|
||||
idxArg = kernelRow.set(idxArg, srcWholeSize.height);
|
||||
|
||||
idxArg = kernelRow.set(idxArg, ocl::KernelArg::PtrWriteOnly(buf));
|
||||
idxArg = kernelRow.set(idxArg, (int)(buf.step / buf.elemSize()));
|
||||
idxArg = kernelRow.set(idxArg, buf.cols);
|
||||
idxArg = kernelRow.set(idxArg, buf.rows);
|
||||
idxArg = kernelRow.set(idxArg, radiusY);
|
||||
|
||||
return kernelRow.run(2, globalsize, localsize, sync);
|
||||
}
|
||||
|
||||
static bool ocl_sepColFilter2D(UMat &buf, UMat &dst, Mat &kernelY, int anchor, bool sync)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
size_t localsize[2] = {16, 10};
|
||||
#else
|
||||
size_t localsize[2] = {16, 16};
|
||||
#endif
|
||||
size_t globalsize[2] = {0, 0};
|
||||
|
||||
int type = dst.type();
|
||||
int cn = CV_MAT_CN(type);
|
||||
int ddepth = CV_MAT_DEPTH(type);
|
||||
Size sz = dst.size();
|
||||
|
||||
globalsize[1] = DIVUP(sz.height, localsize[1]) * localsize[1];
|
||||
|
||||
cv::String build_options;
|
||||
if (CV_8U == ddepth)
|
||||
{
|
||||
switch (cn)
|
||||
{
|
||||
case 1:
|
||||
globalsize[0] = DIVUP(sz.width, localsize[0]) * localsize[0];
|
||||
build_options = cv::format("-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s",
|
||||
anchor, (int)localsize[0], (int)localsize[1], cn, "float", "uchar", "convert_uchar_sat");
|
||||
break;
|
||||
case 2:
|
||||
globalsize[0] = DIVUP((sz.width + 1) / 2, localsize[0]) * localsize[0];
|
||||
build_options = cv::format("-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s",
|
||||
anchor, (int)localsize[0], (int)localsize[1], cn, "float2", "uchar2", "convert_uchar2_sat");
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
globalsize[0] = DIVUP(sz.width, localsize[0]) * localsize[0];
|
||||
build_options = cv::format("-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s",
|
||||
anchor, (int)localsize[0], (int)localsize[1], cn, "float4", "uchar4", "convert_uchar4_sat");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
globalsize[0] = DIVUP(sz.width, localsize[0]) * localsize[0];
|
||||
switch (dst.type())
|
||||
{
|
||||
case CV_32SC1:
|
||||
build_options = cv::format("-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s",
|
||||
anchor, (int)localsize[0], (int)localsize[1], cn, "float", "int", "convert_int_sat");
|
||||
break;
|
||||
case CV_32SC3:
|
||||
case CV_32SC4:
|
||||
build_options = cv::format("-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s",
|
||||
anchor, (int)localsize[0], (int)localsize[1], cn, "float4", "int4", "convert_int4_sat");
|
||||
break;
|
||||
case CV_32FC1:
|
||||
build_options = cv::format("-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s",
|
||||
anchor, (int)localsize[0], (int)localsize[1], cn, "float", "float", "");
|
||||
break;
|
||||
case CV_32FC3:
|
||||
case CV_32FC4:
|
||||
build_options = cv::format("-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s",
|
||||
anchor, (int)localsize[0], (int)localsize[1], cn, "float4", "float4", "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
build_options += ocl::kernelToStr(kernelY, CV_32F);
|
||||
|
||||
ocl::Kernel kernelCol;
|
||||
if (!kernelCol.create("col_filter", cv::ocl::imgproc::filterSepCol_oclsrc, build_options))
|
||||
return false;
|
||||
|
||||
int idxArg = 0;
|
||||
idxArg = kernelCol.set(idxArg, ocl::KernelArg::PtrReadOnly(buf));
|
||||
idxArg = kernelCol.set(idxArg, (int)(buf.step / buf.elemSize()));
|
||||
idxArg = kernelCol.set(idxArg, buf.cols);
|
||||
idxArg = kernelCol.set(idxArg, buf.rows);
|
||||
|
||||
idxArg = kernelCol.set(idxArg, ocl::KernelArg::PtrWriteOnly(dst));
|
||||
idxArg = kernelCol.set(idxArg, (int)(dst.offset / dst.elemSize()));
|
||||
idxArg = kernelCol.set(idxArg, (int)(dst.step / dst.elemSize()));
|
||||
idxArg = kernelCol.set(idxArg, dst.cols);
|
||||
idxArg = kernelCol.set(idxArg, dst.rows);
|
||||
|
||||
return kernelCol.run(2, globalsize, localsize, sync);
|
||||
}
|
||||
|
||||
static bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth,
|
||||
InputArray _kernelX, InputArray _kernelY, Point anchor,
|
||||
double delta, int borderType )
|
||||
{
|
||||
if (abs(delta)> FLT_MIN)
|
||||
return false;
|
||||
|
||||
int type = _src.type();
|
||||
if ( !( (CV_8UC1 == type || CV_8UC4 == type || CV_32FC1 == type || CV_32FC4 == type) &&
|
||||
(ddepth == CV_32F || ddepth == CV_8U || ddepth < 0) ) )
|
||||
return false;
|
||||
|
||||
int cn = CV_MAT_CN(type);
|
||||
|
||||
Mat kernelX = _kernelX.getMat().reshape(1, 1);
|
||||
if (1 != (kernelX.cols % 2))
|
||||
return false;
|
||||
Mat kernelY = _kernelY.getMat().reshape(1, 1);
|
||||
if (1 != (kernelY.cols % 2))
|
||||
return false;
|
||||
|
||||
int sdepth = CV_MAT_DEPTH(type);
|
||||
if( anchor.x < 0 )
|
||||
anchor.x = kernelX.cols >> 1;
|
||||
if( anchor.y < 0 )
|
||||
anchor.y = kernelY.cols >> 1;
|
||||
|
||||
if( ddepth < 0 )
|
||||
ddepth = sdepth;
|
||||
|
||||
UMat src = _src.getUMat();
|
||||
Size srcWholeSize; Point srcOffset;
|
||||
src.locateROI(srcWholeSize, srcOffset);
|
||||
if ( (0 != (srcOffset.x % 4)) ||
|
||||
(0 != (src.cols % 4)) ||
|
||||
(0 != ((src.step / src.elemSize()) % 4))
|
||||
)
|
||||
return false;
|
||||
|
||||
Size srcSize = src.size();
|
||||
Size bufSize(srcSize.width, srcSize.height + kernelY.cols - 1);
|
||||
UMat buf; buf.create(bufSize, CV_MAKETYPE(CV_32F, cn));
|
||||
if (!ocl_sepRowFilter2D(src, buf, kernelX, anchor.x, borderType, false))
|
||||
return false;
|
||||
|
||||
_dst.create(srcSize, CV_MAKETYPE(ddepth, cn));
|
||||
UMat dst = _dst.getUMat();
|
||||
return ocl_sepColFilter2D(buf, dst, kernelY, anchor.y, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
cv::Ptr<cv::BaseFilter> cv::getLinearFilter(int srcType, int dstType,
|
||||
@@ -3431,9 +3674,8 @@ void cv::filter2D( InputArray _src, OutputArray _dst, int ddepth,
|
||||
InputArray _kernel, Point anchor,
|
||||
double delta, int borderType )
|
||||
{
|
||||
bool use_opencl = ocl::useOpenCL() && _dst.isUMat();
|
||||
if( use_opencl && ocl_filter2D(_src, _dst, ddepth, _kernel, anchor, delta, borderType))
|
||||
return;
|
||||
CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
|
||||
ocl_filter2D(_src, _dst, ddepth, _kernel, anchor, delta, borderType))
|
||||
|
||||
Mat src = _src.getMat(), kernel = _kernel.getMat();
|
||||
|
||||
@@ -3481,6 +3723,9 @@ void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth,
|
||||
InputArray _kernelX, InputArray _kernelY, Point anchor,
|
||||
double delta, int borderType )
|
||||
{
|
||||
CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
|
||||
ocl_sepFilter2D(_src, _dst, ddepth, _kernelX, _kernelY, anchor, delta, borderType))
|
||||
|
||||
Mat src = _src.getMat(), kernelX = _kernelX.getMat(), kernelY = _kernelY.getMat();
|
||||
|
||||
if( ddepth < 0 )
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8)
|
||||
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 8)
|
||||
# pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -380,6 +380,6 @@ bool GCGraph<TWeight>::inSourceSegment( int i )
|
||||
{
|
||||
CV_Assert( i>=0 && i<(int)vtcs.size() );
|
||||
return vtcs[i].t == 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,7 +38,9 @@
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
@@ -1397,6 +1399,61 @@ static void calcHist( const Mat* images, int nimages, const int* channels,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
enum
|
||||
{
|
||||
BINS = 256
|
||||
};
|
||||
|
||||
static bool ocl_calcHist1(InputArray _src, OutputArray _hist, int ddepth = CV_32S)
|
||||
{
|
||||
int compunits = ocl::Device::getDefault().maxComputeUnits();
|
||||
size_t wgs = ocl::Device::getDefault().maxWorkGroupSize();
|
||||
|
||||
ocl::Kernel k1("calculate_histogram", ocl::imgproc::histogram_oclsrc,
|
||||
format("-D BINS=%d -D HISTS_COUNT=%d -D WGS=%d", BINS, compunits, wgs));
|
||||
if (k1.empty())
|
||||
return false;
|
||||
|
||||
_hist.create(BINS, 1, ddepth);
|
||||
UMat src = _src.getUMat(), ghist(1, BINS * compunits, CV_32SC1),
|
||||
hist = ddepth == CV_32S ? _hist.getUMat() : UMat(BINS, 1, CV_32SC1);
|
||||
|
||||
k1.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::PtrWriteOnly(ghist),
|
||||
(int)src.total());
|
||||
|
||||
size_t globalsize = compunits * wgs;
|
||||
if (!k1.run(1, &globalsize, &wgs, false))
|
||||
return false;
|
||||
|
||||
ocl::Kernel k2("merge_histogram", ocl::imgproc::histogram_oclsrc,
|
||||
format("-D BINS=%d -D HISTS_COUNT=%d -D WGS=%d", BINS, compunits, (int)wgs));
|
||||
if (k2.empty())
|
||||
return false;
|
||||
|
||||
k2.args(ocl::KernelArg::PtrReadOnly(ghist), ocl::KernelArg::PtrWriteOnly(hist));
|
||||
if (!k2.run(1, &wgs, &wgs, false))
|
||||
return false;
|
||||
|
||||
if (hist.depth() != ddepth)
|
||||
hist.convertTo(_hist, ddepth);
|
||||
else
|
||||
_hist.getUMatRef() = hist;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ocl_calcHist(InputArrayOfArrays images, OutputArray hist)
|
||||
{
|
||||
std::vector<UMat> v;
|
||||
images.getUMatVector(v);
|
||||
|
||||
return ocl_calcHist1(v[0], hist, CV_32F);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void cv::calcHist( const Mat* images, int nimages, const int* channels,
|
||||
@@ -1415,6 +1472,12 @@ void cv::calcHist( InputArrayOfArrays images, const std::vector<int>& channels,
|
||||
const std::vector<float>& ranges,
|
||||
bool accumulate )
|
||||
{
|
||||
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,
|
||||
ocl_calcHist(images, hist))
|
||||
|
||||
int i, dims = (int)histSize.size(), rsz = (int)ranges.size(), csz = (int)channels.size();
|
||||
int nimages = (int)images.total();
|
||||
|
||||
@@ -1927,14 +1990,166 @@ void cv::calcBackProject( const Mat* images, int nimages, const int* channels,
|
||||
CV_Error(CV_StsUnsupportedFormat, "");
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace cv {
|
||||
|
||||
static void getUMatIndex(const std::vector<UMat> & um, int cn, int & idx, int & cnidx)
|
||||
{
|
||||
int totalChannels = 0;
|
||||
for (size_t i = 0, size = um.size(); i < size; ++i)
|
||||
{
|
||||
int ccn = um[i].channels();
|
||||
totalChannels += ccn;
|
||||
|
||||
if (totalChannels == cn)
|
||||
{
|
||||
idx = (int)(i + 1);
|
||||
cnidx = 0;
|
||||
return;
|
||||
}
|
||||
else if (totalChannels > cn)
|
||||
{
|
||||
idx = (int)i;
|
||||
cnidx = i == 0 ? cn : (cn - totalChannels + ccn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
idx = cnidx = -1;
|
||||
}
|
||||
|
||||
static bool ocl_calcBackProject( InputArrayOfArrays _images, std::vector<int> channels,
|
||||
InputArray _hist, OutputArray _dst,
|
||||
const std::vector<float>& ranges,
|
||||
float scale, size_t histdims )
|
||||
{
|
||||
std::vector<UMat> images;
|
||||
_images.getUMatVector(images);
|
||||
|
||||
size_t nimages = images.size(), totalcn = images[0].channels();
|
||||
|
||||
CV_Assert(nimages > 0);
|
||||
Size size = images[0].size();
|
||||
int depth = images[0].depth();
|
||||
|
||||
for (size_t i = 1; i < nimages; ++i)
|
||||
{
|
||||
const UMat & m = images[i];
|
||||
totalcn += m.channels();
|
||||
CV_Assert(size == m.size() && depth == m.depth());
|
||||
}
|
||||
|
||||
std::sort(channels.begin(), channels.end());
|
||||
for (size_t i = 0; i < histdims; ++i)
|
||||
CV_Assert(channels[i] < (int)totalcn);
|
||||
|
||||
if (histdims == 1)
|
||||
{
|
||||
int idx, cnidx;
|
||||
getUMatIndex(images, channels[0], idx, cnidx);
|
||||
CV_Assert(idx >= 0);
|
||||
UMat im = images[idx];
|
||||
|
||||
String opts = format("-D histdims=1 -D scn=%d", im.channels());
|
||||
ocl::Kernel lutk("calcLUT", ocl::imgproc::calc_back_project_oclsrc, opts);
|
||||
if (lutk.empty())
|
||||
return false;
|
||||
|
||||
size_t lsize = 256;
|
||||
UMat lut(1, (int)lsize, CV_32SC1), hist = _hist.getUMat(), uranges(ranges, true);
|
||||
|
||||
lutk.args(ocl::KernelArg::ReadOnlyNoSize(hist), hist.rows,
|
||||
ocl::KernelArg::PtrWriteOnly(lut), scale, ocl::KernelArg::PtrReadOnly(uranges));
|
||||
if (!lutk.run(1, &lsize, NULL, false))
|
||||
return false;
|
||||
|
||||
ocl::Kernel mapk("LUT", ocl::imgproc::calc_back_project_oclsrc, opts);
|
||||
if (mapk.empty())
|
||||
return false;
|
||||
|
||||
_dst.create(size, depth);
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
im.offset += cnidx;
|
||||
mapk.args(ocl::KernelArg::ReadOnlyNoSize(im), ocl::KernelArg::PtrReadOnly(lut),
|
||||
ocl::KernelArg::WriteOnly(dst));
|
||||
|
||||
size_t globalsize[2] = { size.width, size.height };
|
||||
return mapk.run(2, globalsize, NULL, false);
|
||||
}
|
||||
else if (histdims == 2)
|
||||
{
|
||||
int idx0, idx1, cnidx0, cnidx1;
|
||||
getUMatIndex(images, channels[0], idx0, cnidx0);
|
||||
getUMatIndex(images, channels[1], idx1, cnidx1);
|
||||
CV_Assert(idx0 >= 0 && idx1 >= 0);
|
||||
UMat im0 = images[idx0], im1 = images[idx1];
|
||||
|
||||
// Lut for the first dimension
|
||||
String opts = format("-D histdims=2 -D scn1=%d -D scn2=%d", im0.channels(), im1.channels());
|
||||
ocl::Kernel lutk1("calcLUT", ocl::imgproc::calc_back_project_oclsrc, opts);
|
||||
if (lutk1.empty())
|
||||
return false;
|
||||
|
||||
size_t lsize = 256;
|
||||
UMat lut(1, (int)lsize<<1, CV_32SC1), uranges(ranges, true), hist = _hist.getUMat();
|
||||
|
||||
lutk1.args(hist.rows, ocl::KernelArg::PtrWriteOnly(lut), (int)0, ocl::KernelArg::PtrReadOnly(uranges), (int)0);
|
||||
if (!lutk1.run(1, &lsize, NULL, false))
|
||||
return false;
|
||||
|
||||
// lut for the second dimension
|
||||
ocl::Kernel lutk2("calcLUT", ocl::imgproc::calc_back_project_oclsrc, opts);
|
||||
if (lutk2.empty())
|
||||
return false;
|
||||
|
||||
lut.offset += lsize * sizeof(int);
|
||||
lutk2.args(hist.cols, ocl::KernelArg::PtrWriteOnly(lut), (int)256, ocl::KernelArg::PtrReadOnly(uranges), (int)2);
|
||||
if (!lutk2.run(1, &lsize, NULL, false))
|
||||
return false;
|
||||
|
||||
// perform lut
|
||||
ocl::Kernel mapk("LUT", ocl::imgproc::calc_back_project_oclsrc, opts);
|
||||
if (mapk.empty())
|
||||
return false;
|
||||
|
||||
_dst.create(size, depth);
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
im0.offset += cnidx0;
|
||||
im1.offset += cnidx1;
|
||||
mapk.args(ocl::KernelArg::ReadOnlyNoSize(im0), ocl::KernelArg::ReadOnlyNoSize(im1),
|
||||
ocl::KernelArg::ReadOnlyNoSize(hist), ocl::KernelArg::PtrReadOnly(lut), scale, ocl::KernelArg::WriteOnly(dst));
|
||||
|
||||
size_t globalsize[2] = { size.width, size.height };
|
||||
return mapk.run(2, globalsize, NULL, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void cv::calcBackProject( InputArrayOfArrays images, const std::vector<int>& channels,
|
||||
InputArray hist, OutputArray dst,
|
||||
const std::vector<float>& ranges,
|
||||
double scale )
|
||||
{
|
||||
Size histSize = hist.size();
|
||||
#ifdef HAVE_OPENCL
|
||||
bool _1D = histSize.height == 1 || histSize.width == 1;
|
||||
size_t histdims = _1D ? 1 : hist.dims();
|
||||
#endif
|
||||
|
||||
CV_OCL_RUN(dst.isUMat() && hist.type() == CV_32FC1 &&
|
||||
histdims <= 2 && ranges.size() == histdims * 2 && histdims == channels.size(),
|
||||
ocl_calcBackProject(images, channels, hist, dst, ranges, (float)scale, histdims))
|
||||
|
||||
Mat H0 = hist.getMat(), H;
|
||||
int hcn = H0.channels();
|
||||
|
||||
if( hcn > 1 )
|
||||
{
|
||||
CV_Assert( H0.isContinuous() );
|
||||
@@ -1945,12 +2160,15 @@ void cv::calcBackProject( InputArrayOfArrays images, const std::vector<int>& cha
|
||||
}
|
||||
else
|
||||
H = H0;
|
||||
|
||||
bool _1d = H.rows == 1 || H.cols == 1;
|
||||
int i, dims = H.dims, rsz = (int)ranges.size(), csz = (int)channels.size();
|
||||
int nimages = (int)images.total();
|
||||
|
||||
CV_Assert(nimages > 0);
|
||||
CV_Assert(rsz == dims*2 || (rsz == 2 && _1d) || (rsz == 0 && images.depth(0) == CV_8U));
|
||||
CV_Assert(csz == 0 || csz == dims || (csz == 1 && _1d));
|
||||
|
||||
float* _ranges[CV_MAX_DIM];
|
||||
if( rsz > 0 )
|
||||
{
|
||||
@@ -3129,17 +3347,50 @@ CV_IMPL void cvEqualizeHist( const CvArr* srcarr, CvArr* dstarr )
|
||||
cv::equalizeHist(cv::cvarrToMat(srcarr), cv::cvarrToMat(dstarr));
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace cv {
|
||||
|
||||
static bool ocl_equalizeHist(InputArray _src, OutputArray _dst)
|
||||
{
|
||||
size_t wgs = std::min<size_t>(ocl::Device::getDefault().maxWorkGroupSize(), BINS);
|
||||
|
||||
// calculation of histogram
|
||||
UMat hist;
|
||||
if (!ocl_calcHist1(_src, hist))
|
||||
return false;
|
||||
|
||||
UMat lut(1, 256, CV_8UC1);
|
||||
ocl::Kernel k("calcLUT", ocl::imgproc::histogram_oclsrc, format("-D BINS=%d -D HISTS_COUNT=1 -D WGS=%d", BINS, (int)wgs));
|
||||
k.args(ocl::KernelArg::PtrWriteOnly(lut), ocl::KernelArg::PtrReadOnly(hist), (int)_src.total());
|
||||
|
||||
// calculation of LUT
|
||||
if (!k.run(1, &wgs, &wgs, false))
|
||||
return false;
|
||||
|
||||
// execute LUT transparently
|
||||
LUT(_src, lut, _dst);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void cv::equalizeHist( InputArray _src, OutputArray _dst )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
CV_Assert( src.type() == CV_8UC1 );
|
||||
CV_Assert( _src.type() == CV_8UC1 );
|
||||
|
||||
if (_src.empty())
|
||||
return;
|
||||
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_equalizeHist(_src, _dst))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
_dst.create( src.size(), src.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
if(src.empty())
|
||||
return;
|
||||
|
||||
Mutex histogramLockInstance;
|
||||
|
||||
const int hist_sz = EqualizeHistCalcHist_Invoker::HIST_SZ;
|
||||
|
||||
@@ -75,7 +75,8 @@ Functions return the actual number of found lines.
|
||||
*/
|
||||
static void
|
||||
HoughLinesStandard( const Mat& img, float rho, float theta,
|
||||
int threshold, std::vector<Vec2f>& lines, int linesMax )
|
||||
int threshold, std::vector<Vec2f>& lines, int linesMax,
|
||||
double min_theta, double max_theta )
|
||||
{
|
||||
int i, j;
|
||||
float irho = 1 / rho;
|
||||
@@ -87,7 +88,13 @@ HoughLinesStandard( const Mat& img, float rho, float theta,
|
||||
int width = img.cols;
|
||||
int height = img.rows;
|
||||
|
||||
int numangle = cvRound(CV_PI / theta);
|
||||
if (max_theta < 0 || max_theta > CV_PI ) {
|
||||
CV_Error( CV_StsBadArg, "max_theta must fall between 0 and pi" );
|
||||
}
|
||||
if (min_theta < 0 || min_theta > max_theta ) {
|
||||
CV_Error( CV_StsBadArg, "min_theta must fall between 0 and max_theta" );
|
||||
}
|
||||
int numangle = cvRound((max_theta - min_theta) / theta);
|
||||
int numrho = cvRound(((width + height) * 2 + 1) / rho);
|
||||
|
||||
AutoBuffer<int> _accum((numangle+2) * (numrho+2));
|
||||
@@ -99,7 +106,7 @@ HoughLinesStandard( const Mat& img, float rho, float theta,
|
||||
|
||||
memset( accum, 0, sizeof(accum[0]) * (numangle+2) * (numrho+2) );
|
||||
|
||||
float ang = 0;
|
||||
float ang = static_cast<float>(min_theta);
|
||||
for(int n = 0; n < numangle; ang += theta, n++ )
|
||||
{
|
||||
tabSin[n] = (float)(sin((double)ang) * irho);
|
||||
@@ -166,7 +173,8 @@ static void
|
||||
HoughLinesSDiv( const Mat& img,
|
||||
float rho, float theta, int threshold,
|
||||
int srn, int stn,
|
||||
std::vector<Vec2f>& lines, int linesMax )
|
||||
std::vector<Vec2f>& lines, int linesMax,
|
||||
double min_theta, double max_theta )
|
||||
{
|
||||
#define _POINT(row, column)\
|
||||
(image_src[(row)*step+(column)])
|
||||
@@ -293,7 +301,7 @@ HoughLinesSDiv( const Mat& img,
|
||||
|
||||
if( count * 100 > rn * tn )
|
||||
{
|
||||
HoughLinesStandard( img, rho, theta, threshold, lines, linesMax );
|
||||
HoughLinesStandard( img, rho, theta, threshold, lines, linesMax, min_theta, max_theta );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -601,15 +609,15 @@ HoughLinesProbabilistic( Mat& image,
|
||||
|
||||
void cv::HoughLines( InputArray _image, OutputArray _lines,
|
||||
double rho, double theta, int threshold,
|
||||
double srn, double stn )
|
||||
double srn, double stn, double min_theta, double max_theta )
|
||||
{
|
||||
Mat image = _image.getMat();
|
||||
std::vector<Vec2f> lines;
|
||||
|
||||
if( srn == 0 && stn == 0 )
|
||||
HoughLinesStandard(image, (float)rho, (float)theta, threshold, lines, INT_MAX);
|
||||
HoughLinesStandard(image, (float)rho, (float)theta, threshold, lines, INT_MAX, min_theta, max_theta );
|
||||
else
|
||||
HoughLinesSDiv(image, (float)rho, (float)theta, threshold, cvRound(srn), cvRound(stn), lines, INT_MAX);
|
||||
HoughLinesSDiv(image, (float)rho, (float)theta, threshold, cvRound(srn), cvRound(stn), lines, INT_MAX, min_theta, max_theta);
|
||||
|
||||
Mat(lines).copyTo(_lines);
|
||||
}
|
||||
@@ -631,7 +639,8 @@ void cv::HoughLinesP(InputArray _image, OutputArray _lines,
|
||||
CV_IMPL CvSeq*
|
||||
cvHoughLines2( CvArr* src_image, void* lineStorage, int method,
|
||||
double rho, double theta, int threshold,
|
||||
double param1, double param2 )
|
||||
double param1, double param2,
|
||||
double min_theta, double max_theta )
|
||||
{
|
||||
cv::Mat image = cv::cvarrToMat(src_image);
|
||||
std::vector<cv::Vec2f> l2;
|
||||
@@ -694,11 +703,11 @@ cvHoughLines2( CvArr* src_image, void* lineStorage, int method,
|
||||
{
|
||||
case CV_HOUGH_STANDARD:
|
||||
HoughLinesStandard( image, (float)rho,
|
||||
(float)theta, threshold, l2, linesMax );
|
||||
(float)theta, threshold, l2, linesMax, min_theta, max_theta );
|
||||
break;
|
||||
case CV_HOUGH_MULTI_SCALE:
|
||||
HoughLinesSDiv( image, (float)rho, (float)theta,
|
||||
threshold, iparam1, iparam2, l2, linesMax );
|
||||
threshold, iparam1, iparam2, l2, linesMax, min_theta, max_theta );
|
||||
break;
|
||||
case CV_HOUGH_PROBABILISTIC:
|
||||
HoughLinesProbabilistic( image, (float)rho, (float)theta,
|
||||
|
||||
+215
-88
@@ -55,12 +55,16 @@ static IppStatus sts = ippInit();
|
||||
|
||||
namespace cv
|
||||
{
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR*100 + IPP_VERSION_MINOR >= 701)
|
||||
typedef IppStatus (CV_STDCALL* ippiResizeFunc)(const void*, int, const void*, int, IppiPoint, IppiSize, IppiBorderType, void*, void*, Ipp8u*);
|
||||
typedef IppStatus (CV_STDCALL* ippiResizeGetBufferSize)(void*, IppiSize, Ipp32u, int*);
|
||||
typedef IppStatus (CV_STDCALL* ippiResizeGetSrcOffset)(void*, IppiPoint, IppiPoint*);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
typedef IppStatus (CV_STDCALL* ippiSetFunc)(const void*, void *, int, IppiSize);
|
||||
typedef IppStatus (CV_STDCALL* ippiWarpPerspectiveBackFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [3][3], int);
|
||||
typedef IppStatus (CV_STDCALL* ippiWarpAffineBackFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [2][3], int);
|
||||
typedef IppStatus (CV_STDCALL* ippiResizeSqrPixelFunc)(const void*, IppiSize, int, IppiRect, void*, int, IppiRect, double, double, double, double, int, Ipp8u *);
|
||||
|
||||
template <int channels, typename Type>
|
||||
bool IPPSetSimple(cv::Scalar value, void *dataPointer, int step, IppiSize &size, ippiSetFunc func)
|
||||
@@ -1216,8 +1220,13 @@ public:
|
||||
alpha(_alpha), _beta(__beta), ssize(_ssize), dsize(_dsize),
|
||||
ksize(_ksize), xmin(_xmin), xmax(_xmax)
|
||||
{
|
||||
CV_Assert(ksize <= MAX_ESIZE);
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 8)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#endif
|
||||
virtual void operator() (const Range& range) const
|
||||
{
|
||||
int dy, cn = src.channels();
|
||||
@@ -1266,6 +1275,9 @@ public:
|
||||
vresize( (const WT**)rows, (T*)(dst.data + dst.step*dy), beta, dsize.width );
|
||||
}
|
||||
}
|
||||
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 8)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
private:
|
||||
Mat src;
|
||||
@@ -1273,7 +1285,9 @@ private:
|
||||
const int* xofs, *yofs;
|
||||
const AT* alpha, *_beta;
|
||||
Size ssize, dsize;
|
||||
int ksize, xmin, xmax;
|
||||
const int ksize, xmin, xmax;
|
||||
|
||||
resizeGeneric_Invoker& operator = (const resizeGeneric_Invoker&);
|
||||
};
|
||||
|
||||
template<class HResize, class VResize>
|
||||
@@ -1862,30 +1876,107 @@ static int computeResizeAreaTab( int ssize, int dsize, int cn, double scale, Dec
|
||||
return k;
|
||||
}
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
#define CHECK_IPP_FUNC(FUNC) if( FUNC==0 ) { *ok = false; return;}
|
||||
#define CHECK_IPP_STATUS(STATUS) if( STATUS!=ippStsNoErr ) { *ok = false; return;}
|
||||
|
||||
#define SET_IPP_RESIZE_LINEAR_FUNC_PTR(TYPE, CN) \
|
||||
func = (ippiResizeFunc)ippiResizeLinear_##TYPE##_##CN##R; CHECK_IPP_FUNC(func);\
|
||||
CHECK_IPP_STATUS(ippiResizeGetSize_##TYPE(srcSize, dstSize, (IppiInterpolationType)mode, 0, &specSize, &initSize));\
|
||||
specBuf.allocate(specSize);\
|
||||
pSpec = (uchar*)specBuf;\
|
||||
CHECK_IPP_STATUS(ippiResizeLinearInit_##TYPE(srcSize, dstSize, (IppiResizeSpec_32f*)pSpec));
|
||||
|
||||
#define SET_IPP_RESIZE_LINEAR_FUNC_64_PTR(TYPE, CN) \
|
||||
if (mode==(int)ippCubic) { *ok = false; return;}\
|
||||
func = (ippiResizeFunc)ippiResizeLinear_##TYPE##_##CN##R; CHECK_IPP_FUNC(func);\
|
||||
CHECK_IPP_STATUS(ippiResizeGetSize_##TYPE(srcSize, dstSize, (IppiInterpolationType)mode, 0, &specSize, &initSize));\
|
||||
specBuf.allocate(specSize);\
|
||||
pSpec = (uchar*)specBuf;\
|
||||
CHECK_IPP_STATUS(ippiResizeLinearInit_##TYPE(srcSize, dstSize, (IppiResizeSpec_64f*)pSpec));\
|
||||
getBufferSizeFunc = (ippiResizeGetBufferSize)ippiResizeGetBufferSize_##TYPE;\
|
||||
getSrcOffsetFunc = (ippiResizeGetSrcOffset) ippiResizeGetBufferSize_##TYPE;
|
||||
|
||||
#define SET_IPP_RESIZE_CUBIC_FUNC_PTR(TYPE, CN) \
|
||||
func = (ippiResizeFunc)ippiResizeCubic_##TYPE##_##CN##R; CHECK_IPP_FUNC(func);\
|
||||
CHECK_IPP_STATUS(ippiResizeGetSize_##TYPE(srcSize, dstSize, (IppiInterpolationType)mode, 0, &specSize, &initSize));\
|
||||
specBuf.allocate(specSize);\
|
||||
pSpec = (uchar*)specBuf;\
|
||||
AutoBuffer<uchar> buf(initSize);\
|
||||
uchar* pInit = (uchar*)buf;\
|
||||
CHECK_IPP_STATUS(ippiResizeCubicInit_##TYPE(srcSize, dstSize, 0.f, 0.75f, (IppiResizeSpec_32f*)pSpec, pInit));
|
||||
|
||||
#define SET_IPP_RESIZE_PTR(TYPE, CN) \
|
||||
if (mode == (int)ippLinear) { SET_IPP_RESIZE_LINEAR_FUNC_PTR(TYPE, CN);}\
|
||||
else if (mode == (int)ippCubic) { SET_IPP_RESIZE_CUBIC_FUNC_PTR(TYPE, CN);}\
|
||||
else { *ok = false; return;}\
|
||||
getBufferSizeFunc = (ippiResizeGetBufferSize)ippiResizeGetBufferSize_##TYPE;\
|
||||
getSrcOffsetFunc = (ippiResizeGetSrcOffset)ippiResizeGetSrcOffset_##TYPE;
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR*100 + IPP_VERSION_MINOR >= 701)
|
||||
class IPPresizeInvoker :
|
||||
public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
IPPresizeInvoker(Mat &_src, Mat &_dst, double &_inv_scale_x, double &_inv_scale_y, int _mode, ippiResizeSqrPixelFunc _func, bool *_ok) :
|
||||
ParallelLoopBody(), src(_src), dst(_dst), inv_scale_x(_inv_scale_x), inv_scale_y(_inv_scale_y), mode(_mode), func(_func), ok(_ok)
|
||||
IPPresizeInvoker(Mat &_src, Mat &_dst, double _inv_scale_x, double _inv_scale_y, int _mode, bool *_ok) :
|
||||
ParallelLoopBody(), src(_src), dst(_dst), inv_scale_x(_inv_scale_x), inv_scale_y(_inv_scale_y), mode(_mode), ok(_ok)
|
||||
{
|
||||
*ok = true;
|
||||
IppiSize srcSize, dstSize;
|
||||
int type = src.type();
|
||||
int specSize = 0, initSize = 0;
|
||||
srcSize.width = src.cols;
|
||||
srcSize.height = src.rows;
|
||||
dstSize.width = dst.cols;
|
||||
dstSize.height = dst.rows;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CV_8UC1: SET_IPP_RESIZE_PTR(8u,C1); break;
|
||||
case CV_8UC3: SET_IPP_RESIZE_PTR(8u,C3); break;
|
||||
case CV_8UC4: SET_IPP_RESIZE_PTR(8u,C4); break;
|
||||
case CV_16UC1: SET_IPP_RESIZE_PTR(16u,C1); break;
|
||||
case CV_16UC3: SET_IPP_RESIZE_PTR(16u,C3); break;
|
||||
case CV_16UC4: SET_IPP_RESIZE_PTR(16u,C4); break;
|
||||
case CV_16SC1: SET_IPP_RESIZE_PTR(16s,C1); break;
|
||||
case CV_16SC3: SET_IPP_RESIZE_PTR(16s,C3); break;
|
||||
case CV_16SC4: SET_IPP_RESIZE_PTR(16s,C4); break;
|
||||
case CV_32FC1: SET_IPP_RESIZE_PTR(32f,C1); break;
|
||||
case CV_32FC3: SET_IPP_RESIZE_PTR(32f,C3); break;
|
||||
case CV_32FC4: SET_IPP_RESIZE_PTR(32f,C4); break;
|
||||
case CV_64FC1: SET_IPP_RESIZE_LINEAR_FUNC_64_PTR(64f,C1); break;
|
||||
case CV_64FC3: SET_IPP_RESIZE_LINEAR_FUNC_64_PTR(64f,C3); break;
|
||||
case CV_64FC4: SET_IPP_RESIZE_LINEAR_FUNC_64_PTR(64f,C4); break;
|
||||
default: { *ok = false; return;} break;
|
||||
}
|
||||
}
|
||||
|
||||
~IPPresizeInvoker()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator() (const Range& range) const
|
||||
{
|
||||
if (*ok == false) return;
|
||||
|
||||
int cn = src.channels();
|
||||
IppiRect srcroi = { 0, range.start, src.cols, range.end - range.start };
|
||||
int dsty = CV_IMIN(cvRound(range.start * inv_scale_y), dst.rows);
|
||||
int dstwidth = CV_IMIN(cvRound(src.cols * inv_scale_x), dst.cols);
|
||||
int dstheight = CV_IMIN(cvRound(range.end * inv_scale_y), dst.rows);
|
||||
IppiRect dstroi = { 0, dsty, dstwidth, dstheight - dsty };
|
||||
int bufsize;
|
||||
ippiResizeGetBufSize( srcroi, dstroi, cn, mode, &bufsize );
|
||||
int dsty = min(cvRound(range.start * inv_scale_y), dst.rows);
|
||||
int dstwidth = min(cvRound(src.cols * inv_scale_x), dst.cols);
|
||||
int dstheight = min(cvRound(range.end * inv_scale_y), dst.rows);
|
||||
|
||||
IppiPoint dstOffset = { 0, dsty }, srcOffset = {0, 0};
|
||||
IppiSize dstSize = { dstwidth, dstheight - dsty };
|
||||
int bufsize = 0, itemSize = (int)src.elemSize1();
|
||||
|
||||
CHECK_IPP_STATUS(getBufferSizeFunc(pSpec, dstSize, cn, &bufsize));
|
||||
CHECK_IPP_STATUS(getSrcOffsetFunc(pSpec, dstOffset, &srcOffset));
|
||||
|
||||
Ipp8u* pSrc = (Ipp8u*)src.data + (int)src.step[0] * srcOffset.y + srcOffset.x * cn * itemSize;
|
||||
Ipp8u* pDst = (Ipp8u*)dst.data + (int)dst.step[0] * dstOffset.y + dstOffset.x * cn * itemSize;
|
||||
|
||||
AutoBuffer<uchar> buf(bufsize + 64);
|
||||
uchar* bufptr = alignPtr((uchar*)buf, 32);
|
||||
if( func( src.data, ippiSize(src.cols, src.rows), (int)src.step[0], srcroi, dst.data, (int)dst.step[0], dstroi, inv_scale_x, inv_scale_y, 0, 0, mode, bufptr ) < 0 )
|
||||
|
||||
if( func( pSrc, (int)src.step[0], pDst, (int)dst.step[0], dstOffset, dstSize, ippBorderRepl, 0, pSpec, bufptr ) < 0 )
|
||||
*ok = false;
|
||||
}
|
||||
private:
|
||||
@@ -1893,13 +1984,19 @@ private:
|
||||
Mat &dst;
|
||||
double inv_scale_x;
|
||||
double inv_scale_y;
|
||||
void *pSpec;
|
||||
AutoBuffer<uchar> specBuf;
|
||||
int mode;
|
||||
ippiResizeSqrPixelFunc func;
|
||||
ippiResizeFunc func;
|
||||
ippiResizeGetBufferSize getBufferSizeFunc;
|
||||
ippiResizeGetSrcOffset getSrcOffsetFunc;
|
||||
bool *ok;
|
||||
const IPPresizeInvoker& operator= (const IPPresizeInvoker&);
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static void ocl_computeResizeAreaTabs(int ssize, int dsize, double scale, int * const map_tab,
|
||||
float * const alpha_tab, int * const ofs_tab)
|
||||
{
|
||||
@@ -1955,7 +2052,7 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize,
|
||||
double inv_fx = 1. / fx, inv_fy = 1. / fy;
|
||||
float inv_fxf = (float)inv_fx, inv_fyf = (float)inv_fy;
|
||||
|
||||
if( cn == 3 || !(cn <= 4 &&
|
||||
if( !(cn <= 4 &&
|
||||
(interpolation == INTER_NEAREST || interpolation == INTER_LINEAR ||
|
||||
(interpolation == INTER_AREA && inv_fx >= 1 && inv_fy >= 1) )) )
|
||||
return false;
|
||||
@@ -1973,15 +2070,18 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize,
|
||||
int wtype = CV_MAKETYPE(wdepth, cn);
|
||||
char buf[2][32];
|
||||
k.create("resizeLN", ocl::imgproc::resize_oclsrc,
|
||||
format("-D INTER_LINEAR -D depth=%d -D PIXTYPE=%s -D WORKTYPE=%s -D convertToWT=%s -D convertToDT=%s",
|
||||
depth, ocl::typeToStr(type), ocl::typeToStr(wtype),
|
||||
format("-D INTER_LINEAR -D depth=%d -D PIXTYPE=%s -D PIXTYPE1=%s "
|
||||
"-D WORKTYPE=%s -D convertToWT=%s -D convertToDT=%s -D cn=%d",
|
||||
depth, ocl::typeToStr(type), ocl::typeToStr(depth), ocl::typeToStr(wtype),
|
||||
ocl::convertTypeStr(depth, wdepth, cn, buf[0]),
|
||||
ocl::convertTypeStr(wdepth, depth, cn, buf[1])));
|
||||
ocl::convertTypeStr(wdepth, depth, cn, buf[1]),
|
||||
cn));
|
||||
}
|
||||
else if (interpolation == INTER_NEAREST)
|
||||
{
|
||||
k.create("resizeNN", ocl::imgproc::resize_oclsrc,
|
||||
format("-D INTER_NEAREST -D PIXTYPE=%s -D cn", ocl::memopTypeToStr(type), cn));
|
||||
format("-D INTER_NEAREST -D PIXTYPE=%s -D PIXTYPE1=%s -D cn=%d",
|
||||
ocl::memopTypeToStr(type), ocl::memopTypeToStr(depth), cn));
|
||||
}
|
||||
else if (interpolation == INTER_AREA)
|
||||
{
|
||||
@@ -1993,9 +2093,9 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize,
|
||||
int wtype = CV_MAKE_TYPE(wdepth, cn);
|
||||
|
||||
char cvt[2][40];
|
||||
String buildOption = format("-D INTER_AREA -D T=%s -D WTV=%s -D convertToWTV=%s",
|
||||
ocl::typeToStr(type), ocl::typeToStr(wtype),
|
||||
ocl::convertTypeStr(depth, wdepth, cn, cvt[0]));
|
||||
String buildOption = format("-D INTER_AREA -D PIXTYPE=%s -D PIXTYPE1=%s -D WTV=%s -D convertToWTV=%s -D cn=%d",
|
||||
ocl::typeToStr(type), ocl::typeToStr(depth), ocl::typeToStr(wtype),
|
||||
ocl::convertTypeStr(depth, wdepth, cn, cvt[0]), cn);
|
||||
|
||||
UMat alphaOcl, tabofsOcl, mapOcl;
|
||||
UMat dmap, smap;
|
||||
@@ -2003,8 +2103,8 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize,
|
||||
if (is_area_fast)
|
||||
{
|
||||
int wdepth2 = std::max(CV_32F, depth), wtype2 = CV_MAKE_TYPE(wdepth2, cn);
|
||||
buildOption = buildOption + format(" -D convertToT=%s -D WT2V=%s -D convertToWT2V=%s -D INTER_AREA_FAST"
|
||||
" -D XSCALE=%d -D YSCALE=%d -D SCALE=%f",
|
||||
buildOption = buildOption + format(" -D convertToPIXTYPE=%s -D WT2V=%s -D convertToWT2V=%s -D INTER_AREA_FAST"
|
||||
" -D XSCALE=%d -D YSCALE=%d -D SCALE=%ff",
|
||||
ocl::convertTypeStr(wdepth2, depth, cn, cvt[0]),
|
||||
ocl::typeToStr(wtype2), ocl::convertTypeStr(wdepth, wdepth2, cn, cvt[1]),
|
||||
iscale_x, iscale_y, 1.0f / (iscale_x * iscale_y));
|
||||
@@ -2026,7 +2126,7 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize,
|
||||
}
|
||||
else
|
||||
{
|
||||
buildOption = buildOption + format(" -D convertToT=%s", ocl::convertTypeStr(wdepth, depth, cn, cvt[0]));
|
||||
buildOption = buildOption + format(" -D convertToPIXTYPE=%s", ocl::convertTypeStr(wdepth, depth, cn, cvt[0]));
|
||||
k.create("resizeAREA", ocl::imgproc::resize_oclsrc, buildOption);
|
||||
if (k.empty())
|
||||
return false;
|
||||
@@ -2069,6 +2169,8 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize,
|
||||
return k.run(2, globalsize, 0, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -2196,9 +2298,8 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
|
||||
inv_scale_y = (double)dsize.height/ssize.height;
|
||||
}
|
||||
|
||||
if( ocl::useOpenCL() && _dst.kind() == _InputArray::UMAT &&
|
||||
ocl_resize(_src, _dst, dsize, inv_scale_x, inv_scale_y, interpolation))
|
||||
return;
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_resize(_src, _dst, dsize, inv_scale_x, inv_scale_y, interpolation))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
_dst.create(dsize, src.type());
|
||||
@@ -2213,32 +2314,37 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
|
||||
double scale_x = 1./inv_scale_x, scale_y = 1./inv_scale_y;
|
||||
int k, sx, sy, dx, dy;
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
int mode = interpolation == INTER_LINEAR ? IPPI_INTER_LINEAR : 0;
|
||||
int type = src.type();
|
||||
ippiResizeSqrPixelFunc ippFunc =
|
||||
type == CV_8UC1 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_8u_C1R :
|
||||
type == CV_8UC3 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_8u_C3R :
|
||||
type == CV_8UC4 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_8u_C4R :
|
||||
type == CV_16UC1 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16u_C1R :
|
||||
type == CV_16UC3 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16u_C3R :
|
||||
type == CV_16UC4 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16u_C4R :
|
||||
type == CV_16SC1 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16s_C1R :
|
||||
type == CV_16SC3 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16s_C3R :
|
||||
type == CV_16SC4 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16s_C4R :
|
||||
type == CV_32FC1 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_32f_C1R :
|
||||
type == CV_32FC3 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_32f_C3R :
|
||||
type == CV_32FC4 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_32f_C4R :
|
||||
0;
|
||||
if( ippFunc && mode != 0 )
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR*100 + IPP_VERSION_MINOR >= 701)
|
||||
#define IPP_RESIZE_EPS 1.e-10
|
||||
|
||||
double ex = fabs((double)dsize.width/src.cols - inv_scale_x)/inv_scale_x;
|
||||
double ey = fabs((double)dsize.height/src.rows - inv_scale_y)/inv_scale_y;
|
||||
|
||||
if ((ex < IPP_RESIZE_EPS && ey < IPP_RESIZE_EPS && depth != CV_64F) ||
|
||||
(ex == 0 && ey == 0 && depth == CV_64F))
|
||||
{
|
||||
bool ok;
|
||||
Range range(0, src.rows);
|
||||
IPPresizeInvoker invoker(src, dst, inv_scale_x, inv_scale_y, mode, ippFunc, &ok);
|
||||
parallel_for_(range, invoker, dst.total()/(double)(1<<16));
|
||||
if( ok )
|
||||
return;
|
||||
int mode = 0;
|
||||
if (interpolation == INTER_LINEAR && src.rows >= 2 && src.cols >= 2)
|
||||
{
|
||||
mode = ippLinear;
|
||||
}
|
||||
else if (interpolation == INTER_CUBIC && src.rows >= 4 && src.cols >= 4)
|
||||
{
|
||||
mode = ippCubic;
|
||||
}
|
||||
if( mode != 0 && (cn == 1 || cn ==3 || cn == 4) &&
|
||||
(depth == CV_8U || depth == CV_16U || depth == CV_16S || depth == CV_32F ||
|
||||
(depth == CV_64F && mode == ippLinear)))
|
||||
{
|
||||
bool ok = true;
|
||||
Range range(0, src.rows);
|
||||
IPPresizeInvoker invoker(src, dst, inv_scale_x, inv_scale_y, mode, &ok);
|
||||
parallel_for_(range, invoker, dst.total()/(double)(1<<16));
|
||||
if( ok )
|
||||
return;
|
||||
}
|
||||
}
|
||||
#undef IPP_RESIZE_EPS
|
||||
#endif
|
||||
|
||||
if( interpolation == INTER_NEAREST )
|
||||
@@ -2360,14 +2466,14 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
|
||||
if( sx < ksize2-1 )
|
||||
{
|
||||
xmin = dx+1;
|
||||
if( sx < 0 )
|
||||
if( sx < 0 && (interpolation != INTER_CUBIC && interpolation != INTER_LANCZOS4))
|
||||
fx = 0, sx = 0;
|
||||
}
|
||||
|
||||
if( sx + ksize2 >= ssize.width )
|
||||
{
|
||||
xmax = std::min( xmax, dx );
|
||||
if( sx >= ssize.width-1 )
|
||||
if( sx >= ssize.width-1 && (interpolation != INTER_CUBIC && interpolation != INTER_LANCZOS4))
|
||||
fx = 0, sx = ssize.width-1;
|
||||
}
|
||||
|
||||
@@ -2565,15 +2671,15 @@ struct RemapVec_8u
|
||||
int operator()( const Mat& _src, void* _dst, const short* XY,
|
||||
const ushort* FXY, const void* _wtab, int width ) const
|
||||
{
|
||||
int cn = _src.channels();
|
||||
int cn = _src.channels(), x = 0, sstep = (int)_src.step;
|
||||
|
||||
if( (cn != 1 && cn != 3 && cn != 4) || !checkHardwareSupport(CV_CPU_SSE2) )
|
||||
if( (cn != 1 && cn != 3 && cn != 4) || !checkHardwareSupport(CV_CPU_SSE2) ||
|
||||
sstep > 0x8000 )
|
||||
return 0;
|
||||
|
||||
const uchar *S0 = _src.data, *S1 = _src.data + _src.step;
|
||||
const short* wtab = cn == 1 ? (const short*)_wtab : &BilinearTab_iC4[0][0][0];
|
||||
uchar* D = (uchar*)_dst;
|
||||
int x = 0, sstep = (int)_src.step;
|
||||
__m128i delta = _mm_set1_epi32(INTER_REMAP_COEF_SCALE/2);
|
||||
__m128i xy2ofs = _mm_set1_epi32(cn + (sstep << 16));
|
||||
__m128i z = _mm_setzero_si128();
|
||||
@@ -3299,7 +3405,10 @@ public:
|
||||
if( m1->type() == CV_16SC2 && (m2->type() == CV_16UC1 || m2->type() == CV_16SC1) )
|
||||
{
|
||||
bufxy = (*m1)(Rect(x, y, bcols, brows));
|
||||
bufa = (*m2)(Rect(x, y, bcols, brows));
|
||||
|
||||
const ushort* sA = (const ushort*)(m2->data + m2->step*(y+y1)) + x;
|
||||
for( x1 = 0; x1 < bcols; x1++ )
|
||||
A[x1] = (ushort)(sA[x1] & (INTER_TAB_SIZE2-1));
|
||||
}
|
||||
else if( planar_input )
|
||||
{
|
||||
@@ -3387,6 +3496,8 @@ private:
|
||||
const void *ctab;
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, InputArray _map2,
|
||||
int interpolation, int borderType, const Scalar& borderValue)
|
||||
{
|
||||
@@ -3459,6 +3570,8 @@ static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, Input
|
||||
return k.run(2, globalThreads, NULL, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void cv::remap( InputArray _src, OutputArray _dst,
|
||||
@@ -3501,8 +3614,8 @@ void cv::remap( InputArray _src, OutputArray _dst,
|
||||
CV_Assert( _map1.size().area() > 0 );
|
||||
CV_Assert( _map2.empty() || (_map2.size() == _map1.size()));
|
||||
|
||||
if (ocl::useOpenCL() && _dst.isUMat() && ocl_remap(_src, _dst, _map1, _map2, interpolation, borderType, borderValue))
|
||||
return;
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_remap(_src, _dst, _map1, _map2, interpolation, borderType, borderValue))
|
||||
|
||||
Mat src = _src.getMat(), map1 = _map1.getMat(), map2 = _map2.getMat();
|
||||
_dst.create( map1.size(), src.type() );
|
||||
@@ -3680,7 +3793,7 @@ void cv::convertMaps( InputArray _map1, InputArray _map2,
|
||||
{
|
||||
for( x = 0; x < size.width; x++ )
|
||||
{
|
||||
int fxy = src2 ? src2[x] : 0;
|
||||
int fxy = src2 ? src2[x] & (INTER_TAB_SIZE2-1) : 0;
|
||||
dst1f[x] = src1[x*2] + (fxy & (INTER_TAB_SIZE-1))*scale;
|
||||
dst2f[x] = src1[x*2+1] + (fxy >> INTER_BITS)*scale;
|
||||
}
|
||||
@@ -3689,7 +3802,7 @@ void cv::convertMaps( InputArray _map1, InputArray _map2,
|
||||
{
|
||||
for( x = 0; x < size.width; x++ )
|
||||
{
|
||||
int fxy = src2 ? src2[x] : 0;
|
||||
int fxy = src2 ? src2[x] & (INTER_TAB_SIZE2-1): 0;
|
||||
dst1f[x*2] = src1[x*2] + (fxy & (INTER_TAB_SIZE-1))*scale;
|
||||
dst1f[x*2+1] = src1[x*2+1] + (fxy >> INTER_BITS)*scale;
|
||||
}
|
||||
@@ -3867,6 +3980,8 @@ private:
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
enum { OCL_OP_PERSPECTIVE = 1, OCL_OP_AFFINE = 0 };
|
||||
|
||||
static bool ocl_warpTransform(InputArray _src, OutputArray _dst, InputArray _M0,
|
||||
@@ -3875,7 +3990,7 @@ static bool ocl_warpTransform(InputArray _src, OutputArray _dst, InputArray _M0,
|
||||
{
|
||||
CV_Assert(op_type == OCL_OP_AFFINE || op_type == OCL_OP_PERSPECTIVE);
|
||||
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), wdepth = depth;
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
double doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
||||
|
||||
int interpolation = flags & INTER_MAX;
|
||||
@@ -3884,36 +3999,48 @@ static bool ocl_warpTransform(InputArray _src, OutputArray _dst, InputArray _M0,
|
||||
|
||||
if ( !(borderType == cv::BORDER_CONSTANT &&
|
||||
(interpolation == cv::INTER_NEAREST || interpolation == cv::INTER_LINEAR || interpolation == cv::INTER_CUBIC)) ||
|
||||
(!doubleSupport && depth == CV_64F) || cn > 4 || cn == 3)
|
||||
(!doubleSupport && depth == CV_64F) || cn > 4)
|
||||
return false;
|
||||
|
||||
const char * const interpolationMap[3] = { "NEAREST", "LINEAR", "CUBIC" };
|
||||
ocl::ProgramSource2 program = op_type == OCL_OP_AFFINE ?
|
||||
ocl::ProgramSource program = op_type == OCL_OP_AFFINE ?
|
||||
ocl::imgproc::warp_affine_oclsrc : ocl::imgproc::warp_perspective_oclsrc;
|
||||
const char * const kernelName = op_type == OCL_OP_AFFINE ? "warpAffine" : "warpPerspective";
|
||||
|
||||
int scalarcn = cn == 3 ? 4 : cn;
|
||||
int wdepth = interpolation == INTER_NEAREST ? depth : std::max(CV_32S, depth);
|
||||
int sctype = CV_MAKETYPE(wdepth, scalarcn);
|
||||
|
||||
ocl::Kernel k;
|
||||
String opts;
|
||||
if (interpolation == INTER_NEAREST)
|
||||
{
|
||||
k.create(kernelName, program,
|
||||
format("-D INTER_NEAREST -D T=%s%s", ocl::typeToStr(type),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : ""));
|
||||
opts = format("-D INTER_NEAREST -D T=%s%s -D T1=%s -D ST=%s -D cn=%d", ocl::typeToStr(type),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : "",
|
||||
ocl::typeToStr(CV_MAT_DEPTH(type)),
|
||||
ocl::typeToStr(sctype),
|
||||
cn);
|
||||
}
|
||||
else
|
||||
{
|
||||
char cvt[2][50];
|
||||
wdepth = std::max(CV_32S, depth);
|
||||
k.create(kernelName, program,
|
||||
format("-D INTER_%s -D T=%s -D WT=%s -D depth=%d -D convertToWT=%s -D convertToT=%s%s",
|
||||
interpolationMap[interpolation], ocl::typeToStr(type),
|
||||
ocl::typeToStr(CV_MAKE_TYPE(wdepth, cn)), depth,
|
||||
ocl::convertTypeStr(depth, wdepth, cn, cvt[0]),
|
||||
ocl::convertTypeStr(wdepth, depth, cn, cvt[1]),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : ""));
|
||||
opts = format("-D INTER_%s -D T=%s -D T1=%s -D ST=%s -D WT=%s -D depth=%d -D convertToWT=%s -D convertToT=%s%s -D cn=%d",
|
||||
interpolationMap[interpolation], ocl::typeToStr(type),
|
||||
ocl::typeToStr(CV_MAT_DEPTH(type)),
|
||||
ocl::typeToStr(sctype),
|
||||
ocl::typeToStr(CV_MAKE_TYPE(wdepth, cn)), depth,
|
||||
ocl::convertTypeStr(depth, wdepth, cn, cvt[0]),
|
||||
ocl::convertTypeStr(wdepth, depth, cn, cvt[1]),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : "", cn);
|
||||
}
|
||||
|
||||
k.create(kernelName, program, opts);
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
double borderBuf[] = {0, 0, 0, 0};
|
||||
scalarToRawData(borderValue, borderBuf, sctype);
|
||||
|
||||
UMat src = _src.getUMat(), M0;
|
||||
_dst.create( dsize.area() == 0 ? src.size() : dsize, src.type() );
|
||||
UMat dst = _dst.getUMat();
|
||||
@@ -3944,12 +4071,14 @@ static bool ocl_warpTransform(InputArray _src, OutputArray _dst, InputArray _M0,
|
||||
matM.convertTo(M0, doubleSupport ? CV_64F : CV_32F);
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst), ocl::KernelArg::PtrReadOnly(M0),
|
||||
ocl::KernelArg::Constant(Mat(1, 1, CV_MAKE_TYPE(wdepth, cn), borderValue)));
|
||||
ocl::KernelArg(0, 0, 0, borderBuf, CV_ELEM_SIZE(sctype)));
|
||||
|
||||
size_t globalThreads[2] = { dst.cols, dst.rows };
|
||||
return k.run(2, globalThreads, NULL, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -3957,10 +4086,9 @@ void cv::warpAffine( InputArray _src, OutputArray _dst,
|
||||
InputArray _M0, Size dsize,
|
||||
int flags, int borderType, const Scalar& borderValue )
|
||||
{
|
||||
if (ocl::useOpenCL() && _dst.isUMat() &&
|
||||
ocl_warpTransform(_src, _dst, _M0, dsize, flags, borderType,
|
||||
borderValue, OCL_OP_AFFINE))
|
||||
return;
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_warpTransform(_src, _dst, _M0, dsize, flags, borderType,
|
||||
borderValue, OCL_OP_AFFINE))
|
||||
|
||||
Mat src = _src.getMat(), M0 = _M0.getMat();
|
||||
_dst.create( dsize.area() == 0 ? src.size() : dsize, src.type() );
|
||||
@@ -4000,7 +4128,7 @@ void cv::warpAffine( InputArray _src, OutputArray _dst,
|
||||
int* adelta = &_abdelta[0], *bdelta = adelta + dst.cols;
|
||||
const int AB_BITS = MAX(10, (int)INTER_BITS);
|
||||
const int AB_SCALE = 1 << AB_BITS;
|
||||
|
||||
/*
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
int depth = src.depth();
|
||||
int channels = src.channels();
|
||||
@@ -4044,7 +4172,7 @@ void cv::warpAffine( InputArray _src, OutputArray _dst,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
*/
|
||||
for( x = 0; x < dst.cols; x++ )
|
||||
{
|
||||
adelta[x] = saturate_cast<int>(M[0]*x*AB_SCALE);
|
||||
@@ -4203,10 +4331,9 @@ void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0,
|
||||
{
|
||||
CV_Assert( _src.total() > 0 );
|
||||
|
||||
if (ocl::useOpenCL() && _dst.isUMat() &&
|
||||
ocl_warpTransform(_src, _dst, _M0, dsize, flags, borderType, borderValue,
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_warpTransform(_src, _dst, _M0, dsize, flags, borderType, borderValue,
|
||||
OCL_OP_PERSPECTIVE))
|
||||
return;
|
||||
|
||||
Mat src = _src.getMat(), M0 = _M0.getMat();
|
||||
_dst.create( dsize.area() == 0 ? src.size() : dsize, src.type() );
|
||||
@@ -4231,7 +4358,7 @@ void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0,
|
||||
|
||||
if( !(flags & WARP_INVERSE_MAP) )
|
||||
invert(matM, matM);
|
||||
|
||||
/*
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
int depth = src.depth();
|
||||
int channels = src.channels();
|
||||
@@ -4275,7 +4402,7 @@ void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
*/
|
||||
Range range(0, dst.rows);
|
||||
warpPerspectiveInvoker invoker(src, dst, M, interpolation, borderType, borderValue);
|
||||
parallel_for_(range, invoker, dst.total()/(double)(1<<16));
|
||||
|
||||
@@ -231,7 +231,7 @@ int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& r
|
||||
// Found a dupe, remove it
|
||||
std::swap(intersection[j], intersection.back());
|
||||
intersection.pop_back();
|
||||
i--; // restart check
|
||||
j--; // restart check
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ static void updateSidesCA(const std::vector<cv::Point2f> &polygon,
|
||||
cv::Point2f &sideAStartVertex, cv::Point2f &sideAEndVertex,
|
||||
cv::Point2f &sideCStartVertex, cv::Point2f &sideCEndVertex);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////// Main functions /////////////////////////////////////
|
||||
@@ -1560,4 +1560,4 @@ static bool lessOrEqual(double number1, double number2) {
|
||||
return ((number1 < number2) || (almostEqual(number1, number2)));
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
+158
-78
@@ -39,6 +39,7 @@
|
||||
//
|
||||
//M*/
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
@@ -202,6 +203,10 @@ static Moments contourMoments( const Mat& contour )
|
||||
\****************************************************************************************/
|
||||
|
||||
template<typename T, typename WT, typename MT>
|
||||
#if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 9
|
||||
// Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60196
|
||||
__attribute__((optimize("no-tree-vectorize")))
|
||||
#endif
|
||||
static void momentsInTile( const Mat& img, double* moments )
|
||||
{
|
||||
Size size = img.size();
|
||||
@@ -362,106 +367,181 @@ Moments::Moments( double _m00, double _m10, double _m01, double _m20, double _m1
|
||||
nu30 = mu30*s3; nu21 = mu21*s3; nu12 = mu12*s3; nu03 = mu03*s3;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_moments( InputArray _src, Moments& m)
|
||||
{
|
||||
const int TILE_SIZE = 32;
|
||||
const int K = 10;
|
||||
ocl::Kernel k("moments", ocl::imgproc::moments_oclsrc, format("-D TILE_SIZE=%d", TILE_SIZE));
|
||||
if( k.empty() )
|
||||
return false;
|
||||
|
||||
UMat src = _src.getUMat();
|
||||
Size sz = src.size();
|
||||
int xtiles = (sz.width + TILE_SIZE-1)/TILE_SIZE;
|
||||
int ytiles = (sz.height + TILE_SIZE-1)/TILE_SIZE;
|
||||
int ntiles = xtiles*ytiles;
|
||||
UMat umbuf(1, ntiles*K, CV_32S);
|
||||
|
||||
size_t globalsize[] = {xtiles, sz.height}, localsize[] = {1, TILE_SIZE};
|
||||
bool ok = k.args(ocl::KernelArg::ReadOnly(src),
|
||||
ocl::KernelArg::PtrWriteOnly(umbuf),
|
||||
xtiles).run(2, globalsize, localsize, true);
|
||||
if(!ok)
|
||||
return false;
|
||||
Mat mbuf = umbuf.getMat(ACCESS_READ);
|
||||
for( int i = 0; i < ntiles; i++ )
|
||||
{
|
||||
double x = (i % xtiles)*TILE_SIZE, y = (i / xtiles)*TILE_SIZE;
|
||||
const int* mom = mbuf.ptr<int>() + i*K;
|
||||
double xm = x * mom[0], ym = y * mom[0];
|
||||
|
||||
// accumulate moments computed in each tile
|
||||
|
||||
// + m00 ( = m00' )
|
||||
m.m00 += mom[0];
|
||||
|
||||
// + m10 ( = m10' + x*m00' )
|
||||
m.m10 += mom[1] + xm;
|
||||
|
||||
// + m01 ( = m01' + y*m00' )
|
||||
m.m01 += mom[2] + ym;
|
||||
|
||||
// + m20 ( = m20' + 2*x*m10' + x*x*m00' )
|
||||
m.m20 += mom[3] + x * (mom[1] * 2 + xm);
|
||||
|
||||
// + m11 ( = m11' + x*m01' + y*m10' + x*y*m00' )
|
||||
m.m11 += mom[4] + x * (mom[2] + ym) + y * mom[1];
|
||||
|
||||
// + m02 ( = m02' + 2*y*m01' + y*y*m00' )
|
||||
m.m02 += mom[5] + y * (mom[2] * 2 + ym);
|
||||
|
||||
// + m30 ( = m30' + 3*x*m20' + 3*x*x*m10' + x*x*x*m00' )
|
||||
m.m30 += mom[6] + x * (3. * mom[3] + x * (3. * mom[1] + xm));
|
||||
|
||||
// + m21 ( = m21' + x*(2*m11' + 2*y*m10' + x*m01' + x*y*m00') + y*m20')
|
||||
m.m21 += mom[7] + x * (2 * (mom[4] + y * mom[1]) + x * (mom[2] + ym)) + y * mom[3];
|
||||
|
||||
// + m12 ( = m12' + y*(2*m11' + 2*x*m01' + y*m10' + x*y*m00') + x*m02')
|
||||
m.m12 += mom[8] + y * (2 * (mom[4] + x * mom[2]) + y * (mom[1] + xm)) + x * mom[5];
|
||||
|
||||
// + m03 ( = m03' + 3*y*m02' + 3*y*y*m01' + y*y*y*m00' )
|
||||
m.m03 += mom[9] + y * (3. * mom[5] + y * (3. * mom[2] + ym));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
cv::Moments cv::moments( InputArray _src, bool binary )
|
||||
{
|
||||
const int TILE_SIZE = 32;
|
||||
Mat mat = _src.getMat();
|
||||
MomentsInTileFunc func = 0;
|
||||
uchar nzbuf[TILE_SIZE*TILE_SIZE];
|
||||
Moments m;
|
||||
int type = mat.type();
|
||||
int type = _src.type();
|
||||
int depth = CV_MAT_DEPTH( type );
|
||||
int cn = CV_MAT_CN( type );
|
||||
|
||||
if( mat.checkVector(2) >= 0 && (depth == CV_32F || depth == CV_32S))
|
||||
return contourMoments(mat);
|
||||
|
||||
Size size = mat.size();
|
||||
|
||||
if( cn > 1 )
|
||||
CV_Error( CV_StsBadArg, "Invalid image type" );
|
||||
Size size = _src.size();
|
||||
|
||||
if( size.width <= 0 || size.height <= 0 )
|
||||
return m;
|
||||
|
||||
if( binary || depth == CV_8U )
|
||||
func = momentsInTile<uchar, int, int>;
|
||||
else if( depth == CV_16U )
|
||||
func = momentsInTile<ushort, int, int64>;
|
||||
else if( depth == CV_16S )
|
||||
func = momentsInTile<short, int, int64>;
|
||||
else if( depth == CV_32F )
|
||||
func = momentsInTile<float, double, double>;
|
||||
else if( depth == CV_64F )
|
||||
func = momentsInTile<double, double, double>;
|
||||
#ifdef HAVE_OPENCL
|
||||
if( ocl::useOpenCL() && type == CV_8UC1 && !binary &&
|
||||
_src.isUMat() && ocl_moments(_src, m) )
|
||||
;
|
||||
else
|
||||
CV_Error( CV_StsUnsupportedFormat, "" );
|
||||
|
||||
Mat src0(mat);
|
||||
|
||||
for( int y = 0; y < size.height; y += TILE_SIZE )
|
||||
#endif
|
||||
{
|
||||
Size tileSize;
|
||||
tileSize.height = std::min(TILE_SIZE, size.height - y);
|
||||
Mat mat = _src.getMat();
|
||||
if( mat.checkVector(2) >= 0 && (depth == CV_32F || depth == CV_32S))
|
||||
return contourMoments(mat);
|
||||
|
||||
for( int x = 0; x < size.width; x += TILE_SIZE )
|
||||
if( cn > 1 )
|
||||
CV_Error( CV_StsBadArg, "Invalid image type (must be single-channel)" );
|
||||
|
||||
if( binary || depth == CV_8U )
|
||||
func = momentsInTile<uchar, int, int>;
|
||||
else if( depth == CV_16U )
|
||||
func = momentsInTile<ushort, int, int64>;
|
||||
else if( depth == CV_16S )
|
||||
func = momentsInTile<short, int, int64>;
|
||||
else if( depth == CV_32F )
|
||||
func = momentsInTile<float, double, double>;
|
||||
else if( depth == CV_64F )
|
||||
func = momentsInTile<double, double, double>;
|
||||
else
|
||||
CV_Error( CV_StsUnsupportedFormat, "" );
|
||||
|
||||
Mat src0(mat);
|
||||
|
||||
for( int y = 0; y < size.height; y += TILE_SIZE )
|
||||
{
|
||||
tileSize.width = std::min(TILE_SIZE, size.width - x);
|
||||
Mat src(src0, cv::Rect(x, y, tileSize.width, tileSize.height));
|
||||
Size tileSize;
|
||||
tileSize.height = std::min(TILE_SIZE, size.height - y);
|
||||
|
||||
if( binary )
|
||||
for( int x = 0; x < size.width; x += TILE_SIZE )
|
||||
{
|
||||
cv::Mat tmp(tileSize, CV_8U, nzbuf);
|
||||
cv::compare( src, 0, tmp, CV_CMP_NE );
|
||||
src = tmp;
|
||||
tileSize.width = std::min(TILE_SIZE, size.width - x);
|
||||
Mat src(src0, cv::Rect(x, y, tileSize.width, tileSize.height));
|
||||
|
||||
if( binary )
|
||||
{
|
||||
cv::Mat tmp(tileSize, CV_8U, nzbuf);
|
||||
cv::compare( src, 0, tmp, CV_CMP_NE );
|
||||
src = tmp;
|
||||
}
|
||||
|
||||
double mom[10];
|
||||
func( src, mom );
|
||||
|
||||
if(binary)
|
||||
{
|
||||
double s = 1./255;
|
||||
for( int k = 0; k < 10; k++ )
|
||||
mom[k] *= s;
|
||||
}
|
||||
|
||||
double xm = x * mom[0], ym = y * mom[0];
|
||||
|
||||
// accumulate moments computed in each tile
|
||||
|
||||
// + m00 ( = m00' )
|
||||
m.m00 += mom[0];
|
||||
|
||||
// + m10 ( = m10' + x*m00' )
|
||||
m.m10 += mom[1] + xm;
|
||||
|
||||
// + m01 ( = m01' + y*m00' )
|
||||
m.m01 += mom[2] + ym;
|
||||
|
||||
// + m20 ( = m20' + 2*x*m10' + x*x*m00' )
|
||||
m.m20 += mom[3] + x * (mom[1] * 2 + xm);
|
||||
|
||||
// + m11 ( = m11' + x*m01' + y*m10' + x*y*m00' )
|
||||
m.m11 += mom[4] + x * (mom[2] + ym) + y * mom[1];
|
||||
|
||||
// + m02 ( = m02' + 2*y*m01' + y*y*m00' )
|
||||
m.m02 += mom[5] + y * (mom[2] * 2 + ym);
|
||||
|
||||
// + m30 ( = m30' + 3*x*m20' + 3*x*x*m10' + x*x*x*m00' )
|
||||
m.m30 += mom[6] + x * (3. * mom[3] + x * (3. * mom[1] + xm));
|
||||
|
||||
// + m21 ( = m21' + x*(2*m11' + 2*y*m10' + x*m01' + x*y*m00') + y*m20')
|
||||
m.m21 += mom[7] + x * (2 * (mom[4] + y * mom[1]) + x * (mom[2] + ym)) + y * mom[3];
|
||||
|
||||
// + m12 ( = m12' + y*(2*m11' + 2*x*m01' + y*m10' + x*y*m00') + x*m02')
|
||||
m.m12 += mom[8] + y * (2 * (mom[4] + x * mom[2]) + y * (mom[1] + xm)) + x * mom[5];
|
||||
|
||||
// + m03 ( = m03' + 3*y*m02' + 3*y*y*m01' + y*y*y*m00' )
|
||||
m.m03 += mom[9] + y * (3. * mom[5] + y * (3. * mom[2] + ym));
|
||||
}
|
||||
|
||||
double mom[10];
|
||||
func( src, mom );
|
||||
|
||||
if(binary)
|
||||
{
|
||||
double s = 1./255;
|
||||
for( int k = 0; k < 10; k++ )
|
||||
mom[k] *= s;
|
||||
}
|
||||
|
||||
double xm = x * mom[0], ym = y * mom[0];
|
||||
|
||||
// accumulate moments computed in each tile
|
||||
|
||||
// + m00 ( = m00' )
|
||||
m.m00 += mom[0];
|
||||
|
||||
// + m10 ( = m10' + x*m00' )
|
||||
m.m10 += mom[1] + xm;
|
||||
|
||||
// + m01 ( = m01' + y*m00' )
|
||||
m.m01 += mom[2] + ym;
|
||||
|
||||
// + m20 ( = m20' + 2*x*m10' + x*x*m00' )
|
||||
m.m20 += mom[3] + x * (mom[1] * 2 + xm);
|
||||
|
||||
// + m11 ( = m11' + x*m01' + y*m10' + x*y*m00' )
|
||||
m.m11 += mom[4] + x * (mom[2] + ym) + y * mom[1];
|
||||
|
||||
// + m02 ( = m02' + 2*y*m01' + y*y*m00' )
|
||||
m.m02 += mom[5] + y * (mom[2] * 2 + ym);
|
||||
|
||||
// + m30 ( = m30' + 3*x*m20' + 3*x*x*m10' + x*x*x*m00' )
|
||||
m.m30 += mom[6] + x * (3. * mom[3] + x * (3. * mom[1] + xm));
|
||||
|
||||
// + m21 ( = m21' + x*(2*m11' + 2*y*m10' + x*m01' + x*y*m00') + y*m20')
|
||||
m.m21 += mom[7] + x * (2 * (mom[4] + y * mom[1]) + x * (mom[2] + ym)) + y * mom[3];
|
||||
|
||||
// + m12 ( = m12' + y*(2*m11' + 2*x*m01' + y*m10' + x*y*m00') + x*m02')
|
||||
m.m12 += mom[8] + y * (2 * (mom[4] + x * mom[2]) + y * (mom[1] + xm)) + x * mom[5];
|
||||
|
||||
// + m03 ( = m03' + 3*y*m02' + 3*y*y*m01' + y*y*y*m00' )
|
||||
m.m03 += mom[9] + y * (3. * mom[5] + y * (3. * mom[2] + ym));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+205
-29
@@ -43,6 +43,7 @@
|
||||
#include "precomp.hpp"
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
/****************************************************************************************\
|
||||
Basic Morphological Operations: Erosion & Dilation
|
||||
@@ -1283,11 +1284,131 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_morphology_op(InputArray _src, OutputArray _dst, InputArray _kernel, Size &ksize, const Point anchor, int iterations, int op)
|
||||
{
|
||||
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
||||
|
||||
if (_src.depth() == CV_64F && !doubleSupport)
|
||||
return false;
|
||||
|
||||
UMat kernel8U;
|
||||
_kernel.getUMat().convertTo(kernel8U, CV_8U);
|
||||
UMat kernel = kernel8U.reshape(1, 1);
|
||||
|
||||
bool rectKernel = true;
|
||||
for(int i = 0; i < kernel.rows * kernel.cols; ++i)
|
||||
if(kernel.getMat(ACCESS_READ).at<uchar>(i) != 1)
|
||||
rectKernel = false;
|
||||
|
||||
UMat src = _src.getUMat();
|
||||
|
||||
#ifdef ANDROID
|
||||
size_t localThreads[3] = {16, 8, 1};
|
||||
#else
|
||||
size_t localThreads[3] = {16, 16, 1};
|
||||
#endif
|
||||
size_t globalThreads[3] = {(src.cols + localThreads[0] - 1) / localThreads[0] *localThreads[0], (src.rows + localThreads[1] - 1) / localThreads[1] *localThreads[1], 1};
|
||||
|
||||
if(localThreads[0]*localThreads[1] * 2 < (localThreads[0] + ksize.width - 1) * (localThreads[1] + ksize.height - 1))
|
||||
return false;
|
||||
|
||||
char compile_option[128];
|
||||
static const char* op2str[] = {"ERODE", "DILATE"};
|
||||
sprintf(compile_option, "-D RADIUSX=%d -D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D %s %s %s -D GENTYPE=%s -D DEPTH_%d",
|
||||
anchor.x, anchor.y, (int)localThreads[0], (int)localThreads[1], op2str[op], doubleSupport?"-D DOUBLE_SUPPORT" :"", rectKernel?"-D RECTKERNEL":"",
|
||||
ocl::typeToStr(_src.type()), _src.depth() );
|
||||
|
||||
std::vector<ocl::Kernel> kernels;
|
||||
for(int i = 0; i<iterations; i++)
|
||||
{
|
||||
ocl::Kernel k( "morph", ocl::imgproc::morph_oclsrc, compile_option);
|
||||
if (k.empty())
|
||||
return false;
|
||||
kernels.push_back(k);
|
||||
}
|
||||
|
||||
_dst.create(src.size(), src.type());
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
if( iterations== 1 && src.u != dst.u)
|
||||
{
|
||||
Size wholesize;
|
||||
Point ofs;
|
||||
src.locateROI(wholesize, ofs);
|
||||
int wholecols = wholesize.width, wholerows = wholesize.height;
|
||||
|
||||
int idxArg = 0;
|
||||
idxArg = kernels[0].set(idxArg, ocl::KernelArg::ReadOnlyNoSize(src));
|
||||
idxArg = kernels[0].set(idxArg, ocl::KernelArg::WriteOnlyNoSize(dst));
|
||||
idxArg = kernels[0].set(idxArg, ofs.x);
|
||||
idxArg = kernels[0].set(idxArg, ofs.y);
|
||||
idxArg = kernels[0].set(idxArg, src.cols);
|
||||
idxArg = kernels[0].set(idxArg, src.rows);
|
||||
idxArg = kernels[0].set(idxArg, ocl::KernelArg::PtrReadOnly(kernel));
|
||||
idxArg = kernels[0].set(idxArg, wholecols);
|
||||
idxArg = kernels[0].set(idxArg, wholerows);
|
||||
|
||||
return kernels[0].run(2, globalThreads, localThreads, false);
|
||||
}
|
||||
|
||||
for(int i = 0; i< iterations; i++)
|
||||
{
|
||||
UMat source;
|
||||
Size wholesize;
|
||||
Point ofs;
|
||||
if( i == 0)
|
||||
{
|
||||
int cols = src.cols, rows = src.rows;
|
||||
src.locateROI(wholesize,ofs);
|
||||
src.adjustROI(ofs.y, wholesize.height - rows - ofs.y, ofs.x, wholesize.width - cols - ofs.x);
|
||||
src.copyTo(source);
|
||||
src.adjustROI(-ofs.y, -wholesize.height + rows + ofs.y, -ofs.x, -wholesize.width + cols + ofs.x);
|
||||
source.adjustROI(-ofs.y, -wholesize.height + rows + ofs.y, -ofs.x, -wholesize.width + cols + ofs.x);
|
||||
}
|
||||
else
|
||||
{
|
||||
int cols = dst.cols, rows = dst.rows;
|
||||
dst.locateROI(wholesize,ofs);
|
||||
dst.adjustROI(ofs.y, wholesize.height - rows - ofs.y, ofs.x, wholesize.width - cols - ofs.x);
|
||||
dst.copyTo(source);
|
||||
dst.adjustROI(-ofs.y, -wholesize.height + rows + ofs.y, -ofs.x, -wholesize.width + cols + ofs.x);
|
||||
source.adjustROI(-ofs.y, -wholesize.height + rows + ofs.y, -ofs.x, -wholesize.width + cols + ofs.x);
|
||||
}
|
||||
|
||||
source.locateROI(wholesize, ofs);
|
||||
int wholecols = wholesize.width, wholerows = wholesize.height;
|
||||
|
||||
int idxArg = 0;
|
||||
idxArg = kernels[i].set(idxArg, ocl::KernelArg::ReadOnlyNoSize(source));
|
||||
idxArg = kernels[i].set(idxArg, ocl::KernelArg::WriteOnlyNoSize(dst));
|
||||
idxArg = kernels[i].set(idxArg, ofs.x);
|
||||
idxArg = kernels[i].set(idxArg, ofs.y);
|
||||
idxArg = kernels[i].set(idxArg, source.cols);
|
||||
idxArg = kernels[i].set(idxArg, source.rows);
|
||||
idxArg = kernels[i].set(idxArg, ocl::KernelArg::PtrReadOnly(kernel));
|
||||
idxArg = kernels[i].set(idxArg, wholecols);
|
||||
idxArg = kernels[i].set(idxArg, wholerows);
|
||||
|
||||
if (!kernels[i].run(2, globalThreads, localThreads, false))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void morphOp( int op, InputArray _src, OutputArray _dst,
|
||||
InputArray _kernel,
|
||||
Point anchor, int iterations,
|
||||
int borderType, const Scalar& borderValue )
|
||||
{
|
||||
#ifdef HAVE_OPENCL
|
||||
int src_type = _src.type(), dst_type = _dst.type(),
|
||||
src_cn = CV_MAT_CN(src_type), src_depth = CV_MAT_DEPTH(src_type);
|
||||
#endif
|
||||
|
||||
Mat kernel = _kernel.getMat();
|
||||
Size ksize = kernel.data ? kernel.size() : Size(3,3);
|
||||
anchor = normalizeAnchor(anchor, ksize);
|
||||
@@ -1299,14 +1420,9 @@ static void morphOp( int op, InputArray _src, OutputArray _dst,
|
||||
return;
|
||||
#endif
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
_dst.create( src.size(), src.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
if( iterations == 0 || kernel.rows*kernel.cols == 1 )
|
||||
{
|
||||
src.copyTo(dst);
|
||||
_src.copyTo(_dst);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1326,6 +1442,18 @@ static void morphOp( int op, InputArray _src, OutputArray _dst,
|
||||
iterations = 1;
|
||||
}
|
||||
|
||||
CV_OCL_RUN(_dst.isUMat() && _src.size() == _dst.size() && src_type == dst_type &&
|
||||
_src.dims() <= 2 && (src_cn == 1 || src_cn == 4) && anchor.x == -1 && anchor.y == -1 &&
|
||||
(src_depth == CV_8U || src_depth == CV_32F || src_depth == CV_64F ) &&
|
||||
borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue() &&
|
||||
(op == MORPH_ERODE || op == MORPH_DILATE),
|
||||
ocl_morphology_op(_src, _dst, kernel, ksize, anchor, iterations, op) )
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
_dst.create( src.size(), src.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
int nStripes = 1;
|
||||
#if defined HAVE_TEGRA_OPTIMIZATION
|
||||
if (src.data != dst.data && iterations == 1 && //NOTE: threads are not used for inplace processing
|
||||
@@ -1362,49 +1490,97 @@ void cv::dilate( InputArray src, OutputArray dst, InputArray kernel,
|
||||
morphOp( MORPH_DILATE, src, dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
}
|
||||
|
||||
|
||||
void cv::morphologyEx( InputArray _src, OutputArray _dst, int op,
|
||||
InputArray kernel, Point anchor, int iterations,
|
||||
int borderType, const Scalar& borderValue )
|
||||
{
|
||||
Mat src = _src.getMat(), temp;
|
||||
_dst.create(src.size(), src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
int src_type = _src.type(), dst_type = _dst.type(),
|
||||
src_cn = CV_MAT_CN(src_type), src_depth = CV_MAT_DEPTH(src_type);
|
||||
|
||||
bool use_opencl = cv::ocl::useOpenCL() && _src.isUMat() && _src.size() == _dst.size() && src_type == dst_type &&
|
||||
_src.dims()<=2 && (src_cn == 1 || src_cn == 4) && (anchor.x == -1) && (anchor.y == -1) &&
|
||||
(src_depth == CV_8U || src_depth == CV_32F || src_depth == CV_64F ) &&
|
||||
(borderType == cv::BORDER_CONSTANT) && (borderValue == morphologyDefaultBorderValue());
|
||||
|
||||
_dst.create(_src.size(), _src.type());
|
||||
Mat src, dst, temp;
|
||||
UMat usrc, udst, utemp;
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case MORPH_ERODE:
|
||||
erode( src, dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
erode( _src, _dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
break;
|
||||
case MORPH_DILATE:
|
||||
dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
dilate( _src, _dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
break;
|
||||
case MORPH_OPEN:
|
||||
erode( src, dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
dilate( dst, dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
erode( _src, _dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
dilate( _dst, _dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
break;
|
||||
case CV_MOP_CLOSE:
|
||||
dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
erode( dst, dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
dilate( _src, _dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
erode( _dst, _dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
break;
|
||||
case CV_MOP_GRADIENT:
|
||||
erode( src, temp, kernel, anchor, iterations, borderType, borderValue );
|
||||
dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
dst -= temp;
|
||||
erode( _src, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel, anchor, iterations, borderType, borderValue );
|
||||
dilate( _src, _dst, kernel, anchor, iterations, borderType, borderValue );
|
||||
if(use_opencl)
|
||||
{
|
||||
udst = _dst.getUMat();
|
||||
subtract(udst, utemp, udst);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = _dst.getMat();
|
||||
dst -= temp;
|
||||
}
|
||||
break;
|
||||
case CV_MOP_TOPHAT:
|
||||
if( src.data != dst.data )
|
||||
temp = dst;
|
||||
erode( src, temp, kernel, anchor, iterations, borderType, borderValue );
|
||||
dilate( temp, temp, kernel, anchor, iterations, borderType, borderValue );
|
||||
dst = src - temp;
|
||||
if(use_opencl)
|
||||
{
|
||||
usrc = _src.getUMat();
|
||||
udst = _dst.getUMat();
|
||||
if( usrc.u != udst.u )
|
||||
utemp = udst;
|
||||
}
|
||||
else
|
||||
{
|
||||
src = _src.getMat();
|
||||
dst = _dst.getMat();
|
||||
if( src.data != dst.data )
|
||||
temp = dst;
|
||||
}
|
||||
erode( _src, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel, anchor, iterations, borderType, borderValue );
|
||||
dilate( use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel,
|
||||
anchor, iterations, borderType, borderValue );
|
||||
if(use_opencl)
|
||||
subtract(usrc, utemp, udst);
|
||||
else
|
||||
dst = src - temp;
|
||||
break;
|
||||
case CV_MOP_BLACKHAT:
|
||||
if( src.data != dst.data )
|
||||
temp = dst;
|
||||
dilate( src, temp, kernel, anchor, iterations, borderType, borderValue );
|
||||
erode( temp, temp, kernel, anchor, iterations, borderType, borderValue );
|
||||
dst = temp - src;
|
||||
if(use_opencl)
|
||||
{
|
||||
usrc = _src.getUMat();
|
||||
udst = _dst.getUMat();
|
||||
if( usrc.u != udst.u )
|
||||
utemp = udst;
|
||||
}
|
||||
else
|
||||
{
|
||||
src = _src.getMat();
|
||||
dst = _dst.getMat();
|
||||
if( src.data != dst.data )
|
||||
temp = dst;
|
||||
}
|
||||
dilate( _src, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel, anchor, iterations, borderType, borderValue );
|
||||
erode( use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel,
|
||||
anchor, iterations, borderType, borderValue );
|
||||
if(use_opencl)
|
||||
subtract(utemp, usrc, udst);
|
||||
else
|
||||
dst = temp - src;
|
||||
break;
|
||||
default:
|
||||
CV_Error( CV_StsBadArg, "unknown morphological operation" );
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
// Copyright (C) 2014, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#ifdef DOUBLE_SUPPORT
|
||||
#ifdef cl_amd_fp64
|
||||
#pragma OPENCL EXTENSION cl_amd_fp64:enable
|
||||
#elif defined (cl_khr_fp64)
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#endif
|
||||
#endif
|
||||
|
||||
__kernel void accumulate(__global const uchar * srcptr, int src_step, int src_offset,
|
||||
#ifdef ACCUMULATE_PRODUCT
|
||||
__global const uchar * src2ptr, int src2_step, int src2_offset,
|
||||
#endif
|
||||
__global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols
|
||||
#ifdef ACCUMULATE_WEIGHTED
|
||||
, dstT alpha
|
||||
#endif
|
||||
#ifdef HAVE_MASK
|
||||
, __global const uchar * mask, int mask_step, int mask_offset
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
int src_index = mad24(y, src_step, src_offset + x * cn * (int)sizeof(srcT));
|
||||
#ifdef HAVE_MASK
|
||||
int mask_index = mad24(y, mask_step, mask_offset + x);
|
||||
mask += mask_index;
|
||||
#endif
|
||||
int dst_index = mad24(y, dst_step, dst_offset + x * cn * (int)sizeof(dstT));
|
||||
|
||||
__global const srcT * src = (__global const srcT *)(srcptr + src_index);
|
||||
#ifdef ACCUMULATE_PRODUCT
|
||||
int src2_index = mad24(y, src2_step, src2_offset + x * cn * (int)sizeof(srcT));
|
||||
__global const srcT * src2 = (__global const srcT *)(src2ptr + src2_index);
|
||||
#endif
|
||||
__global dstT * dst = (__global dstT *)(dstptr + dst_index);
|
||||
|
||||
#pragma unroll
|
||||
for (int c = 0; c < cn; ++c)
|
||||
#ifdef HAVE_MASK
|
||||
if (mask[0])
|
||||
#endif
|
||||
#ifdef ACCUMULATE
|
||||
dst[c] += src[c];
|
||||
#elif defined ACCUMULATE_SQUARE
|
||||
dst[c] += src[c] * src[c];
|
||||
#elif defined ACCUMULATE_PRODUCT
|
||||
dst[c] += src[c] * src2[c];
|
||||
#elif defined ACCUMULATE_WEIGHTED
|
||||
dst[c] = (1 - alpha) * dst[c] + src[c] * alpha;
|
||||
#else
|
||||
#error "Unknown accumulation type"
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/*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) 2010-2013, Advanced Micro Devices, 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*/
|
||||
|
||||
#ifdef DOUBLE_SUPPORT
|
||||
#ifdef cl_amd_fp64
|
||||
#pragma OPENCL EXTENSION cl_amd_fp64:enable
|
||||
#elif defined (cl_khr_fp64)
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BORDER_CONSTANT
|
||||
#elif defined BORDER_REPLICATE
|
||||
#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \
|
||||
{ \
|
||||
x = max(min(x, maxX - 1), minX); \
|
||||
y = max(min(y, maxY - 1), minY); \
|
||||
}
|
||||
#elif defined BORDER_WRAP
|
||||
#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \
|
||||
{ \
|
||||
if (x < minX) \
|
||||
x -= ((x - maxX + 1) / maxX) * maxX; \
|
||||
if (x >= maxX) \
|
||||
x %= maxX; \
|
||||
if (y < minY) \
|
||||
y -= ((y - maxY + 1) / maxY) * maxY; \
|
||||
if (y >= maxY) \
|
||||
y %= maxY; \
|
||||
}
|
||||
#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT_101)
|
||||
#define EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, delta) \
|
||||
{ \
|
||||
if (maxX - minX == 1) \
|
||||
x = minX; \
|
||||
else \
|
||||
do \
|
||||
{ \
|
||||
if (x < minX) \
|
||||
x = minX - (x - minX) - 1 + delta; \
|
||||
else \
|
||||
x = maxX - 1 - (x - maxX) - delta; \
|
||||
} \
|
||||
while (x >= maxX || x < minX); \
|
||||
\
|
||||
if (maxY - minY == 1) \
|
||||
y = minY; \
|
||||
else \
|
||||
do \
|
||||
{ \
|
||||
if (y < minY) \
|
||||
y = minY - (y - minY) - 1 + delta; \
|
||||
else \
|
||||
y = maxY - 1 - (y - maxY) - delta; \
|
||||
} \
|
||||
while (y >= maxY || y < minY); \
|
||||
}
|
||||
#ifdef BORDER_REFLECT
|
||||
#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, 0)
|
||||
#elif defined(BORDER_REFLECT_101)
|
||||
#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, 1)
|
||||
#endif
|
||||
#else
|
||||
#error No extrapolation method
|
||||
#endif
|
||||
|
||||
#define noconvert
|
||||
|
||||
#ifdef SQR
|
||||
#define PROCESS_ELEM(value) (value * value)
|
||||
#else
|
||||
#define PROCESS_ELEM(value) value
|
||||
#endif
|
||||
|
||||
struct RectCoords
|
||||
{
|
||||
int x1, y1, x2, y2;
|
||||
};
|
||||
|
||||
inline WT readSrcPixel(int2 pos, __global const uchar * srcptr, int src_step, const struct RectCoords srcCoords)
|
||||
{
|
||||
#ifdef BORDER_ISOLATED
|
||||
if (pos.x >= srcCoords.x1 && pos.y >= srcCoords.y1 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2)
|
||||
#else
|
||||
if (pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2)
|
||||
#endif
|
||||
{
|
||||
int src_index = mad24(pos.y, src_step, pos.x * (int)sizeof(ST));
|
||||
WT value = convertToWT(*(__global const ST *)(srcptr + src_index));
|
||||
|
||||
return PROCESS_ELEM(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef BORDER_CONSTANT
|
||||
return (WT)(0);
|
||||
#else
|
||||
int selected_col = pos.x, selected_row = pos.y;
|
||||
|
||||
EXTRAPOLATE(selected_col, selected_row,
|
||||
#ifdef BORDER_ISOLATED
|
||||
srcCoords.x1, srcCoords.y1,
|
||||
#else
|
||||
0, 0,
|
||||
#endif
|
||||
srcCoords.x2, srcCoords.y2);
|
||||
|
||||
int src_index = mad24(selected_row, src_step, selected_col * (int)sizeof(ST));
|
||||
WT value = convertToWT(*(__global const ST *)(srcptr + src_index));
|
||||
|
||||
return PROCESS_ELEM(value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void boxFilter(__global const uchar * srcptr, int src_step, int srcOffsetX, int srcOffsetY, int srcEndX, int srcEndY,
|
||||
__global uchar * dstptr, int dst_step, int dst_offset, int rows, int cols
|
||||
#ifdef NORMALIZE
|
||||
, float alpha
|
||||
#endif
|
||||
)
|
||||
{
|
||||
const struct RectCoords srcCoords = { srcOffsetX, srcOffsetY, srcEndX, srcEndY }; // for non-isolated border: offsetX, offsetY, wholeX, wholeY
|
||||
|
||||
int x = get_local_id(0) + (LOCAL_SIZE_X - (KERNEL_SIZE_X - 1)) * get_group_id(0) - ANCHOR_X;
|
||||
int y = get_global_id(1) * BLOCK_SIZE_Y;
|
||||
int local_id = get_local_id(0);
|
||||
|
||||
WT data[KERNEL_SIZE_Y];
|
||||
__local WT sumOfCols[LOCAL_SIZE_X];
|
||||
int2 srcPos = (int2)(srcCoords.x1 + x, srcCoords.y1 + y - ANCHOR_Y);
|
||||
|
||||
#pragma unroll
|
||||
for (int sy = 0; sy < KERNEL_SIZE_Y; sy++, srcPos.y++)
|
||||
data[sy] = readSrcPixel(srcPos, srcptr, src_step, srcCoords);
|
||||
|
||||
WT tmp_sum = (WT)(0);
|
||||
#pragma unroll
|
||||
for (int sy = 0; sy < KERNEL_SIZE_Y; sy++)
|
||||
tmp_sum += data[sy];
|
||||
|
||||
sumOfCols[local_id] = tmp_sum;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
int dst_index = mad24(y, dst_step, x * (int)sizeof(DT) + dst_offset);
|
||||
__global DT * dst = (__global DT *)(dstptr + dst_index);
|
||||
|
||||
int sy_index = 0; // current index in data[] array
|
||||
for (int i = 0, stepY = min(rows - y, BLOCK_SIZE_Y); i < stepY; ++i)
|
||||
{
|
||||
if (local_id >= ANCHOR_X && local_id < LOCAL_SIZE_X - (KERNEL_SIZE_X - 1 - ANCHOR_X) &&
|
||||
x >= 0 && x < cols)
|
||||
{
|
||||
WT total_sum = (WT)(0);
|
||||
|
||||
#pragma unroll
|
||||
for (int sx = 0; sx < KERNEL_SIZE_X; sx++)
|
||||
total_sum += sumOfCols[local_id + sx - ANCHOR_X];
|
||||
|
||||
#ifdef NORMALIZE
|
||||
dst[0] = convertToDT((WT)(alpha) * total_sum);
|
||||
#else
|
||||
dst[0] = convertToDT(total_sum);
|
||||
#endif
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
tmp_sum = sumOfCols[local_id];
|
||||
tmp_sum -= data[sy_index];
|
||||
|
||||
data[sy_index] = readSrcPixel(srcPos, srcptr, src_step, srcCoords);
|
||||
srcPos.y++;
|
||||
|
||||
tmp_sum += data[sy_index];
|
||||
sumOfCols[local_id] = tmp_sum;
|
||||
|
||||
sy_index = sy_index + 1 < KERNEL_SIZE_Y ? sy_index + 1 : 0;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
dst = (__global DT *)((__global uchar *)dst + dst_step);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
// Jia Haipeng, jiahaipeng95@gmail.com
|
||||
// Xu Pang, pangxu010@163.com
|
||||
// Wenju He, wenju@multicorewareinc.com
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
|
||||
#define OUT_OF_RANGE -1
|
||||
|
||||
#if histdims == 1
|
||||
|
||||
__kernel void calcLUT(__global const uchar * histptr, int hist_step, int hist_offset, int hist_bins,
|
||||
__global int * lut, float scale, __constant float * ranges)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
float value = convert_float(x);
|
||||
|
||||
if (value > ranges[1] || value < ranges[0])
|
||||
lut[x] = OUT_OF_RANGE;
|
||||
else
|
||||
{
|
||||
float lb = ranges[0], ub = ranges[1], gap = (ub - lb) / hist_bins;
|
||||
value -= lb;
|
||||
int bin = convert_int_sat_rtn(value / gap);
|
||||
|
||||
if (bin >= hist_bins)
|
||||
lut[x] = OUT_OF_RANGE;
|
||||
else
|
||||
{
|
||||
int hist_index = mad24(hist_step, bin, hist_offset);
|
||||
__global const float * hist = (__global const float *)(histptr + hist_index);
|
||||
|
||||
lut[x] = (int)convert_uchar_sat_rte(hist[0] * scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void LUT(__global const uchar * src, int src_step, int src_offset,
|
||||
__constant int * lut,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
int src_index = mad24(y, src_step, src_offset + x * scn);
|
||||
int dst_index = mad24(y, dst_step, dst_offset + x);
|
||||
|
||||
int value = lut[src[src_index]];
|
||||
dst[dst_index] = value == OUT_OF_RANGE ? 0 : convert_uchar(value);
|
||||
}
|
||||
}
|
||||
|
||||
#elif histdims == 2
|
||||
|
||||
__kernel void calcLUT(int hist_bins, __global int * lut, int lut_offset,
|
||||
__constant float * ranges, int roffset)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
float value = convert_float(x);
|
||||
|
||||
ranges += roffset;
|
||||
lut += lut_offset;
|
||||
|
||||
if (value > ranges[1] || value < ranges[0])
|
||||
lut[x] = OUT_OF_RANGE;
|
||||
else
|
||||
{
|
||||
float lb = ranges[0], ub = ranges[1], gap = (ub - lb) / hist_bins;
|
||||
value -= lb;
|
||||
int bin = convert_int_sat_rtn(value / gap);
|
||||
|
||||
lut[x] = bin >= hist_bins ? OUT_OF_RANGE : bin;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void LUT(__global const uchar * src1, int src1_step, int src1_offset,
|
||||
__global const uchar * src2, int src2_step, int src2_offset,
|
||||
__global const uchar * histptr, int hist_step, int hist_offset,
|
||||
__constant int * lut, float scale,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
int src1_index = mad24(y, src1_step, src1_offset + x * scn1);
|
||||
int src2_index = mad24(y, src2_step, src2_offset + x * scn2);
|
||||
int dst_index = mad24(y, dst_step, dst_offset + x);
|
||||
|
||||
int bin1 = lut[src1[src1_index]];
|
||||
int bin2 = lut[src2[src2_index] + 256];
|
||||
dst[dst_index] = bin1 == OUT_OF_RANGE || bin2 == OUT_OF_RANGE ? 0 :
|
||||
convert_uchar_sat_rte(*(__global const float *)(histptr +
|
||||
mad24(hist_step, bin1, hist_offset + bin2 * (int)sizeof(float))) * scale);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#error "(nimages <= 2) should be true"
|
||||
#endif
|
||||
@@ -0,0 +1,514 @@
|
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Peng Xiao, pengxiao@multicorewareinc.com
|
||||
//
|
||||
// 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*/
|
||||
|
||||
// Smoothing perpendicular to the derivative direction with a triangle filter
|
||||
// only support 3x3 Sobel kernel
|
||||
// h (-1) = 1, h (0) = 2, h (1) = 1
|
||||
// h'(-1) = -1, h'(0) = 0, h'(1) = 1
|
||||
// thus sobel 2D operator can be calculated as:
|
||||
// h'(x, y) = h'(x)h(y) for x direction
|
||||
//
|
||||
// src input 8bit single channel image data
|
||||
// dx_buf output dx buffer
|
||||
// dy_buf output dy buffer
|
||||
|
||||
__kernel void __attribute__((reqd_work_group_size(16, 16, 1)))
|
||||
calcSobelRowPass
|
||||
(__global const uchar * src, int src_step, int src_offset, int rows, int cols,
|
||||
__global uchar * dx_buf, int dx_buf_step, int dx_buf_offset,
|
||||
__global uchar * dy_buf, int dy_buf_step, int dy_buf_offset)
|
||||
{
|
||||
int gidx = get_global_id(0);
|
||||
int gidy = get_global_id(1);
|
||||
|
||||
int lidx = get_local_id(0);
|
||||
int lidy = get_local_id(1);
|
||||
|
||||
__local int smem[16][18];
|
||||
|
||||
smem[lidy][lidx + 1] = src[mad24(src_step, min(gidy, rows - 1), gidx + src_offset)];
|
||||
if (lidx == 0)
|
||||
{
|
||||
smem[lidy][0] = src[mad24(src_step, min(gidy, rows - 1), max(gidx - 1, 0) + src_offset)];
|
||||
smem[lidy][17] = src[mad24(src_step, min(gidy, rows - 1), min(gidx + 16, cols - 1) + src_offset)];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (gidy < rows && gidx < cols)
|
||||
{
|
||||
*(__global short *)(dx_buf + mad24(gidy, dx_buf_step, gidx * (int)sizeof(short) + dx_buf_offset)) =
|
||||
smem[lidy][lidx + 2] - smem[lidy][lidx];
|
||||
*(__global short *)(dy_buf + mad24(gidy, dy_buf_step, gidx * (int)sizeof(short) + dy_buf_offset)) =
|
||||
smem[lidy][lidx] + 2 * smem[lidy][lidx + 1] + smem[lidy][lidx + 2];
|
||||
}
|
||||
}
|
||||
|
||||
inline int calc(short x, short y)
|
||||
{
|
||||
#ifdef L2GRAD
|
||||
return x * x + y * y;
|
||||
#else
|
||||
return (x >= 0 ? x : -x) + (y >= 0 ? y : -y);
|
||||
#endif
|
||||
}
|
||||
|
||||
// calculate the magnitude of the filter pass combining both x and y directions
|
||||
// This is the non-buffered version(non-3x3 sobel)
|
||||
//
|
||||
// dx_buf dx buffer, calculated from calcSobelRowPass
|
||||
// dy_buf dy buffer, calculated from calcSobelRowPass
|
||||
// dx direvitive in x direction output
|
||||
// dy direvitive in y direction output
|
||||
// mag magnitude direvitive of xy output
|
||||
|
||||
__kernel void calcMagnitude(__global const uchar * dxptr, int dx_step, int dx_offset,
|
||||
__global const uchar * dyptr, int dy_step, int dy_offset,
|
||||
__global uchar * magptr, int mag_step, int mag_offset, int rows, int cols)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (y < rows && x < cols)
|
||||
{
|
||||
int dx_index = mad24(dx_step, y, x * (int)sizeof(short) + dx_offset);
|
||||
int dy_index = mad24(dy_step, y, x * (int)sizeof(short) + dy_offset);
|
||||
int mag_index = mad24(mag_step, y + 1, (x + 1) * (int)sizeof(int) + mag_offset);
|
||||
|
||||
__global const short * dx = (__global const short *)(dxptr + dx_index);
|
||||
__global const short * dy = (__global const short *)(dyptr + dy_index);
|
||||
__global int * mag = (__global int *)(magptr + mag_index);
|
||||
|
||||
mag[0] = calc(dx[0], dy[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the magnitude of the filter pass combining both x and y directions
|
||||
// This is the buffered version(3x3 sobel)
|
||||
//
|
||||
// dx_buf dx buffer, calculated from calcSobelRowPass
|
||||
// dy_buf dy buffer, calculated from calcSobelRowPass
|
||||
// dx direvitive in x direction output
|
||||
// dy direvitive in y direction output
|
||||
// mag magnitude direvitive of xy output
|
||||
__kernel void __attribute__((reqd_work_group_size(16, 16, 1)))
|
||||
calcMagnitude_buf
|
||||
(__global const short * dx_buf, int dx_buf_step, int dx_buf_offset,
|
||||
__global const short * dy_buf, int dy_buf_step, int dy_buf_offset,
|
||||
__global short * dx, int dx_step, int dx_offset,
|
||||
__global short * dy, int dy_step, int dy_offset,
|
||||
__global int * mag, int mag_step, int mag_offset,
|
||||
int rows, int cols)
|
||||
{
|
||||
dx_buf_step /= sizeof(*dx_buf);
|
||||
dx_buf_offset /= sizeof(*dx_buf);
|
||||
dy_buf_step /= sizeof(*dy_buf);
|
||||
dy_buf_offset /= sizeof(*dy_buf);
|
||||
dx_step /= sizeof(*dx);
|
||||
dx_offset /= sizeof(*dx);
|
||||
dy_step /= sizeof(*dy);
|
||||
dy_offset /= sizeof(*dy);
|
||||
mag_step /= sizeof(*mag);
|
||||
mag_offset /= sizeof(*mag);
|
||||
|
||||
int gidx = get_global_id(0);
|
||||
int gidy = get_global_id(1);
|
||||
|
||||
int lidx = get_local_id(0);
|
||||
int lidy = get_local_id(1);
|
||||
|
||||
__local short sdx[18][16];
|
||||
__local short sdy[18][16];
|
||||
|
||||
sdx[lidy + 1][lidx] = dx_buf[gidx + min(gidy, rows - 1) * dx_buf_step + dx_buf_offset];
|
||||
sdy[lidy + 1][lidx] = dy_buf[gidx + min(gidy, rows - 1) * dy_buf_step + dy_buf_offset];
|
||||
if (lidy == 0)
|
||||
{
|
||||
sdx[0][lidx] = dx_buf[gidx + min(max(gidy - 1, 0), rows - 1) * dx_buf_step + dx_buf_offset];
|
||||
sdx[17][lidx] = dx_buf[gidx + min(gidy + 16, rows - 1) * dx_buf_step + dx_buf_offset];
|
||||
|
||||
sdy[0][lidx] = dy_buf[gidx + min(max(gidy - 1, 0), rows - 1) * dy_buf_step + dy_buf_offset];
|
||||
sdy[17][lidx] = dy_buf[gidx + min(gidy + 16, rows - 1) * dy_buf_step + dy_buf_offset];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (gidx < cols && gidy < rows)
|
||||
{
|
||||
short x = sdx[lidy][lidx] + 2 * sdx[lidy + 1][lidx] + sdx[lidy + 2][lidx];
|
||||
short y = -sdy[lidy][lidx] + sdy[lidy + 2][lidx];
|
||||
|
||||
dx[gidx + gidy * dx_step + dx_offset] = x;
|
||||
dy[gidx + gidy * dy_step + dy_offset] = y;
|
||||
|
||||
mag[(gidx + 1) + (gidy + 1) * mag_step + mag_offset] = calc(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0.4142135623730950488016887242097 is tan(22.5)
|
||||
|
||||
#define CANNY_SHIFT 15
|
||||
#define TG22 (int)(0.4142135623730950488016887242097f*(1<<CANNY_SHIFT) + 0.5f)
|
||||
|
||||
// First pass of edge detection and non-maximum suppression
|
||||
// edgetype is set to for each pixel:
|
||||
// 0 - below low thres, not an edge
|
||||
// 1 - maybe an edge
|
||||
// 2 - is an edge, either magnitude is greater than high thres, or
|
||||
// Given estimates of the image gradients, a search is then carried out
|
||||
// to determine if the gradient magnitude assumes a local maximum in the gradient direction.
|
||||
// if the rounded gradient angle is zero degrees (i.e. the edge is in the north-south direction) the point will be considered to be on the edge if its gradient magnitude is greater than the magnitudes in the west and east directions,
|
||||
// if the rounded gradient angle is 90 degrees (i.e. the edge is in the east-west direction) the point will be considered to be on the edge if its gradient magnitude is greater than the magnitudes in the north and south directions,
|
||||
// if the rounded gradient angle is 135 degrees (i.e. the edge is in the north east-south west direction) the point will be considered to be on the edge if its gradient magnitude is greater than the magnitudes in the north west and south east directions,
|
||||
// if the rounded gradient angle is 45 degrees (i.e. the edge is in the north west-south east direction)the point will be considered to be on the edge if its gradient magnitude is greater than the magnitudes in the north east and south west directions.
|
||||
//
|
||||
// dx, dy direvitives of x and y direction
|
||||
// mag magnitudes calculated from calcMagnitude function
|
||||
// map output containing raw edge types
|
||||
|
||||
__kernel void __attribute__((reqd_work_group_size(16,16,1)))
|
||||
calcMap(
|
||||
__global const uchar * dx, int dx_step, int dx_offset,
|
||||
__global const uchar * dy, int dy_step, int dy_offset,
|
||||
__global const uchar * mag, int mag_step, int mag_offset,
|
||||
__global uchar * map, int map_step, int map_offset,
|
||||
int rows, int cols, int low_thresh, int high_thresh)
|
||||
{
|
||||
__local int smem[18][18];
|
||||
|
||||
int gidx = get_global_id(0);
|
||||
int gidy = get_global_id(1);
|
||||
|
||||
int lidx = get_local_id(0);
|
||||
int lidy = get_local_id(1);
|
||||
|
||||
int grp_idx = get_global_id(0) & 0xFFFFF0;
|
||||
int grp_idy = get_global_id(1) & 0xFFFFF0;
|
||||
|
||||
int tid = lidx + lidy * 16;
|
||||
int lx = tid % 18;
|
||||
int ly = tid / 18;
|
||||
|
||||
mag += mag_offset;
|
||||
if (ly < 14)
|
||||
smem[ly][lx] = *(__global const int *)(mag +
|
||||
mad24(mag_step, min(grp_idy + ly, rows - 1), (int)sizeof(int) * (grp_idx + lx)));
|
||||
if (ly < 4 && grp_idy + ly + 14 <= rows && grp_idx + lx <= cols)
|
||||
smem[ly + 14][lx] = *(__global const int *)(mag +
|
||||
mad24(mag_step, min(grp_idy + ly + 14, rows - 1), (int)sizeof(int) * (grp_idx + lx)));
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (gidy < rows && gidx < cols)
|
||||
{
|
||||
// 0 - the pixel can not belong to an edge
|
||||
// 1 - the pixel might belong to an edge
|
||||
// 2 - the pixel does belong to an edge
|
||||
int edge_type = 0;
|
||||
int m = smem[lidy + 1][lidx + 1];
|
||||
|
||||
if (m > low_thresh)
|
||||
{
|
||||
short xs = *(__global const short *)(dx + mad24(gidy, dx_step, dx_offset + (int)sizeof(short) * gidx));
|
||||
short ys = *(__global const short *)(dy + mad24(gidy, dy_step, dy_offset + (int)sizeof(short) * gidx));
|
||||
int x = abs(xs), y = abs(ys);
|
||||
|
||||
int tg22x = x * TG22;
|
||||
y <<= CANNY_SHIFT;
|
||||
|
||||
if (y < tg22x)
|
||||
{
|
||||
if (m > smem[lidy + 1][lidx] && m >= smem[lidy + 1][lidx + 2])
|
||||
edge_type = 1 + (int)(m > high_thresh);
|
||||
}
|
||||
else
|
||||
{
|
||||
int tg67x = tg22x + (x << (1 + CANNY_SHIFT));
|
||||
if (y > tg67x)
|
||||
{
|
||||
if (m > smem[lidy][lidx + 1]&& m >= smem[lidy + 2][lidx + 1])
|
||||
edge_type = 1 + (int)(m > high_thresh);
|
||||
}
|
||||
else
|
||||
{
|
||||
int s = (xs ^ ys) < 0 ? -1 : 1;
|
||||
if (m > smem[lidy][lidx + 1 - s]&& m > smem[lidy + 2][lidx + 1 + s])
|
||||
edge_type = 1 + (int)(m > high_thresh);
|
||||
}
|
||||
}
|
||||
}
|
||||
*(__global int *)(map + mad24(map_step, gidy + 1, (gidx + 1) * (int)sizeof(int) + map_offset)) = edge_type;
|
||||
}
|
||||
}
|
||||
|
||||
#undef CANNY_SHIFT
|
||||
#undef TG22
|
||||
|
||||
struct PtrStepSz
|
||||
{
|
||||
__global uchar * ptr;
|
||||
int step, rows, cols;
|
||||
};
|
||||
|
||||
inline int get(struct PtrStepSz data, int y, int x)
|
||||
{
|
||||
return *(__global int *)(data.ptr + mad24(data.step, y + 1, (int)sizeof(int) * (x + 1)));
|
||||
}
|
||||
|
||||
inline void set(struct PtrStepSz data, int y, int x, int value)
|
||||
{
|
||||
*(__global int *)(data.ptr + mad24(data.step, y + 1, (int)sizeof(int) * (x + 1))) = value;
|
||||
}
|
||||
|
||||
// perform Hysteresis for pixel whose edge type is 1
|
||||
//
|
||||
// If candidate pixel (edge type is 1) has a neighbour pixel (in 3x3 area) with type 2, it is believed to be part of an edge and
|
||||
// marked as edge. Each thread will iterate for 16 times to connect local edges.
|
||||
// Candidate pixel being identified as edge will then be tested if there is nearby potiential edge points. If there is, counter will
|
||||
// be incremented by 1 and the point location is stored. These potiential candidates will be processed further in next kernel.
|
||||
//
|
||||
// map raw edge type results calculated from calcMap.
|
||||
// stack the potiential edge points found in this kernel call
|
||||
// counter the number of potiential edge points
|
||||
|
||||
__kernel void __attribute__((reqd_work_group_size(16,16,1)))
|
||||
edgesHysteresisLocal
|
||||
(__global uchar * map_ptr, int map_step, int map_offset,
|
||||
__global ushort2 * st, __global unsigned int * counter,
|
||||
int rows, int cols)
|
||||
{
|
||||
struct PtrStepSz map = { map_ptr + map_offset, map_step, rows + 1, cols + 1 };
|
||||
|
||||
__local int smem[18][18];
|
||||
|
||||
int2 blockIdx = (int2)(get_group_id(0), get_group_id(1));
|
||||
int2 blockDim = (int2)(get_local_size(0), get_local_size(1));
|
||||
int2 threadIdx = (int2)(get_local_id(0), get_local_id(1));
|
||||
|
||||
const int x = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
const int y = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
|
||||
smem[threadIdx.y + 1][threadIdx.x + 1] = x < map.cols && y < map.rows ? get(map, y, x) : 0;
|
||||
if (threadIdx.y == 0)
|
||||
smem[0][threadIdx.x + 1] = x < map.cols ? get(map, y - 1, x) : 0;
|
||||
if (threadIdx.y == blockDim.y - 1)
|
||||
smem[blockDim.y + 1][threadIdx.x + 1] = y + 1 < map.rows ? get(map, y + 1, x) : 0;
|
||||
if (threadIdx.x == 0)
|
||||
smem[threadIdx.y + 1][0] = y < map.rows ? get(map, y, x - 1) : 0;
|
||||
if (threadIdx.x == blockDim.x - 1)
|
||||
smem[threadIdx.y + 1][blockDim.x + 1] = x + 1 < map.cols && y < map.rows ? get(map, y, x + 1) : 0;
|
||||
if (threadIdx.x == 0 && threadIdx.y == 0)
|
||||
smem[0][0] = y > 0 && x > 0 ? get(map, y - 1, x - 1) : 0;
|
||||
if (threadIdx.x == blockDim.x - 1 && threadIdx.y == 0)
|
||||
smem[0][blockDim.x + 1] = y > 0 && x + 1 < map.cols ? get(map, y - 1, x + 1) : 0;
|
||||
if (threadIdx.x == 0 && threadIdx.y == blockDim.y - 1)
|
||||
smem[blockDim.y + 1][0] = y + 1 < map.rows && x > 0 ? get(map, y + 1, x - 1) : 0;
|
||||
if (threadIdx.x == blockDim.x - 1 && threadIdx.y == blockDim.y - 1)
|
||||
smem[blockDim.y + 1][blockDim.x + 1] = y + 1 < map.rows && x + 1 < map.cols ? get(map, y + 1, x + 1) : 0;
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (x >= cols || y >= rows)
|
||||
return;
|
||||
|
||||
int n;
|
||||
|
||||
#pragma unroll
|
||||
for (int k = 0; k < 16; ++k)
|
||||
{
|
||||
n = 0;
|
||||
|
||||
if (smem[threadIdx.y + 1][threadIdx.x + 1] == 1)
|
||||
{
|
||||
n += smem[threadIdx.y ][threadIdx.x ] == 2;
|
||||
n += smem[threadIdx.y ][threadIdx.x + 1] == 2;
|
||||
n += smem[threadIdx.y ][threadIdx.x + 2] == 2;
|
||||
|
||||
n += smem[threadIdx.y + 1][threadIdx.x ] == 2;
|
||||
n += smem[threadIdx.y + 1][threadIdx.x + 2] == 2;
|
||||
|
||||
n += smem[threadIdx.y + 2][threadIdx.x ] == 2;
|
||||
n += smem[threadIdx.y + 2][threadIdx.x + 1] == 2;
|
||||
n += smem[threadIdx.y + 2][threadIdx.x + 2] == 2;
|
||||
}
|
||||
|
||||
if (n > 0)
|
||||
smem[threadIdx.y + 1][threadIdx.x + 1] = 2;
|
||||
}
|
||||
|
||||
const int e = smem[threadIdx.y + 1][threadIdx.x + 1];
|
||||
set(map, y, x, e);
|
||||
n = 0;
|
||||
|
||||
if (e == 2)
|
||||
{
|
||||
n += smem[threadIdx.y ][threadIdx.x ] == 1;
|
||||
n += smem[threadIdx.y ][threadIdx.x + 1] == 1;
|
||||
n += smem[threadIdx.y ][threadIdx.x + 2] == 1;
|
||||
|
||||
n += smem[threadIdx.y + 1][threadIdx.x ] == 1;
|
||||
n += smem[threadIdx.y + 1][threadIdx.x + 2] == 1;
|
||||
|
||||
n += smem[threadIdx.y + 2][threadIdx.x ] == 1;
|
||||
n += smem[threadIdx.y + 2][threadIdx.x + 1] == 1;
|
||||
n += smem[threadIdx.y + 2][threadIdx.x + 2] == 1;
|
||||
}
|
||||
|
||||
if (n > 0)
|
||||
{
|
||||
const int ind = atomic_inc(counter);
|
||||
st[ind] = (ushort2)(x + 1, y + 1);
|
||||
}
|
||||
}
|
||||
|
||||
__constant int c_dx[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
|
||||
__constant int c_dy[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
|
||||
|
||||
|
||||
#define stack_size 512
|
||||
#define map_index mad24(map_step, pos.y, pos.x * (int)sizeof(int))
|
||||
|
||||
__kernel void __attribute__((reqd_work_group_size(128, 1, 1)))
|
||||
edgesHysteresisGlobal(__global uchar * map, int map_step, int map_offset,
|
||||
__global ushort2 * st1, __global ushort2 * st2, __global int * counter,
|
||||
int rows, int cols, int count)
|
||||
{
|
||||
map += map_offset;
|
||||
|
||||
int lidx = get_local_id(0);
|
||||
|
||||
int grp_idx = get_group_id(0);
|
||||
int grp_idy = get_group_id(1);
|
||||
|
||||
__local unsigned int s_counter, s_ind;
|
||||
__local ushort2 s_st[stack_size];
|
||||
|
||||
if (lidx == 0)
|
||||
s_counter = 0;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
int ind = mad24(grp_idy, (int)get_local_size(0), grp_idx);
|
||||
|
||||
if (ind < count)
|
||||
{
|
||||
ushort2 pos = st1[ind];
|
||||
if (lidx < 8)
|
||||
{
|
||||
pos.x += c_dx[lidx];
|
||||
pos.y += c_dy[lidx];
|
||||
if (pos.x > 0 && pos.x <= cols && pos.y > 0 && pos.y <= rows && *(__global int *)(map + map_index) == 1)
|
||||
{
|
||||
*(__global int *)(map + map_index) = 2;
|
||||
ind = atomic_inc(&s_counter);
|
||||
s_st[ind] = pos;
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
while (s_counter > 0 && s_counter <= stack_size - get_local_size(0))
|
||||
{
|
||||
const int subTaskIdx = lidx >> 3;
|
||||
const int portion = min(s_counter, (uint)(get_local_size(0)>> 3));
|
||||
|
||||
if (subTaskIdx < portion)
|
||||
pos = s_st[s_counter - 1 - subTaskIdx];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (lidx == 0)
|
||||
s_counter -= portion;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (subTaskIdx < portion)
|
||||
{
|
||||
pos.x += c_dx[lidx & 7];
|
||||
pos.y += c_dy[lidx & 7];
|
||||
if (pos.x > 0 && pos.x <= cols && pos.y > 0 && pos.y <= rows && *(__global int *)(map + map_index) == 1)
|
||||
{
|
||||
*(__global int *)(map + map_index) = 2;
|
||||
ind = atomic_inc(&s_counter);
|
||||
s_st[ind] = pos;
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
|
||||
if (s_counter > 0)
|
||||
{
|
||||
if (lidx == 0)
|
||||
{
|
||||
ind = atomic_add(counter, s_counter);
|
||||
s_ind = ind - s_counter;
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
ind = s_ind;
|
||||
for (int i = lidx; i < (int)s_counter; i += get_local_size(0))
|
||||
st2[ind + i] = s_st[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef map_index
|
||||
#undef stack_size
|
||||
|
||||
// Get the edge result. egde type of value 2 will be marked as an edge point and set to 255. Otherwise 0.
|
||||
// map edge type mappings
|
||||
// dst edge output
|
||||
|
||||
__kernel void getEdges(__global const uchar * mapptr, int map_step, int map_offset,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int rows, int cols)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (y < rows && x < cols)
|
||||
{
|
||||
int map_index = mad24(map_step, y + 1, (x + 1) * (int)sizeof(int) + map_offset);
|
||||
int dst_index = mad24(dst_step, y, x + dst_offset);
|
||||
|
||||
__global const int * map = (__global const int *)(mapptr + map_index);
|
||||
|
||||
dst[dst_index] = (uchar)(-(map[0] >> 1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Sen Liu, swjtuls1987@126.com
|
||||
//
|
||||
// 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*/
|
||||
|
||||
#ifndef WAVE_SIZE
|
||||
#define WAVE_SIZE 1
|
||||
#endif
|
||||
|
||||
inline int calc_lut(__local int* smem, int val, int tid)
|
||||
{
|
||||
smem[tid] = val;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid == 0)
|
||||
for (int i = 1; i < 256; ++i)
|
||||
smem[i] += smem[i - 1];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
return smem[tid];
|
||||
}
|
||||
|
||||
#ifdef CPU
|
||||
inline void reduce(volatile __local int* smem, int val, int tid)
|
||||
{
|
||||
smem[tid] = val;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 128)
|
||||
smem[tid] = val += smem[tid + 128];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 64)
|
||||
smem[tid] = val += smem[tid + 64];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 32)
|
||||
smem[tid] += smem[tid + 32];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 16)
|
||||
smem[tid] += smem[tid + 16];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 8)
|
||||
smem[tid] += smem[tid + 8];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 4)
|
||||
smem[tid] += smem[tid + 4];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 2)
|
||||
smem[tid] += smem[tid + 2];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 1)
|
||||
smem[256] = smem[tid] + smem[tid + 1];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void reduce(__local volatile int* smem, int val, int tid)
|
||||
{
|
||||
smem[tid] = val;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 128)
|
||||
smem[tid] = val += smem[tid + 128];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 64)
|
||||
smem[tid] = val += smem[tid + 64];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 32)
|
||||
{
|
||||
smem[tid] += smem[tid + 32];
|
||||
#if WAVE_SIZE < 32
|
||||
} barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 16)
|
||||
{
|
||||
#endif
|
||||
smem[tid] += smem[tid + 16];
|
||||
#if WAVE_SIZE < 16
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (tid < 8)
|
||||
{
|
||||
#endif
|
||||
smem[tid] += smem[tid + 8];
|
||||
smem[tid] += smem[tid + 4];
|
||||
smem[tid] += smem[tid + 2];
|
||||
smem[tid] += smem[tid + 1];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
__kernel void calcLut(__global __const uchar * src, const int srcStep,
|
||||
const int src_offset, __global uchar * lut,
|
||||
const int dstStep, const int dst_offset,
|
||||
const int2 tileSize, const int tilesX,
|
||||
const int clipLimit, const float lutScale)
|
||||
{
|
||||
__local int smem[512];
|
||||
|
||||
int tx = get_group_id(0);
|
||||
int ty = get_group_id(1);
|
||||
int tid = get_local_id(1) * get_local_size(0)
|
||||
+ get_local_id(0);
|
||||
smem[tid] = 0;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
for (int i = get_local_id(1); i < tileSize.y; i += get_local_size(1))
|
||||
{
|
||||
__global const uchar* srcPtr = src + mad24(ty * tileSize.y + i, srcStep, tx * tileSize.x + src_offset);
|
||||
for (int j = get_local_id(0); j < tileSize.x; j += get_local_size(0))
|
||||
{
|
||||
const int data = srcPtr[j];
|
||||
atomic_inc(&smem[data]);
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
int tHistVal = smem[tid];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (clipLimit > 0)
|
||||
{
|
||||
// clip histogram bar
|
||||
int clipped = 0;
|
||||
if (tHistVal > clipLimit)
|
||||
{
|
||||
clipped = tHistVal - clipLimit;
|
||||
tHistVal = clipLimit;
|
||||
}
|
||||
|
||||
// find number of overall clipped samples
|
||||
reduce(smem, clipped, tid);
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
#ifdef CPU
|
||||
clipped = smem[256];
|
||||
#else
|
||||
clipped = smem[0];
|
||||
#endif
|
||||
|
||||
// broadcast evaluated value
|
||||
|
||||
__local int totalClipped;
|
||||
|
||||
if (tid == 0)
|
||||
totalClipped = clipped;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
// redistribute clipped samples evenly
|
||||
|
||||
int redistBatch = totalClipped / 256;
|
||||
tHistVal += redistBatch;
|
||||
|
||||
int residual = totalClipped - redistBatch * 256;
|
||||
if (tid < residual)
|
||||
++tHistVal;
|
||||
}
|
||||
|
||||
const int lutVal = calc_lut(smem, tHistVal, tid);
|
||||
uint ires = (uint)convert_int_rte(lutScale * lutVal);
|
||||
lut[(ty * tilesX + tx) * dstStep + tid + dst_offset] =
|
||||
convert_uchar(clamp(ires, (uint)0, (uint)255));
|
||||
}
|
||||
|
||||
__kernel void transform(__global __const uchar * src, const int srcStep, const int src_offset,
|
||||
__global uchar * dst, const int dstStep, const int dst_offset,
|
||||
__global uchar * lut, const int lutStep, int lut_offset,
|
||||
const int cols, const int rows,
|
||||
const int2 tileSize,
|
||||
const int tilesX, const int tilesY)
|
||||
{
|
||||
const int x = get_global_id(0);
|
||||
const int y = get_global_id(1);
|
||||
|
||||
if (x >= cols || y >= rows)
|
||||
return;
|
||||
|
||||
const float tyf = (convert_float(y) / tileSize.y) - 0.5f;
|
||||
int ty1 = convert_int_rtn(tyf);
|
||||
int ty2 = ty1 + 1;
|
||||
const float ya = tyf - ty1;
|
||||
ty1 = max(ty1, 0);
|
||||
ty2 = min(ty2, tilesY - 1);
|
||||
|
||||
const float txf = (convert_float(x) / tileSize.x) - 0.5f;
|
||||
int tx1 = convert_int_rtn(txf);
|
||||
int tx2 = tx1 + 1;
|
||||
const float xa = txf - tx1;
|
||||
tx1 = max(tx1, 0);
|
||||
tx2 = min(tx2, tilesX - 1);
|
||||
|
||||
const int srcVal = src[mad24(y, srcStep, x + src_offset)];
|
||||
|
||||
float res = 0;
|
||||
|
||||
res += lut[mad24(ty1 * tilesX + tx1, lutStep, srcVal + lut_offset)] * ((1.0f - xa) * (1.0f - ya));
|
||||
res += lut[mad24(ty1 * tilesX + tx2, lutStep, srcVal + lut_offset)] * ((xa) * (1.0f - ya));
|
||||
res += lut[mad24(ty2 * tilesX + tx1, lutStep, srcVal + lut_offset)] * ((1.0f - xa) * (ya));
|
||||
res += lut[mad24(ty2 * tilesX + tx2, lutStep, srcVal + lut_offset)] * ((xa) * (ya));
|
||||
|
||||
uint ires = (uint)convert_int_rte(res);
|
||||
dst[mad24(y, dstStep, x + dst_offset)] = convert_uchar(clamp(ires, (uint)0, (uint)255));
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Shengen Yan,yanshengen@gmail.com
|
||||
//
|
||||
// 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*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////Macro for border type////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef BORDER_CONSTANT
|
||||
#elif defined BORDER_REPLICATE
|
||||
#define EXTRAPOLATE(x, maxV) \
|
||||
{ \
|
||||
x = max(min(x, maxV - 1), 0); \
|
||||
}
|
||||
#elif defined BORDER_WRAP
|
||||
#define EXTRAPOLATE(x, maxV) \
|
||||
{ \
|
||||
if (x < 0) \
|
||||
x -= ((x - maxV + 1) / maxV) * maxV; \
|
||||
if (x >= maxV) \
|
||||
x %= maxV; \
|
||||
}
|
||||
#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT101)
|
||||
#define EXTRAPOLATE_(x, maxV, delta) \
|
||||
{ \
|
||||
if (maxV == 1) \
|
||||
x = 0; \
|
||||
else \
|
||||
do \
|
||||
{ \
|
||||
if ( x < 0 ) \
|
||||
x = -x - 1 + delta; \
|
||||
else \
|
||||
x = maxV - 1 - (x - maxV) - delta; \
|
||||
} \
|
||||
while (x >= maxV || x < 0); \
|
||||
}
|
||||
#ifdef BORDER_REFLECT
|
||||
#define EXTRAPOLATE(x, maxV) EXTRAPOLATE_(x, maxV, 0)
|
||||
#else
|
||||
#define EXTRAPOLATE(x, maxV) EXTRAPOLATE_(x, maxV, 1)
|
||||
#endif
|
||||
#else
|
||||
#error No extrapolation method
|
||||
#endif
|
||||
|
||||
#define THREADS 256
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////calcHarris////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__kernel void corner(__global const float * Dx, int dx_step, int dx_offset, int dx_whole_rows, int dx_whole_cols,
|
||||
__global const float * Dy, int dy_step, int dy_offset, int dy_whole_rows, int dy_whole_cols,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols, float k)
|
||||
{
|
||||
int col = get_local_id(0);
|
||||
int gX = get_group_id(0);
|
||||
int gY = get_group_id(1);
|
||||
int gly = get_global_id(1);
|
||||
|
||||
int dx_x_off = (dx_offset % dx_step) >> 2;
|
||||
int dx_y_off = dx_offset / dx_step;
|
||||
int dy_x_off = (dy_offset % dy_step) >> 2;
|
||||
int dy_y_off = dy_offset / dy_step;
|
||||
int dst_x_off = (dst_offset % dst_step) >> 2;
|
||||
int dst_y_off = dst_offset / dst_step;
|
||||
|
||||
int dx_startX = gX * (THREADS-ksX+1) - anX + dx_x_off;
|
||||
int dx_startY = (gY << 1) - anY + dx_y_off;
|
||||
int dy_startX = gX * (THREADS-ksX+1) - anX + dy_x_off;
|
||||
int dy_startY = (gY << 1) - anY + dy_y_off;
|
||||
int dst_startX = gX * (THREADS-ksX+1) + dst_x_off;
|
||||
int dst_startY = (gY << 1) + dst_y_off;
|
||||
|
||||
float dx_data[ksY+1],dy_data[ksY+1], data[3][ksY+1];
|
||||
__local float temp[6][THREADS];
|
||||
|
||||
#ifdef BORDER_CONSTANT
|
||||
for (int i=0; i < ksY+1; i++)
|
||||
{
|
||||
bool dx_con = dx_startX+col >= 0 && dx_startX+col < dx_whole_cols && dx_startY+i >= 0 && dx_startY+i < dx_whole_rows;
|
||||
int indexDx = (dx_startY+i)*(dx_step>>2)+(dx_startX+col);
|
||||
float dx_s = dx_con ? Dx[indexDx] : 0.0f;
|
||||
dx_data[i] = dx_s;
|
||||
|
||||
bool dy_con = dy_startX+col >= 0 && dy_startX+col < dy_whole_cols && dy_startY+i >= 0 && dy_startY+i < dy_whole_rows;
|
||||
int indexDy = (dy_startY+i)*(dy_step>>2)+(dy_startX+col);
|
||||
float dy_s = dy_con ? Dy[indexDy] : 0.0f;
|
||||
dy_data[i] = dy_s;
|
||||
|
||||
data[0][i] = dx_data[i] * dx_data[i];
|
||||
data[1][i] = dx_data[i] * dy_data[i];
|
||||
data[2][i] = dy_data[i] * dy_data[i];
|
||||
}
|
||||
#else
|
||||
int clamped_col = min(2*dst_cols, col);
|
||||
for (int i=0; i < ksY+1; i++)
|
||||
{
|
||||
int dx_selected_row = dx_startY+i, dx_selected_col = dx_startX+clamped_col;
|
||||
EXTRAPOLATE(dx_selected_row, dx_whole_rows)
|
||||
EXTRAPOLATE(dx_selected_col, dx_whole_cols)
|
||||
dx_data[i] = Dx[dx_selected_row * (dx_step>>2) + dx_selected_col];
|
||||
|
||||
int dy_selected_row = dy_startY+i, dy_selected_col = dy_startX+clamped_col;
|
||||
EXTRAPOLATE(dy_selected_row, dy_whole_rows)
|
||||
EXTRAPOLATE(dy_selected_col, dy_whole_cols)
|
||||
dy_data[i] = Dy[dy_selected_row * (dy_step>>2) + dy_selected_col];
|
||||
|
||||
data[0][i] = dx_data[i] * dx_data[i];
|
||||
data[1][i] = dx_data[i] * dy_data[i];
|
||||
data[2][i] = dy_data[i] * dy_data[i];
|
||||
}
|
||||
#endif
|
||||
float sum0 = 0.0f, sum1 = 0.0f, sum2 = 0.0f;
|
||||
for (int i=1; i < ksY; i++)
|
||||
{
|
||||
sum0 += data[0][i];
|
||||
sum1 += data[1][i];
|
||||
sum2 += data[2][i];
|
||||
}
|
||||
|
||||
float sum01 = sum0 + data[0][0];
|
||||
float sum02 = sum0 + data[0][ksY];
|
||||
temp[0][col] = sum01;
|
||||
temp[1][col] = sum02;
|
||||
float sum11 = sum1 + data[1][0];
|
||||
float sum12 = sum1 + data[1][ksY];
|
||||
temp[2][col] = sum11;
|
||||
temp[3][col] = sum12;
|
||||
float sum21 = sum2 + data[2][0];
|
||||
float sum22 = sum2 + data[2][ksY];
|
||||
temp[4][col] = sum21;
|
||||
temp[5][col] = sum22;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (col < (THREADS - (ksX - 1)))
|
||||
{
|
||||
col += anX;
|
||||
int posX = dst_startX - dst_x_off + col - anX;
|
||||
int posY = (gly << 1);
|
||||
int till = (ksX + 1)%2;
|
||||
float tmp_sum[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
for (int k=0; k<6; k++)
|
||||
{
|
||||
float temp_sum = 0;
|
||||
for (int i=-anX; i<=anX - till; i++)
|
||||
temp_sum += temp[k][col+i];
|
||||
tmp_sum[k] = temp_sum;
|
||||
}
|
||||
|
||||
#ifdef CORNER_HARRIS
|
||||
if (posX < dst_cols && (posY) < dst_rows)
|
||||
{
|
||||
int dst_index = mad24(dst_step, dst_startY, (int)sizeof(float) * (dst_startX + col - anX));
|
||||
*(__global float *)(dst + dst_index) =
|
||||
tmp_sum[0] * tmp_sum[4] - tmp_sum[2] * tmp_sum[2] - k * (tmp_sum[0] + tmp_sum[4]) * (tmp_sum[0] + tmp_sum[4]);
|
||||
}
|
||||
if (posX < dst_cols && (posY + 1) < dst_rows)
|
||||
{
|
||||
int dst_index = mad24(dst_step, dst_startY + 1, (int)sizeof(float) * (dst_startX + col - anX));
|
||||
*(__global float *)(dst + dst_index) =
|
||||
tmp_sum[1] * tmp_sum[5] - tmp_sum[3] * tmp_sum[3] - k * (tmp_sum[1] + tmp_sum[5]) * (tmp_sum[1] + tmp_sum[5]);
|
||||
}
|
||||
#elif defined CORNER_MINEIGENVAL
|
||||
if (posX < dst_cols && (posY) < dst_rows)
|
||||
{
|
||||
int dst_index = mad24(dst_step, dst_startY, (int)sizeof(float) * (dst_startX + col - anX));
|
||||
float a = tmp_sum[0] * 0.5f;
|
||||
float b = tmp_sum[2];
|
||||
float c = tmp_sum[4] * 0.5f;
|
||||
*(__global float *)(dst + dst_index) = (float)((a+c) - sqrt((a-c)*(a-c) + b*b));
|
||||
}
|
||||
if (posX < dst_cols && (posY + 1) < dst_rows)
|
||||
{
|
||||
int dst_index = mad24(dst_step, dst_startY + 1, (int)sizeof(float) * (dst_startX + col - anX));
|
||||
float a = tmp_sum[1] * 0.5f;
|
||||
float b = tmp_sum[3];
|
||||
float c = tmp_sum[5] * 0.5f;
|
||||
*(__global float *)(dst + dst_index) = (float)((a+c) - sqrt((a-c)*(a-c) + b*b));
|
||||
}
|
||||
#else
|
||||
#error "No such corners type"
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -46,10 +46,6 @@
|
||||
|
||||
/**************************************PUBLICFUNC*************************************/
|
||||
|
||||
#if defined (DOUBLE_SUPPORT)
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#endif
|
||||
|
||||
#if depth == 0
|
||||
#define DATA_TYPE uchar
|
||||
#define MAX_NUM 255
|
||||
@@ -472,7 +468,7 @@ __kernel void RGB(__global const uchar* srcptr, int src_step, int src_offset,
|
||||
dst[0] = src[2];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[0];
|
||||
#elif defined ORDER
|
||||
#else
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
@@ -728,7 +724,7 @@ __kernel void RGB2HSV(__global const uchar* srcptr, int src_step, int src_offset
|
||||
|
||||
diff = v - vmin;
|
||||
s = diff/(float)(fabs(v) + FLT_EPSILON);
|
||||
diff = (float)(60./(diff + FLT_EPSILON));
|
||||
diff = (float)(60.f/(diff + FLT_EPSILON));
|
||||
if( v == r )
|
||||
h = (g - b)*diff;
|
||||
else if( v == g )
|
||||
@@ -1065,3 +1061,234 @@ __kernel void mRGBA2RGBA(__global const uchar* src, int src_step, int src_offset
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/////////////////////////////////// [l|s]RGB <-> Lab ///////////////////////////
|
||||
|
||||
#define lab_shift xyz_shift
|
||||
#define gamma_shift 3
|
||||
#define lab_shift2 (lab_shift + gamma_shift)
|
||||
#define GAMMA_TAB_SIZE 1024
|
||||
#define GammaTabScale (float)GAMMA_TAB_SIZE
|
||||
|
||||
inline float splineInterpolate(float x, __global const float * tab, int n)
|
||||
{
|
||||
int ix = clamp(convert_int_sat_rtn(x), 0, n-1);
|
||||
x -= ix;
|
||||
tab += ix*4;
|
||||
return ((tab[3]*x + tab[2])*x + tab[1])*x + tab[0];
|
||||
}
|
||||
|
||||
#ifdef DEPTH_0
|
||||
|
||||
__kernel void BGR2Lab(__global const uchar * src, int src_step, int src_offset,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int rows, int cols,
|
||||
__global const ushort * gammaTab, __global ushort * LabCbrtTab_b,
|
||||
__constant int * coeffs, int Lscale, int Lshift)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (y < rows && x < cols)
|
||||
{
|
||||
int src_idx = mad24(y, src_step, src_offset + x * scnbytes);
|
||||
int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes);
|
||||
|
||||
src += src_idx;
|
||||
dst += dst_idx;
|
||||
|
||||
int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
|
||||
C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
|
||||
C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
|
||||
|
||||
int R = gammaTab[src[0]], G = gammaTab[src[1]], B = gammaTab[src[2]];
|
||||
int fX = LabCbrtTab_b[CV_DESCALE(R*C0 + G*C1 + B*C2, lab_shift)];
|
||||
int fY = LabCbrtTab_b[CV_DESCALE(R*C3 + G*C4 + B*C5, lab_shift)];
|
||||
int fZ = LabCbrtTab_b[CV_DESCALE(R*C6 + G*C7 + B*C8, lab_shift)];
|
||||
|
||||
int L = CV_DESCALE( Lscale*fY + Lshift, lab_shift2 );
|
||||
int a = CV_DESCALE( 500*(fX - fY) + 128*(1 << lab_shift2), lab_shift2 );
|
||||
int b = CV_DESCALE( 200*(fY - fZ) + 128*(1 << lab_shift2), lab_shift2 );
|
||||
|
||||
dst[0] = SAT_CAST(L);
|
||||
dst[1] = SAT_CAST(a);
|
||||
dst[2] = SAT_CAST(b);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined DEPTH_5
|
||||
|
||||
__kernel void BGR2Lab(__global const uchar * srcptr, int src_step, int src_offset,
|
||||
__global uchar * dstptr, int dst_step, int dst_offset, int rows, int cols,
|
||||
#ifdef SRGB
|
||||
__global const float * gammaTab,
|
||||
#endif
|
||||
__constant float * coeffs, float _1_3, float _a)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (y < rows && x < cols)
|
||||
{
|
||||
int src_idx = mad24(y, src_step, src_offset + x * scnbytes);
|
||||
int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes);
|
||||
|
||||
__global const float * src = (__global const float *)(srcptr + src_idx);
|
||||
__global float * dst = (__global float *)(dstptr + dst_idx);
|
||||
|
||||
float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
|
||||
C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
|
||||
C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
|
||||
|
||||
float R = clamp(src[0], 0.0f, 1.0f);
|
||||
float G = clamp(src[1], 0.0f, 1.0f);
|
||||
float B = clamp(src[2], 0.0f, 1.0f);
|
||||
|
||||
#ifdef SRGB
|
||||
R = splineInterpolate(R * GammaTabScale, gammaTab, GAMMA_TAB_SIZE);
|
||||
G = splineInterpolate(G * GammaTabScale, gammaTab, GAMMA_TAB_SIZE);
|
||||
B = splineInterpolate(B * GammaTabScale, gammaTab, GAMMA_TAB_SIZE);
|
||||
#endif
|
||||
|
||||
float X = R*C0 + G*C1 + B*C2;
|
||||
float Y = R*C3 + G*C4 + B*C5;
|
||||
float Z = R*C6 + G*C7 + B*C8;
|
||||
|
||||
float FX = X > 0.008856f ? pow(X, _1_3) : (7.787f * X + _a);
|
||||
float FY = Y > 0.008856f ? pow(Y, _1_3) : (7.787f * Y + _a);
|
||||
float FZ = Z > 0.008856f ? pow(Z, _1_3) : (7.787f * Z + _a);
|
||||
|
||||
float L = Y > 0.008856f ? (116.f * FY - 16.f) : (903.3f * Y);
|
||||
float a = 500.f * (FX - FY);
|
||||
float b = 200.f * (FY - FZ);
|
||||
|
||||
dst[0] = L;
|
||||
dst[1] = a;
|
||||
dst[2] = b;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline void Lab2BGR_f(const float * srcbuf, float * dstbuf,
|
||||
#ifdef SRGB
|
||||
__global const float * gammaTab,
|
||||
#endif
|
||||
__constant float * coeffs, float lThresh, float fThresh)
|
||||
{
|
||||
float li = srcbuf[0], ai = srcbuf[1], bi = srcbuf[2];
|
||||
|
||||
float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
|
||||
C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
|
||||
C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
|
||||
|
||||
float y, fy;
|
||||
if (li <= lThresh)
|
||||
{
|
||||
y = li / 903.3f;
|
||||
fy = 7.787f * y + 16.0f / 116.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
fy = (li + 16.0f) / 116.0f;
|
||||
y = fy * fy * fy;
|
||||
}
|
||||
|
||||
float fxz[] = { ai / 500.0f + fy, fy - bi / 200.0f };
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
if (fxz[j] <= fThresh)
|
||||
fxz[j] = (fxz[j] - 16.0f / 116.0f) / 7.787f;
|
||||
else
|
||||
fxz[j] = fxz[j] * fxz[j] * fxz[j];
|
||||
|
||||
float x = fxz[0], z = fxz[1];
|
||||
float ro = clamp(C0 * x + C1 * y + C2 * z, 0.0f, 1.0f);
|
||||
float go = clamp(C3 * x + C4 * y + C5 * z, 0.0f, 1.0f);
|
||||
float bo = clamp(C6 * x + C7 * y + C8 * z, 0.0f, 1.0f);
|
||||
|
||||
#ifdef SRGB
|
||||
ro = splineInterpolate(ro * GammaTabScale, gammaTab, GAMMA_TAB_SIZE);
|
||||
go = splineInterpolate(go * GammaTabScale, gammaTab, GAMMA_TAB_SIZE);
|
||||
bo = splineInterpolate(bo * GammaTabScale, gammaTab, GAMMA_TAB_SIZE);
|
||||
#endif
|
||||
|
||||
dstbuf[0] = ro, dstbuf[1] = go, dstbuf[2] = bo;
|
||||
}
|
||||
|
||||
#ifdef DEPTH_0
|
||||
|
||||
__kernel void Lab2BGR(__global const uchar * src, int src_step, int src_offset,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int rows, int cols,
|
||||
#ifdef SRGB
|
||||
__global const float * gammaTab,
|
||||
#endif
|
||||
__constant float * coeffs, float lThresh, float fThresh)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (y < rows && x < cols)
|
||||
{
|
||||
int src_idx = mad24(y, src_step, src_offset + x * scnbytes);
|
||||
int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes);
|
||||
|
||||
src += src_idx;
|
||||
dst += dst_idx;
|
||||
|
||||
float srcbuf[3], dstbuf[3];
|
||||
srcbuf[0] = src[0]*(100.f/255.f);
|
||||
srcbuf[1] = convert_float(src[1] - 128);
|
||||
srcbuf[2] = convert_float(src[2] - 128);
|
||||
|
||||
Lab2BGR_f(&srcbuf[0], &dstbuf[0],
|
||||
#ifdef SRGB
|
||||
gammaTab,
|
||||
#endif
|
||||
coeffs, lThresh, fThresh);
|
||||
|
||||
dst[0] = SAT_CAST(dstbuf[0] * 255.0f);
|
||||
dst[1] = SAT_CAST(dstbuf[1] * 255.0f);
|
||||
dst[2] = SAT_CAST(dstbuf[2] * 255.0f);
|
||||
#if dcn == 4
|
||||
dst[3] = MAX_NUM;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined DEPTH_5
|
||||
|
||||
__kernel void Lab2BGR(__global const uchar * srcptr, int src_step, int src_offset,
|
||||
__global uchar * dstptr, int dst_step, int dst_offset, int rows, int cols,
|
||||
#ifdef SRGB
|
||||
__global const float * gammaTab,
|
||||
#endif
|
||||
__constant float * coeffs, float lThresh, float fThresh)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (y < rows && x < cols)
|
||||
{
|
||||
int src_idx = mad24(y, src_step, src_offset + x * scnbytes);
|
||||
int dst_idx = mad24(y, dst_step, dst_offset + x * dcnbytes);
|
||||
|
||||
__global const float * src = (__global const float *)(srcptr + src_idx);
|
||||
__global float * dst = (__global float *)(dstptr + dst_idx);
|
||||
|
||||
float srcbuf[3], dstbuf[3];
|
||||
srcbuf[0] = src[0], srcbuf[1] = src[1], srcbuf[2] = src[2];
|
||||
|
||||
Lab2BGR_f(&srcbuf[0], &dstbuf[0],
|
||||
#ifdef SRGB
|
||||
gammaTab,
|
||||
#endif
|
||||
coeffs, lThresh, fThresh);
|
||||
|
||||
dst[0] = dstbuf[0], dst[1] = dstbuf[1], dst[2] = dstbuf[2];
|
||||
#if dcn == 4
|
||||
dst[3] = MAX_NUM;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
|
||||
#define READ_TIMES_COL ((2*(RADIUSY+LSIZE1)-1)/LSIZE1)
|
||||
#define RADIUS 1
|
||||
#if CN ==1
|
||||
#define ALIGN (((RADIUS)+3)>>2<<2)
|
||||
#elif CN==2
|
||||
#define ALIGN (((RADIUS)+1)>>1<<1)
|
||||
#elif CN==3
|
||||
#define ALIGN (((RADIUS)+3)>>2<<2)
|
||||
#elif CN==4
|
||||
#define ALIGN (RADIUS)
|
||||
#define READ_TIMES_ROW ((2*(RADIUS+LSIZE0)-1)/LSIZE0)
|
||||
#endif
|
||||
|
||||
/**********************************************************************************
|
||||
These kernels are written for separable filters such as Sobel, Scharr, GaussianBlur.
|
||||
Now(6/29/2011) the kernels only support 8U data type and the anchor of the convovle
|
||||
kernel must be in the center. ROI is not supported either.
|
||||
Each kernels read 4 elements(not 4 pixels), save them to LDS and read the data needed
|
||||
from LDS to calculate the result.
|
||||
The length of the convovle kernel supported is only related to the MAX size of LDS,
|
||||
which is HW related.
|
||||
Niko
|
||||
6/29/2011
|
||||
The info above maybe obsolete.
|
||||
***********************************************************************************/
|
||||
|
||||
#define DIG(a) a,
|
||||
__constant float mat_kernel[] = { COEFF };
|
||||
|
||||
__kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void col_filter
|
||||
(__global const GENTYPE_SRC * restrict src,
|
||||
const int src_step_in_pixel,
|
||||
const int src_whole_cols,
|
||||
const int src_whole_rows,
|
||||
__global GENTYPE_DST * dst,
|
||||
const int dst_offset_in_pixel,
|
||||
const int dst_step_in_pixel,
|
||||
const int dst_cols,
|
||||
const int dst_rows)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
int l_x = get_local_id(0);
|
||||
int l_y = get_local_id(1);
|
||||
|
||||
int start_addr = mad24(y, src_step_in_pixel, x);
|
||||
int end_addr = mad24(src_whole_rows - 1, src_step_in_pixel, src_whole_cols);
|
||||
|
||||
int i;
|
||||
GENTYPE_SRC sum, temp[READ_TIMES_COL];
|
||||
__local GENTYPE_SRC LDS_DAT[LSIZE1 * READ_TIMES_COL][LSIZE0 + 1];
|
||||
|
||||
//read pixels from src
|
||||
for(i = 0;i<READ_TIMES_COL;i++)
|
||||
{
|
||||
int current_addr = start_addr+i*LSIZE1*src_step_in_pixel;
|
||||
current_addr = current_addr < end_addr ? current_addr : 0;
|
||||
temp[i] = src[current_addr];
|
||||
}
|
||||
//save pixels to lds
|
||||
for(i = 0;i<READ_TIMES_COL;i++)
|
||||
{
|
||||
LDS_DAT[l_y+i*LSIZE1][l_x] = temp[i];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
//read pixels from lds and calculate the result
|
||||
sum = LDS_DAT[l_y+RADIUSY][l_x]*mat_kernel[RADIUSY];
|
||||
for(i=1;i<=RADIUSY;i++)
|
||||
{
|
||||
temp[0]=LDS_DAT[l_y+RADIUSY-i][l_x];
|
||||
temp[1]=LDS_DAT[l_y+RADIUSY+i][l_x];
|
||||
sum += temp[0] * mat_kernel[RADIUSY-i]+temp[1] * mat_kernel[RADIUSY+i];
|
||||
}
|
||||
//write the result to dst
|
||||
if((x<dst_cols) & (y<dst_rows))
|
||||
{
|
||||
start_addr = mad24(y, dst_step_in_pixel, x + dst_offset_in_pixel);
|
||||
dst[start_addr] = convert_to_DST(sum);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,569 @@
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
|
||||
#define READ_TIMES_ROW ((2*(RADIUSX+LSIZE0)-1)/LSIZE0) //for c4 only
|
||||
#define READ_TIMES_COL ((2*(RADIUSY+LSIZE1)-1)/LSIZE1)
|
||||
//#pragma OPENCL EXTENSION cl_amd_printf : enable
|
||||
#define RADIUS 1
|
||||
#if CN ==1
|
||||
#define ALIGN (((RADIUS)+3)>>2<<2)
|
||||
#elif CN==2
|
||||
#define ALIGN (((RADIUS)+1)>>1<<1)
|
||||
#elif CN==3
|
||||
#define ALIGN (((RADIUS)+3)>>2<<2)
|
||||
#elif CN==4
|
||||
#define ALIGN (RADIUS)
|
||||
#endif
|
||||
|
||||
#ifdef BORDER_REPLICATE
|
||||
//BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh
|
||||
#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? (l_edge) : (i))
|
||||
#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? (r_edge)-1 : (addr))
|
||||
#endif
|
||||
|
||||
#ifdef BORDER_REFLECT
|
||||
//BORDER_REFLECT: fedcba|abcdefgh|hgfedcb
|
||||
#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? -(i)-1 : (i))
|
||||
#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? -(i)-1+((r_edge)<<1) : (addr))
|
||||
#endif
|
||||
|
||||
#ifdef BORDER_REFLECT_101
|
||||
//BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba
|
||||
#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? -(i) : (i))
|
||||
#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? -(i)-2+((r_edge)<<1) : (addr))
|
||||
#endif
|
||||
|
||||
//blur function does not support BORDER_WRAP
|
||||
#ifdef BORDER_WRAP
|
||||
//BORDER_WRAP: cdefgh|abcdefgh|abcdefg
|
||||
#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? (i)+(r_edge) : (i))
|
||||
#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? (i)-(r_edge) : (addr))
|
||||
#endif
|
||||
|
||||
#ifdef EXTRA_EXTRAPOLATION // border > src image size
|
||||
#ifdef BORDER_CONSTANT
|
||||
#define ELEM(i,l_edge,r_edge,elem1,elem2) (i)<(l_edge) | (i) >= (r_edge) ? (elem1) : (elem2)
|
||||
#elif defined BORDER_REPLICATE
|
||||
#define EXTRAPOLATE(t, minT, maxT) \
|
||||
{ \
|
||||
t = max(min(t, (maxT) - 1), (minT)); \
|
||||
}
|
||||
#elif defined BORDER_WRAP
|
||||
#define EXTRAPOLATE(x, minT, maxT) \
|
||||
{ \
|
||||
if (t < (minT)) \
|
||||
t -= ((t - (maxT) + 1) / (maxT)) * (maxT); \
|
||||
if (t >= (maxT)) \
|
||||
t %= (maxT); \
|
||||
}
|
||||
#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT_101)
|
||||
#define EXTRAPOLATE_(t, minT, maxT, delta) \
|
||||
{ \
|
||||
if ((maxT) - (minT) == 1) \
|
||||
t = (minT); \
|
||||
else \
|
||||
do \
|
||||
{ \
|
||||
if (t < (minT)) \
|
||||
t = (minT) - (t - (minT)) - 1 + delta; \
|
||||
else \
|
||||
t = (maxT) - 1 - (t - (maxT)) - delta; \
|
||||
} \
|
||||
while (t >= (maxT) || t < (minT)); \
|
||||
\
|
||||
}
|
||||
#ifdef BORDER_REFLECT
|
||||
#define EXTRAPOLATE(t, minT, maxT) EXTRAPOLATE_(t, minT, maxT, 0)
|
||||
#elif defined(BORDER_REFLECT_101)
|
||||
#define EXTRAPOLATE(t, minT, maxT) EXTRAPOLATE_(t, minT, maxT, 1)
|
||||
#endif
|
||||
#else
|
||||
#error No extrapolation method
|
||||
#endif //BORDER_....
|
||||
#else //EXTRA_EXTRAPOLATION
|
||||
#ifdef BORDER_CONSTANT
|
||||
#define ELEM(i,l_edge,r_edge,elem1,elem2) (i)<(l_edge) | (i) >= (r_edge) ? (elem1) : (elem2)
|
||||
#else
|
||||
#define EXTRAPOLATE(t, minT, maxT) \
|
||||
{ \
|
||||
int _delta = t - (minT); \
|
||||
_delta = ADDR_L(_delta, 0, (maxT) - (minT)); \
|
||||
_delta = ADDR_R(_delta, (maxT) - (minT), _delta); \
|
||||
t = _delta + (minT); \
|
||||
}
|
||||
#endif //BORDER_CONSTANT
|
||||
#endif //EXTRA_EXTRAPOLATION
|
||||
|
||||
/**********************************************************************************
|
||||
These kernels are written for separable filters such as Sobel, Scharr, GaussianBlur.
|
||||
Now(6/29/2011) the kernels only support 8U data type and the anchor of the convovle
|
||||
kernel must be in the center. ROI is not supported either.
|
||||
For channels =1,2,4, each kernels read 4 elements(not 4 pixels), and for channels =3,
|
||||
the kernel read 4 pixels, save them to LDS and read the data needed from LDS to
|
||||
calculate the result.
|
||||
The length of the convovle kernel supported is related to the LSIZE0 and the MAX size
|
||||
of LDS, which is HW related.
|
||||
For channels = 1,3 the RADIUS is no more than LSIZE0*2
|
||||
For channels = 2, the RADIUS is no more than LSIZE0
|
||||
For channels = 4, arbitary RADIUS is supported unless the LDS is not enough
|
||||
Niko
|
||||
6/29/2011
|
||||
The info above maybe obsolete.
|
||||
***********************************************************************************/
|
||||
|
||||
#define DIG(a) a,
|
||||
__constant float mat_kernel[] = { COEFF };
|
||||
|
||||
__kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_C1_D0
|
||||
(__global uchar * restrict src,
|
||||
int src_step_in_pixel,
|
||||
int src_offset_x, int src_offset_y,
|
||||
int src_cols, int src_rows,
|
||||
int src_whole_cols, int src_whole_rows,
|
||||
__global float * dst,
|
||||
int dst_step_in_pixel,
|
||||
int dst_cols, int dst_rows,
|
||||
int radiusy)
|
||||
{
|
||||
int x = get_global_id(0)<<2;
|
||||
int y = get_global_id(1);
|
||||
int l_x = get_local_id(0);
|
||||
int l_y = get_local_id(1);
|
||||
|
||||
int start_x = x+src_offset_x - RADIUSX & 0xfffffffc;
|
||||
int offset = src_offset_x - RADIUSX & 3;
|
||||
int start_y = y + src_offset_y - radiusy;
|
||||
int start_addr = mad24(start_y, src_step_in_pixel, start_x);
|
||||
int i;
|
||||
float4 sum;
|
||||
uchar4 temp[READ_TIMES_ROW];
|
||||
|
||||
__local uchar4 LDS_DAT[LSIZE1][READ_TIMES_ROW*LSIZE0+1];
|
||||
#ifdef BORDER_CONSTANT
|
||||
int end_addr = mad24(src_whole_rows - 1, src_step_in_pixel, src_whole_cols);
|
||||
|
||||
// read pixels from src
|
||||
for (i = 0; i < READ_TIMES_ROW; i++)
|
||||
{
|
||||
int current_addr = start_addr+i*LSIZE0*4;
|
||||
current_addr = ((current_addr < end_addr) && (current_addr > 0)) ? current_addr : 0;
|
||||
temp[i] = *(__global uchar4*)&src[current_addr];
|
||||
}
|
||||
|
||||
// judge if read out of boundary
|
||||
#ifdef BORDER_ISOLATED
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
temp[i].x = ELEM(start_x+i*LSIZE0*4, src_offset_x, src_offset_x + src_cols, 0, temp[i].x);
|
||||
temp[i].y = ELEM(start_x+i*LSIZE0*4+1, src_offset_x, src_offset_x + src_cols, 0, temp[i].y);
|
||||
temp[i].z = ELEM(start_x+i*LSIZE0*4+2, src_offset_x, src_offset_x + src_cols, 0, temp[i].z);
|
||||
temp[i].w = ELEM(start_x+i*LSIZE0*4+3, src_offset_x, src_offset_x + src_cols, 0, temp[i].w);
|
||||
temp[i] = ELEM(start_y, src_offset_y, src_offset_y + src_rows, (uchar4)0, temp[i]);
|
||||
}
|
||||
#else
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
temp[i].x = ELEM(start_x+i*LSIZE0*4, 0, src_whole_cols, 0, temp[i].x);
|
||||
temp[i].y = ELEM(start_x+i*LSIZE0*4+1, 0, src_whole_cols, 0, temp[i].y);
|
||||
temp[i].z = ELEM(start_x+i*LSIZE0*4+2, 0, src_whole_cols, 0, temp[i].z);
|
||||
temp[i].w = ELEM(start_x+i*LSIZE0*4+3, 0, src_whole_cols, 0, temp[i].w);
|
||||
temp[i] = ELEM(start_y, 0, src_whole_rows, (uchar4)0, temp[i]);
|
||||
}
|
||||
#endif
|
||||
#else // BORDER_CONSTANT
|
||||
#ifdef BORDER_ISOLATED
|
||||
int not_all_in_range = (start_x<src_offset_x) | (start_x + READ_TIMES_ROW*LSIZE0*4+4>src_offset_x + src_cols)| (start_y<src_offset_y) | (start_y >= src_offset_y + src_rows);
|
||||
#else
|
||||
int not_all_in_range = (start_x<0) | (start_x + READ_TIMES_ROW*LSIZE0*4+4>src_whole_cols)| (start_y<0) | (start_y >= src_whole_rows);
|
||||
#endif
|
||||
int4 index[READ_TIMES_ROW];
|
||||
int4 addr;
|
||||
int s_y;
|
||||
|
||||
if (not_all_in_range)
|
||||
{
|
||||
// judge if read out of boundary
|
||||
for (i = 0; i < READ_TIMES_ROW; i++)
|
||||
{
|
||||
index[i] = (int4)(start_x+i*LSIZE0*4) + (int4)(0, 1, 2, 3);
|
||||
#ifdef BORDER_ISOLATED
|
||||
EXTRAPOLATE(index[i].x, src_offset_x, src_offset_x + src_cols);
|
||||
EXTRAPOLATE(index[i].y, src_offset_x, src_offset_x + src_cols);
|
||||
EXTRAPOLATE(index[i].z, src_offset_x, src_offset_x + src_cols);
|
||||
EXTRAPOLATE(index[i].w, src_offset_x, src_offset_x + src_cols);
|
||||
#else
|
||||
EXTRAPOLATE(index[i].x, 0, src_whole_cols);
|
||||
EXTRAPOLATE(index[i].y, 0, src_whole_cols);
|
||||
EXTRAPOLATE(index[i].z, 0, src_whole_cols);
|
||||
EXTRAPOLATE(index[i].w, 0, src_whole_cols);
|
||||
#endif
|
||||
}
|
||||
s_y = start_y;
|
||||
#ifdef BORDER_ISOLATED
|
||||
EXTRAPOLATE(s_y, src_offset_y, src_offset_y + src_rows);
|
||||
#else
|
||||
EXTRAPOLATE(s_y, 0, src_whole_rows);
|
||||
#endif
|
||||
|
||||
// read pixels from src
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
addr = mad24((int4)s_y,(int4)src_step_in_pixel,index[i]);
|
||||
temp[i].x = src[addr.x];
|
||||
temp[i].y = src[addr.y];
|
||||
temp[i].z = src[addr.z];
|
||||
temp[i].w = src[addr.w];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// read pixels from src
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
temp[i] = *(__global uchar4*)&src[start_addr+i*LSIZE0*4];
|
||||
}
|
||||
#endif //BORDER_CONSTANT
|
||||
|
||||
// save pixels to lds
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
LDS_DAT[l_y][l_x+i*LSIZE0]=temp[i];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
// read pixels from lds and calculate the result
|
||||
sum =convert_float4(vload4(0,(__local uchar*)&LDS_DAT[l_y][l_x]+RADIUSX+offset))*mat_kernel[RADIUSX];
|
||||
for (i=1; i<=RADIUSX; i++)
|
||||
{
|
||||
temp[0] = vload4(0, (__local uchar*)&LDS_DAT[l_y][l_x] + RADIUSX + offset - i);
|
||||
temp[1] = vload4(0, (__local uchar*)&LDS_DAT[l_y][l_x] + RADIUSX + offset + i);
|
||||
sum += convert_float4(temp[0]) * mat_kernel[RADIUSX-i] + convert_float4(temp[1]) * mat_kernel[RADIUSX+i];
|
||||
}
|
||||
|
||||
start_addr = mad24(y,dst_step_in_pixel,x);
|
||||
|
||||
// write the result to dst
|
||||
if ((x+3<dst_cols) & (y<dst_rows))
|
||||
*(__global float4*)&dst[start_addr] = sum;
|
||||
else if ((x+2<dst_cols) && (y<dst_rows))
|
||||
{
|
||||
dst[start_addr] = sum.x;
|
||||
dst[start_addr+1] = sum.y;
|
||||
dst[start_addr+2] = sum.z;
|
||||
}
|
||||
else if ((x+1<dst_cols) && (y<dst_rows))
|
||||
{
|
||||
dst[start_addr] = sum.x;
|
||||
dst[start_addr+1] = sum.y;
|
||||
}
|
||||
else if (x<dst_cols && y<dst_rows)
|
||||
dst[start_addr] = sum.x;
|
||||
}
|
||||
|
||||
__kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_C4_D0
|
||||
(__global uchar4 * restrict src,
|
||||
int src_step_in_pixel,
|
||||
int src_offset_x, int src_offset_y,
|
||||
int src_cols, int src_rows,
|
||||
int src_whole_cols, int src_whole_rows,
|
||||
__global float4 * dst,
|
||||
int dst_step_in_pixel,
|
||||
int dst_cols, int dst_rows,
|
||||
int radiusy)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
int l_x = get_local_id(0);
|
||||
int l_y = get_local_id(1);
|
||||
int start_x = x+src_offset_x-RADIUSX;
|
||||
int start_y = y+src_offset_y-radiusy;
|
||||
int start_addr = mad24(start_y,src_step_in_pixel,start_x);
|
||||
int i;
|
||||
float4 sum;
|
||||
uchar4 temp[READ_TIMES_ROW];
|
||||
|
||||
__local uchar4 LDS_DAT[LSIZE1][READ_TIMES_ROW*LSIZE0+1];
|
||||
#ifdef BORDER_CONSTANT
|
||||
int end_addr = mad24(src_whole_rows - 1,src_step_in_pixel,src_whole_cols);
|
||||
|
||||
// read pixels from src
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
int current_addr = start_addr+i*LSIZE0;
|
||||
current_addr = ((current_addr < end_addr) && (current_addr > 0)) ? current_addr : 0;
|
||||
temp[i] = src[current_addr];
|
||||
}
|
||||
|
||||
//judge if read out of boundary
|
||||
#ifdef BORDER_ISOLATED
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
temp[i]= ELEM(start_x+i*LSIZE0, src_offset_x, src_offset_x + src_cols, (uchar4)0, temp[i]);
|
||||
temp[i]= ELEM(start_y, src_offset_y, src_offset_y + src_rows, (uchar4)0, temp[i]);
|
||||
}
|
||||
#else
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
temp[i]= ELEM(start_x+i*LSIZE0, 0, src_whole_cols, (uchar4)0, temp[i]);
|
||||
temp[i]= ELEM(start_y, 0, src_whole_rows, (uchar4)0, temp[i]);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
int index[READ_TIMES_ROW];
|
||||
int s_x,s_y;
|
||||
|
||||
// judge if read out of boundary
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
s_x = start_x+i*LSIZE0;
|
||||
s_y = start_y;
|
||||
#ifdef BORDER_ISOLATED
|
||||
EXTRAPOLATE(s_x, src_offset_x, src_offset_x + src_cols);
|
||||
EXTRAPOLATE(s_y, src_offset_y, src_offset_y + src_rows);
|
||||
#else
|
||||
EXTRAPOLATE(s_x, 0, src_whole_cols);
|
||||
EXTRAPOLATE(s_y, 0, src_whole_rows);
|
||||
#endif
|
||||
index[i]=mad24(s_y, src_step_in_pixel, s_x);
|
||||
}
|
||||
|
||||
//read pixels from src
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
temp[i] = src[index[i]];
|
||||
#endif //BORDER_CONSTANT
|
||||
|
||||
//save pixels to lds
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
LDS_DAT[l_y][l_x+i*LSIZE0]=temp[i];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
//read pixels from lds and calculate the result
|
||||
sum =convert_float4(LDS_DAT[l_y][l_x+RADIUSX])*mat_kernel[RADIUSX];
|
||||
for (i=1; i<=RADIUSX; i++)
|
||||
{
|
||||
temp[0]=LDS_DAT[l_y][l_x+RADIUSX-i];
|
||||
temp[1]=LDS_DAT[l_y][l_x+RADIUSX+i];
|
||||
sum += convert_float4(temp[0])*mat_kernel[RADIUSX-i]+convert_float4(temp[1])*mat_kernel[RADIUSX+i];
|
||||
}
|
||||
//write the result to dst
|
||||
if (x<dst_cols && y<dst_rows)
|
||||
{
|
||||
start_addr = mad24(y,dst_step_in_pixel,x);
|
||||
dst[start_addr] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_C1_D5
|
||||
(__global float * restrict src,
|
||||
int src_step_in_pixel,
|
||||
int src_offset_x, int src_offset_y,
|
||||
int src_cols, int src_rows,
|
||||
int src_whole_cols, int src_whole_rows,
|
||||
__global float * dst,
|
||||
int dst_step_in_pixel,
|
||||
int dst_cols, int dst_rows,
|
||||
int radiusy)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
int l_x = get_local_id(0);
|
||||
int l_y = get_local_id(1);
|
||||
int start_x = x+src_offset_x-RADIUSX;
|
||||
int start_y = y+src_offset_y-radiusy;
|
||||
int start_addr = mad24(start_y,src_step_in_pixel,start_x);
|
||||
int i;
|
||||
float sum;
|
||||
float temp[READ_TIMES_ROW];
|
||||
|
||||
__local float LDS_DAT[LSIZE1][READ_TIMES_ROW*LSIZE0+1];
|
||||
#ifdef BORDER_CONSTANT
|
||||
int end_addr = mad24(src_whole_rows - 1,src_step_in_pixel,src_whole_cols);
|
||||
|
||||
// read pixels from src
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
int current_addr = start_addr+i*LSIZE0;
|
||||
current_addr = ((current_addr < end_addr) && (current_addr > 0)) ? current_addr : 0;
|
||||
temp[i] = src[current_addr];
|
||||
}
|
||||
|
||||
// judge if read out of boundary
|
||||
#ifdef BORDER_ISOLATED
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
temp[i]= ELEM(start_x+i*LSIZE0, src_offset_x, src_offset_x + src_cols, (float)0,temp[i]);
|
||||
temp[i]= ELEM(start_y, src_offset_y, src_offset_y + src_rows, (float)0,temp[i]);
|
||||
}
|
||||
#else
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
temp[i]= ELEM(start_x+i*LSIZE0, 0, src_whole_cols, (float)0,temp[i]);
|
||||
temp[i]= ELEM(start_y, 0, src_whole_rows, (float)0,temp[i]);
|
||||
}
|
||||
#endif
|
||||
#else // BORDER_CONSTANT
|
||||
int index[READ_TIMES_ROW];
|
||||
int s_x,s_y;
|
||||
// judge if read out of boundary
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
s_x = start_x + i*LSIZE0, s_y = start_y;
|
||||
#ifdef BORDER_ISOLATED
|
||||
EXTRAPOLATE(s_x, src_offset_x, src_offset_x + src_cols);
|
||||
EXTRAPOLATE(s_y, src_offset_y, src_offset_y + src_rows);
|
||||
#else
|
||||
EXTRAPOLATE(s_x, 0, src_whole_cols);
|
||||
EXTRAPOLATE(s_y, 0, src_whole_rows);
|
||||
#endif
|
||||
|
||||
index[i]=mad24(s_y, src_step_in_pixel, s_x);
|
||||
}
|
||||
// read pixels from src
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
temp[i] = src[index[i]];
|
||||
#endif// BORDER_CONSTANT
|
||||
|
||||
//save pixels to lds
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
LDS_DAT[l_y][l_x+i*LSIZE0]=temp[i];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
// read pixels from lds and calculate the result
|
||||
sum =LDS_DAT[l_y][l_x+RADIUSX]*mat_kernel[RADIUSX];
|
||||
for (i=1; i<=RADIUSX; i++)
|
||||
{
|
||||
temp[0]=LDS_DAT[l_y][l_x+RADIUSX-i];
|
||||
temp[1]=LDS_DAT[l_y][l_x+RADIUSX+i];
|
||||
sum += temp[0]*mat_kernel[RADIUSX-i]+temp[1]*mat_kernel[RADIUSX+i];
|
||||
}
|
||||
|
||||
// write the result to dst
|
||||
if (x<dst_cols && y<dst_rows)
|
||||
{
|
||||
start_addr = mad24(y,dst_step_in_pixel,x);
|
||||
dst[start_addr] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_C4_D5
|
||||
(__global float4 * restrict src,
|
||||
int src_step_in_pixel,
|
||||
int src_offset_x, int src_offset_y,
|
||||
int src_cols, int src_rows,
|
||||
int src_whole_cols, int src_whole_rows,
|
||||
__global float4 * dst,
|
||||
int dst_step_in_pixel,
|
||||
int dst_cols, int dst_rows,
|
||||
int radiusy)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
int l_x = get_local_id(0);
|
||||
int l_y = get_local_id(1);
|
||||
int start_x = x+src_offset_x-RADIUSX;
|
||||
int start_y = y+src_offset_y-radiusy;
|
||||
int start_addr = mad24(start_y,src_step_in_pixel,start_x);
|
||||
int i;
|
||||
float4 sum;
|
||||
float4 temp[READ_TIMES_ROW];
|
||||
|
||||
__local float4 LDS_DAT[LSIZE1][READ_TIMES_ROW*LSIZE0+1];
|
||||
#ifdef BORDER_CONSTANT
|
||||
int end_addr = mad24(src_whole_rows - 1,src_step_in_pixel,src_whole_cols);
|
||||
|
||||
// read pixels from src
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
int current_addr = start_addr+i*LSIZE0;
|
||||
current_addr = ((current_addr < end_addr) && (current_addr > 0)) ? current_addr : 0;
|
||||
temp[i] = src[current_addr];
|
||||
}
|
||||
|
||||
// judge if read out of boundary
|
||||
#ifdef BORDER_ISOLATED
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
temp[i]= ELEM(start_x+i*LSIZE0, src_offset_x, src_offset_x + src_cols, (float4)0,temp[i]);
|
||||
temp[i]= ELEM(start_y, src_offset_y, src_offset_y + src_rows, (float4)0,temp[i]);
|
||||
}
|
||||
#else
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
temp[i]= ELEM(start_x+i*LSIZE0, 0, src_whole_cols, (float4)0,temp[i]);
|
||||
temp[i]= ELEM(start_y, 0, src_whole_rows, (float4)0,temp[i]);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
int index[READ_TIMES_ROW];
|
||||
int s_x,s_y;
|
||||
|
||||
// judge if read out of boundary
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
{
|
||||
s_x = start_x + i*LSIZE0, s_y = start_y;
|
||||
#ifdef BORDER_ISOLATED
|
||||
EXTRAPOLATE(s_x, src_offset_x, src_offset_x + src_cols);
|
||||
EXTRAPOLATE(s_y, src_offset_y, src_offset_y + src_rows);
|
||||
#else
|
||||
EXTRAPOLATE(s_x, 0, src_whole_cols);
|
||||
EXTRAPOLATE(s_y, 0, src_whole_rows);
|
||||
#endif
|
||||
|
||||
index[i]=mad24(s_y,src_step_in_pixel,s_x);
|
||||
}
|
||||
// read pixels from src
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
temp[i] = src[index[i]];
|
||||
#endif
|
||||
|
||||
// save pixels to lds
|
||||
for (i = 0; i<READ_TIMES_ROW; i++)
|
||||
LDS_DAT[l_y][l_x+i*LSIZE0]=temp[i];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
// read pixels from lds and calculate the result
|
||||
sum =LDS_DAT[l_y][l_x+RADIUSX]*mat_kernel[RADIUSX];
|
||||
for (i=1; i<=RADIUSX; i++)
|
||||
{
|
||||
temp[0]=LDS_DAT[l_y][l_x+RADIUSX-i];
|
||||
temp[1]=LDS_DAT[l_y][l_x+RADIUSX+i];
|
||||
sum += temp[0]*mat_kernel[RADIUSX-i]+temp[1]*mat_kernel[RADIUSX+i];
|
||||
}
|
||||
|
||||
// write the result to dst
|
||||
if (x<dst_cols && y<dst_rows)
|
||||
{
|
||||
start_addr = mad24(y,dst_step_in_pixel,x);
|
||||
dst[start_addr] = sum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Zhang Ying, zhangying913@gmail.com
|
||||
//
|
||||
// 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*/
|
||||
|
||||
__kernel void findCorners(__global const uchar * eigptr, int eig_step, int eig_offset,
|
||||
#ifdef HAVE_MASK
|
||||
__global const uchar * mask, int mask_step, int mask_offset,
|
||||
#endif
|
||||
__global const uchar * tmpptr, int tmp_step, int tmp_offset,
|
||||
__global uchar * cornersptr, __global int * counter,
|
||||
int rows, int cols)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < cols && y < rows)
|
||||
{
|
||||
++x, ++y;
|
||||
|
||||
int eig_index = mad24(y, eig_step, eig_offset + x * (int)sizeof(float));
|
||||
int tmp_index = mad24(y, tmp_step, tmp_offset + x * (int)sizeof(float));
|
||||
#ifdef HAVE_MASK
|
||||
int mask_index = mad24(y, mask_step, mask_offset + x);
|
||||
mask += mask_index;
|
||||
#endif
|
||||
|
||||
float val = *(__global const float *)(eigptr + eig_index);
|
||||
float tmp = *(__global const float *)(tmpptr + tmp_index);
|
||||
|
||||
if (val != 0 && val == tmp
|
||||
#ifdef HAVE_MASK
|
||||
&& mask[0] != 0
|
||||
#endif
|
||||
)
|
||||
{
|
||||
__global float2 * corners = (__global float2 *)(cornersptr + (int)sizeof(float2) * atomic_inc(counter));
|
||||
corners[0] = (float2)(val, as_float( (x<<16) | y ));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
// Jia Haipeng, jiahaipeng95@gmail.com
|
||||
// Xu Pang, pangxu010@163.com
|
||||
// Wenju He, wenju@multicorewareinc.com
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
|
||||
__kernel void calculate_histogram(__global const uchar * src, int src_step, int src_offset, int src_rows, int src_cols,
|
||||
__global uchar * hist, int total)
|
||||
{
|
||||
int lid = get_local_id(0);
|
||||
int id = get_global_id(0);
|
||||
int gid = get_group_id(0);
|
||||
|
||||
__local int localhist[BINS];
|
||||
|
||||
for (int i = lid; i < BINS; i += WGS)
|
||||
localhist[i] = 0;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
for (int grain = HISTS_COUNT * WGS; id < total; id += grain)
|
||||
{
|
||||
int src_index = mad24(id / src_cols, src_step, src_offset + id % src_cols);
|
||||
atomic_inc(localhist + (int)src[src_index]);
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
for (int i = lid; i < BINS; i += WGS)
|
||||
*(__global int *)(hist + mad24(gid, BINS * (int)sizeof(int), i * (int)sizeof(int))) = localhist[i];
|
||||
}
|
||||
|
||||
__kernel void merge_histogram(__global const int * ghist, __global int * hist)
|
||||
{
|
||||
int lid = get_local_id(0);
|
||||
|
||||
#pragma unroll
|
||||
for (int i = lid; i < BINS; i += WGS)
|
||||
hist[i] = 0;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
#pragma unroll
|
||||
for (int i = 0; i < HISTS_COUNT; ++i)
|
||||
{
|
||||
#pragma unroll
|
||||
for (int j = lid; j < BINS; j += WGS)
|
||||
hist[j] += ghist[mad24(i, BINS, j)];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void calcLUT(__global uchar * dst, __constant int * hist, int total)
|
||||
{
|
||||
int lid = get_local_id(0);
|
||||
__local int sumhist[BINS];
|
||||
__local float scale;
|
||||
|
||||
sumhist[lid] = hist[lid];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (lid == 0)
|
||||
{
|
||||
int sum = 0, i = 0;
|
||||
while (!sumhist[i])
|
||||
++i;
|
||||
|
||||
if (total == sumhist[i])
|
||||
{
|
||||
scale = 1;
|
||||
for (int j = 0; j < BINS; ++j)
|
||||
sumhist[i] = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = 255.f / (total - sumhist[i]);
|
||||
|
||||
for (sumhist[i++] = 0; i < BINS; i++)
|
||||
{
|
||||
sum += sumhist[i];
|
||||
sumhist[i] = sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
#pragma unroll
|
||||
for (int i = lid; i < BINS; i += WGS)
|
||||
dst[i]= convert_uchar_sat_rte(convert_float(sumhist[i]) * scale);
|
||||
}
|
||||
@@ -0,0 +1,461 @@
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, 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.
|
||||
|
||||
#define DATA_SIZE ((int)sizeof(type))
|
||||
#define ELEM_TYPE elem_type
|
||||
#define ELEM_SIZE ((int)sizeof(elem_type))
|
||||
|
||||
#define SQSUMS_PTR(ox, oy) mad24(y + oy, src_sqsums_step, mad24(x + ox, cn, src_sqsums_offset))
|
||||
#define SUMS_PTR(ox, oy) mad24(y + oy, src_sums_step, mad24(x + ox, cn, src_sums_offset))
|
||||
|
||||
inline float normAcc(float num, float denum)
|
||||
{
|
||||
if (fabs(num) < denum)
|
||||
return num / denum;
|
||||
if (fabs(num) < denum * 1.125f)
|
||||
return num > 0 ? 1 : -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline float normAcc_SQDIFF(float num, float denum)
|
||||
{
|
||||
if (fabs(num) < denum)
|
||||
return num / denum;
|
||||
if (fabs(num) < denum * 1.125f)
|
||||
return num > 0 ? 1 : -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define noconvert
|
||||
|
||||
#if cn == 1
|
||||
#define convertToDT(value) (float)(value)
|
||||
#elif cn == 2
|
||||
#define convertToDT(value) (float)(value.x + value.y)
|
||||
#elif cn == 4
|
||||
#define convertToDT(value) (float)(value.x + value.y + value.z + value.w)
|
||||
#else
|
||||
#error "cn should be 1, 2 or 4"
|
||||
#endif
|
||||
|
||||
#ifdef CALC_SUM
|
||||
|
||||
__kernel void calcSum(__global const uchar * srcptr, int src_step, int src_offset,
|
||||
int cols, int total, __global float * dst)
|
||||
{
|
||||
int lid = get_local_id(0), id = get_global_id(0);
|
||||
|
||||
__local WT localmem[WGS2_ALIGNED];
|
||||
WT accumulator = (WT)(0), tmp;
|
||||
|
||||
for ( ; id < total; id += WGS)
|
||||
{
|
||||
int src_index = mad24(id / cols, src_step, mad24(id % cols, (int)sizeof(T), src_offset));
|
||||
__global const T * src = (__global const T *)(srcptr + src_index);
|
||||
|
||||
tmp = convertToWT(src[0]);
|
||||
#if wdepth == 4
|
||||
accumulator = mad24(tmp, tmp, accumulator);
|
||||
#else
|
||||
accumulator = mad(tmp, tmp, accumulator);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (lid < WGS2_ALIGNED)
|
||||
localmem[lid] = accumulator;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (lid >= WGS2_ALIGNED && total >= WGS2_ALIGNED)
|
||||
localmem[lid - WGS2_ALIGNED] += accumulator;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
for (int lsize = WGS2_ALIGNED >> 1; lsize > 0; lsize >>= 1)
|
||||
{
|
||||
if (lid < lsize)
|
||||
{
|
||||
int lid2 = lsize + lid;
|
||||
localmem[lid] += localmem[lid2];
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
|
||||
if (lid == 0)
|
||||
dst[0] = convertToDT(localmem[0]);
|
||||
}
|
||||
|
||||
#elif defined CCORR
|
||||
|
||||
__kernel void matchTemplate_Naive_CCORR(__global const uchar * srcptr, int src_step, int src_offset,
|
||||
__global const uchar * templateptr, int template_step, int template_offset, int template_rows, int template_cols,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
WT sum = (WT)(0);
|
||||
|
||||
__global const T * src = (__global const T *)(srcptr + mad24(y, src_step, mad24(x, (int)sizeof(T), src_offset)));
|
||||
__global const T * template = (__global const T *)(templateptr + template_offset);
|
||||
|
||||
for (int i = 0; i < template_rows; ++i)
|
||||
{
|
||||
for (int j = 0; j < template_cols; ++j)
|
||||
#if wdepth == 4
|
||||
sum = mad24(convertToWT(src[j]), convertToWT(template[j]), sum);
|
||||
#else
|
||||
sum = mad(convertToWT(src[j]), convertToWT(template[j]), sum);
|
||||
#endif
|
||||
|
||||
src = (__global const T *)((__global const uchar *)src + src_step);
|
||||
template = (__global const T *)((__global const uchar *)template + template_step);
|
||||
}
|
||||
|
||||
int dst_idx = mad24(y, dst_step, mad24(x, (int)sizeof(float), dst_offset));
|
||||
*(__global float *)(dst + dst_idx) = convertToDT(sum);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined CCORR_NORMED
|
||||
|
||||
__kernel void matchTemplate_CCORR_NORMED(__global const uchar * src_sqsums, int src_sqsums_step, int src_sqsums_offset,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
int template_rows, int template_cols, __global const float * template_sqsum)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
__global const float * sqsum = (__global const float *)(src_sqsums);
|
||||
|
||||
src_sqsums_step /= sizeof(float);
|
||||
src_sqsums_offset /= sizeof(float);
|
||||
float image_sqsum_ = (float)(sqsum[SQSUMS_PTR(template_cols, template_rows)] - sqsum[SQSUMS_PTR(template_cols, 0)] -
|
||||
sqsum[SQSUMS_PTR(0, template_rows)] + sqsum[SQSUMS_PTR(0, 0)]);
|
||||
|
||||
int dst_idx = mad24(y, dst_step, mad24(x, (int)sizeof(float), dst_offset));
|
||||
__global float * dstult = (__global float *)(dst + dst_idx);
|
||||
*dstult = normAcc(*dstult, sqrt(image_sqsum_ * template_sqsum[0]));
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SQDIFF
|
||||
|
||||
__kernel void matchTemplate_Naive_SQDIFF(__global const uchar * srcptr, int src_step, int src_offset,
|
||||
__global const uchar * templateptr, int template_step, int template_offset, int template_rows, int template_cols,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
__global const T * src = (__global const T *)(srcptr + mad24(y, src_step, mad24(x, (int)sizeof(T), src_offset)));
|
||||
__global const T * template = (__global const T *)(templateptr + template_offset);
|
||||
|
||||
WT sum = (WT)(0), value;
|
||||
|
||||
for (int i = 0; i < template_rows; ++i)
|
||||
{
|
||||
for (int j = 0; j < template_cols; ++j)
|
||||
{
|
||||
value = convertToWT(src[j]) - convertToWT(template[j]);
|
||||
#if wdepth == 4
|
||||
sum = mad24(value, value, sum);
|
||||
#else
|
||||
sum = mad(value, value, sum);
|
||||
#endif
|
||||
}
|
||||
|
||||
src = (__global const T *)((__global const uchar *)src + src_step);
|
||||
template = (__global const T *)((__global const uchar *)template + template_step);
|
||||
}
|
||||
|
||||
int dst_idx = mad24(y, dst_step, mad24(x, (int)sizeof(float), dst_offset));
|
||||
*(__global float *)(dst + dst_idx) = convertToDT(sum);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SQDIFF_NORMED
|
||||
|
||||
__kernel void matchTemplate_SQDIFF_NORMED(__global const uchar * src_sqsums, int src_sqsums_step, int src_sqsums_offset,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
int template_rows, int template_cols, __global const float * template_sqsum)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
src_sqsums_step /= sizeof(float);
|
||||
src_sqsums_offset /= sizeof(float);
|
||||
|
||||
__global const float * sqsum = (__global const float *)(src_sqsums);
|
||||
float image_sqsum_ = (float)(
|
||||
(sqsum[SQSUMS_PTR(template_cols, template_rows)] - sqsum[SQSUMS_PTR(template_cols, 0)]) -
|
||||
(sqsum[SQSUMS_PTR(0, template_rows)] - sqsum[SQSUMS_PTR(0, 0)]));
|
||||
float template_sqsum_value = template_sqsum[0];
|
||||
|
||||
int dst_idx = mad24(y, dst_step, mad24(x, (int)sizeof(float), dst_offset));
|
||||
__global float * dstult = (__global float *)(dst + dst_idx);
|
||||
*dstult = normAcc_SQDIFF(image_sqsum_ - 2.0f * dstult[0] + template_sqsum_value, sqrt(image_sqsum_ * template_sqsum_value));
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined CCOEFF
|
||||
|
||||
#if cn == 1
|
||||
|
||||
__kernel void matchTemplate_Prepared_CCOEFF(__global const uchar * src_sums, int src_sums_step, int src_sums_offset,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
int template_rows, int template_cols, float template_sum)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
__global ELEM_TYPE* sum = (__global ELEM_TYPE*)(src_sums);
|
||||
|
||||
src_sums_step /= ELEM_SIZE;
|
||||
src_sums_offset /= ELEM_SIZE;
|
||||
float image_sum_ = (float)((sum[SUMS_PTR(template_cols, template_rows)] - sum[SUMS_PTR(template_cols, 0)])-
|
||||
(sum[SUMS_PTR(0, template_rows)] - sum[SUMS_PTR(0, 0)])) * template_sum;
|
||||
|
||||
int dst_idx = mad24(y, dst_step, mad24(x, (int)sizeof(float), dst_offset));
|
||||
__global float * dstult = (__global float *)(dst + dst_idx);
|
||||
*dstult -= image_sum_;
|
||||
}
|
||||
}
|
||||
|
||||
#elif cn == 2
|
||||
|
||||
__kernel void matchTemplate_Prepared_CCOEFF(__global const uchar * src_sums, int src_sums_step, int src_sums_offset,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
int template_rows, int template_cols, float template_sum_0, float template_sum_1)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
src_sums_step /= ELEM_SIZE;
|
||||
src_sums_offset /= ELEM_SIZE;
|
||||
|
||||
__global ELEM_TYPE* sum = (__global ELEM_TYPE*)(src_sums);
|
||||
|
||||
float image_sum_ = template_sum_0 * (float)((sum[SUMS_PTR(template_cols, template_rows)] - sum[SUMS_PTR(template_cols, 0)]) -(sum[SUMS_PTR(0, template_rows)] - sum[SUMS_PTR(0, 0)]));
|
||||
image_sum_ += template_sum_1 * (float)((sum[SUMS_PTR(template_cols, template_rows)+1] - sum[SUMS_PTR(template_cols, 0)+1])-(sum[SUMS_PTR(0, template_rows)+1] - sum[SUMS_PTR(0, 0)+1]));
|
||||
|
||||
|
||||
int dst_idx = mad24(y, dst_step, mad24(x, (int)sizeof(float), dst_offset));
|
||||
__global float * dstult = (__global float *)(dst+dst_idx);
|
||||
*dstult -= image_sum_;
|
||||
}
|
||||
}
|
||||
|
||||
#elif cn == 4
|
||||
|
||||
__kernel void matchTemplate_Prepared_CCOEFF(__global const uchar * src_sums, int src_sums_step, int src_sums_offset,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
int template_rows, int template_cols, float template_sum_0, float template_sum_1, float template_sum_2, float template_sum_3)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
src_sums_step /= ELEM_SIZE;
|
||||
src_sums_offset /= ELEM_SIZE;
|
||||
|
||||
__global ELEM_TYPE* sum = (__global ELEM_TYPE*)(src_sums);
|
||||
|
||||
int c_r = SUMS_PTR(template_cols, template_rows);
|
||||
int c_o = SUMS_PTR(template_cols, 0);
|
||||
int o_r = SUMS_PTR(0,template_rows);
|
||||
int oo = SUMS_PTR(0, 0);
|
||||
|
||||
float image_sum_ = template_sum_0 * (float)((sum[c_r] - sum[c_o]) -(sum[o_r] - sum[oo]));
|
||||
image_sum_ += template_sum_1 * (float)((sum[c_r+1] - sum[c_o+1])-(sum[o_r+1] - sum[oo+1]));
|
||||
image_sum_ += template_sum_2 * (float)((sum[c_r+2] - sum[c_o+2])-(sum[o_r+2] - sum[oo+2]));
|
||||
image_sum_ += template_sum_3 * (float)((sum[c_r+3] - sum[c_o+3])-(sum[o_r+3] - sum[oo+3]));
|
||||
|
||||
int dst_idx = mad24(y, dst_step, mad24(x, (int)sizeof(float), dst_offset));
|
||||
__global float * dstult = (__global float *)(dst+dst_idx);
|
||||
*dstult -= image_sum_;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#error "cn should be 1, 2 or 4"
|
||||
#endif
|
||||
|
||||
#elif defined CCOEFF_NORMED
|
||||
|
||||
#if cn == 1
|
||||
|
||||
__kernel void matchTemplate_CCOEFF_NORMED(__global const uchar * src_sums, int src_sums_step, int src_sums_offset,
|
||||
__global const uchar * src_sqsums, int src_sqsums_step, int src_sqsums_offset,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
int t_rows, int t_cols, float weight, float template_sum, float template_sqsum)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
src_sums_offset /= ELEM_SIZE;
|
||||
src_sums_step /= ELEM_SIZE;
|
||||
src_sqsums_step /= sizeof(float);
|
||||
src_sqsums_offset /= sizeof(float);
|
||||
|
||||
__global ELEM_TYPE* sum = (__global ELEM_TYPE*)(src_sums);
|
||||
__global float * sqsum = (__global float*)(src_sqsums);
|
||||
|
||||
float image_sum_ = (float)((sum[SUMS_PTR(t_cols, t_rows)] - sum[SUMS_PTR(t_cols, 0)]) -
|
||||
(sum[SUMS_PTR(0, t_rows)] - sum[SUMS_PTR(0, 0)]));
|
||||
|
||||
float image_sqsum_ = (float)((sqsum[SQSUMS_PTR(t_cols, t_rows)] - sqsum[SQSUMS_PTR(t_cols, 0)]) -
|
||||
(sqsum[SQSUMS_PTR(0, t_rows)] - sqsum[SQSUMS_PTR(0, 0)]));
|
||||
|
||||
int dst_idx = mad24(y, dst_step, mad24(x, (int)sizeof(float), dst_offset));
|
||||
__global float * dstult = (__global float *)(dst+dst_idx);
|
||||
*dstult = normAcc((*dstult) - image_sum_ * template_sum,
|
||||
sqrt(template_sqsum * (image_sqsum_ - weight * image_sum_ * image_sum_)));
|
||||
}
|
||||
}
|
||||
|
||||
#elif cn == 2
|
||||
|
||||
__kernel void matchTemplate_CCOEFF_NORMED(__global const uchar * src_sums, int src_sums_step, int src_sums_offset,
|
||||
__global const uchar * src_sqsums, int src_sqsums_step, int src_sqsums_offset,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
int t_rows, int t_cols, float weight, float template_sum_0, float template_sum_1, float template_sqsum)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
float sum_[2];
|
||||
float sqsum_[2];
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
src_sums_offset /= ELEM_SIZE;
|
||||
src_sums_step /= ELEM_SIZE;
|
||||
src_sqsums_step /= sizeof(float);
|
||||
src_sqsums_offset /= sizeof(float);
|
||||
|
||||
__global ELEM_TYPE* sum = (__global ELEM_TYPE*)(src_sums);
|
||||
__global float * sqsum = (__global float*)(src_sqsums);
|
||||
|
||||
sum_[0] = (float)((sum[SUMS_PTR(t_cols, t_rows)] - sum[SUMS_PTR(t_cols, 0)])-(sum[SUMS_PTR(0, t_rows)] - sum[SUMS_PTR(0, 0)]));
|
||||
sum_[1] = (float)((sum[SUMS_PTR(t_cols, t_rows)+1] - sum[SUMS_PTR(t_cols, 0)+1])-(sum[SUMS_PTR(0, t_rows)+1] - sum[SUMS_PTR(0, 0)+1]));
|
||||
|
||||
sqsum_[0] = (float)((sqsum[SQSUMS_PTR(t_cols, t_rows)] - sqsum[SQSUMS_PTR(t_cols, 0)])-(sqsum[SQSUMS_PTR(0, t_rows)] - sqsum[SQSUMS_PTR(0, 0)]));
|
||||
sqsum_[1] = (float)((sqsum[SQSUMS_PTR(t_cols, t_rows)+1] - sqsum[SQSUMS_PTR(t_cols, 0)+1])-(sqsum[SQSUMS_PTR(0, t_rows)+1] - sqsum[SQSUMS_PTR(0, 0)+1]));
|
||||
|
||||
float num = sum_[0]*template_sum_0 + sum_[1]*template_sum_1;
|
||||
|
||||
float denum = sqrt( template_sqsum * (sqsum_[0] - weight * sum_[0]* sum_[0] +
|
||||
sqsum_[1] - weight * sum_[1]* sum_[1]));
|
||||
|
||||
int dst_idx = mad24(y, dst_step, mad24(x, (int)sizeof(float), dst_offset));
|
||||
__global float * dstult = (__global float *)(dst+dst_idx);
|
||||
*dstult = normAcc((*dstult) - num, denum);
|
||||
}
|
||||
}
|
||||
|
||||
#elif cn == 4
|
||||
|
||||
__kernel void matchTemplate_CCOEFF_NORMED(__global const uchar * src_sums, int src_sums_step, int src_sums_offset,
|
||||
__global const uchar * src_sqsums, int src_sqsums_step, int src_sqsums_offset,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
int t_rows, int t_cols, float weight,
|
||||
float template_sum_0, float template_sum_1, float template_sum_2, float template_sum_3,
|
||||
float template_sqsum)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
float sum_[4];
|
||||
float sqsum_[4];
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
src_sums_offset /= ELEM_SIZE;
|
||||
src_sums_step /= ELEM_SIZE;
|
||||
src_sqsums_step /= sizeof(float);
|
||||
src_sqsums_offset /= sizeof(float);
|
||||
|
||||
__global ELEM_TYPE* sum = (__global ELEM_TYPE*)(src_sums);
|
||||
__global float * sqsum = (__global float*)(src_sqsums);
|
||||
|
||||
int c_r = SUMS_PTR(t_cols, t_rows);
|
||||
int c_o = SUMS_PTR(t_cols, 0);
|
||||
int o_r = SUMS_PTR(0, t_rows);
|
||||
int o_o = SUMS_PTR(0, 0);
|
||||
|
||||
sum_[0] = (float)((sum[c_r] - sum[c_o]) -(sum[o_r] - sum[o_o ]));
|
||||
sum_[1] = (float)((sum[c_r+1] - sum[c_o+1])-(sum[o_r+1] - sum[o_o +1]));
|
||||
sum_[2] = (float)((sum[c_r+2] - sum[c_o+2])-(sum[o_r+2] - sum[o_o +2]));
|
||||
sum_[3] = (float)((sum[c_r+3] - sum[c_o+3])-(sum[o_r+3] - sum[o_o +3]));
|
||||
|
||||
c_r = SQSUMS_PTR(t_cols, t_rows);
|
||||
c_o = SQSUMS_PTR(t_cols, 0);
|
||||
o_r = SQSUMS_PTR(0, t_rows);
|
||||
o_o = SQSUMS_PTR(0, 0);
|
||||
|
||||
sqsum_[0] = (float)((sqsum[c_r] - sqsum[c_o]) -(sqsum[o_r] - sqsum[o_o]));
|
||||
sqsum_[1] = (float)((sqsum[c_r+1] - sqsum[c_o+1])-(sqsum[o_r+1] - sqsum[o_o+1]));
|
||||
sqsum_[2] = (float)((sqsum[c_r+2] - sqsum[c_o+2])-(sqsum[o_r+2] - sqsum[o_o+2]));
|
||||
sqsum_[3] = (float)((sqsum[c_r+3] - sqsum[c_o+3])-(sqsum[o_r+3] - sqsum[o_o+3]));
|
||||
|
||||
float num = sum_[0]*template_sum_0 + sum_[1]*template_sum_1 + sum_[2]*template_sum_2 + sum_[3]*template_sum_3;
|
||||
|
||||
float denum = sqrt( template_sqsum * (
|
||||
sqsum_[0] - weight * sum_[0]* sum_[0] +
|
||||
sqsum_[1] - weight * sum_[1]* sum_[1] +
|
||||
sqsum_[2] - weight * sum_[2]* sum_[2] +
|
||||
sqsum_[3] - weight * sum_[3]* sum_[3] ));
|
||||
|
||||
int dst_idx = mad24(y, dst_step, mad24(x, (int)sizeof(float), dst_offset));
|
||||
__global float * dstult = (__global float *)(dst+dst_idx);
|
||||
*dstult = normAcc((*dstult) - num, denum);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#error "cn should be 1, 2 or 4"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,167 @@
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, 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.
|
||||
|
||||
#define DATA_TYPE type
|
||||
|
||||
#define scnbytes ((int)sizeof(type))
|
||||
|
||||
#define op(a,b) { mid=a; a=min(a,b); b=max(mid,b);}
|
||||
|
||||
__kernel void medianFilter3(__global const uchar* srcptr, int srcStep, int srcOffset,
|
||||
__global uchar* dstptr, int dstStep, int dstOffset,
|
||||
int rows, int cols)
|
||||
{
|
||||
__local DATA_TYPE data[18][18];
|
||||
|
||||
int x = get_local_id(0);
|
||||
int y = get_local_id(1);
|
||||
|
||||
int gx= get_global_id(0);
|
||||
int gy= get_global_id(1);
|
||||
|
||||
int dx = gx - x - 1;
|
||||
int dy = gy - y - 1;
|
||||
|
||||
const int id = min((int)(x*16+y), 9*18-1);
|
||||
|
||||
int dr = id / 18;
|
||||
int dc = id % 18;
|
||||
|
||||
int c = clamp(dx+dc, 0, cols-1);
|
||||
|
||||
int r = clamp(dy+dr, 0, rows-1);
|
||||
int index1 = mad24(r, srcStep, srcOffset + c*scnbytes);
|
||||
|
||||
r = clamp(dy+dr+9, 0, rows-1);
|
||||
int index9 = mad24(r, srcStep, srcOffset + c*scnbytes);
|
||||
|
||||
__global DATA_TYPE * src = (__global DATA_TYPE *)(srcptr + index1);
|
||||
data[dr][dc] = src[0];
|
||||
|
||||
src = (__global DATA_TYPE *)(srcptr + index9);
|
||||
data[dr+9][dc] = src[0];
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
DATA_TYPE p0=data[y][x], p1=data[y][(x+1)], p2=data[y][(x+2)];
|
||||
DATA_TYPE p3=data[y+1][x], p4=data[y+1][(x+1)], p5=data[y+1][(x+2)];
|
||||
DATA_TYPE p6=data[y+2][x], p7=data[y+2][(x+1)], p8=data[y+2][(x+2)];
|
||||
DATA_TYPE mid;
|
||||
|
||||
op(p1, p2); op(p4, p5); op(p7, p8); op(p0, p1);
|
||||
op(p3, p4); op(p6, p7); op(p1, p2); op(p4, p5);
|
||||
op(p7, p8); op(p0, p3); op(p5, p8); op(p4, p7);
|
||||
op(p3, p6); op(p1, p4); op(p2, p5); op(p4, p7);
|
||||
op(p4, p2); op(p6, p4); op(p4, p2);
|
||||
|
||||
int dst_index = mad24( gy, dstStep, dstOffset + gx * scnbytes);
|
||||
|
||||
if( gy < rows && gx < cols)
|
||||
{
|
||||
__global DATA_TYPE* dst = (__global DATA_TYPE *)(dstptr + dst_index);
|
||||
dst[0] = p4;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void medianFilter5(__global const uchar* srcptr, int srcStep, int srcOffset,
|
||||
__global uchar* dstptr, int dstStep, int dstOffset,
|
||||
int rows, int cols)
|
||||
{
|
||||
__local DATA_TYPE data[20][20];
|
||||
|
||||
int x =get_local_id(0);
|
||||
int y =get_local_id(1);
|
||||
|
||||
int gx=get_global_id(0);
|
||||
int gy=get_global_id(1);
|
||||
|
||||
int dx = gx - x - 2;
|
||||
int dy = gy - y - 2;
|
||||
|
||||
const int id = min((int)(x*16+y), 10*20-1);
|
||||
|
||||
int dr=id/20;
|
||||
int dc=id%20;
|
||||
|
||||
int c=clamp(dx+dc, 0, cols-1);
|
||||
|
||||
int r = clamp(dy+dr, 0, rows-1);
|
||||
int index1 = mad24(r, srcStep, srcOffset + c*scnbytes);
|
||||
|
||||
r = clamp(dy+dr+10, 0, rows-1);
|
||||
int index10 = mad24(r, srcStep, srcOffset + c*scnbytes);
|
||||
|
||||
__global DATA_TYPE * src = (__global DATA_TYPE *)(srcptr + index1);
|
||||
data[dr][dc] = src[0];
|
||||
src = (__global DATA_TYPE *)(srcptr + index10);
|
||||
data[dr+10][dc] = src[0];
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
DATA_TYPE p0=data[y][x], p1=data[y][x+1], p2=data[y][x+2], p3=data[y][x+3], p4=data[y][x+4];
|
||||
DATA_TYPE p5=data[y+1][x], p6=data[y+1][x+1], p7=data[y+1][x+2], p8=data[y+1][x+3], p9=data[y+1][x+4];
|
||||
DATA_TYPE p10=data[y+2][x], p11=data[y+2][x+1], p12=data[y+2][x+2], p13=data[y+2][x+3], p14=data[y+2][x+4];
|
||||
DATA_TYPE p15=data[y+3][x], p16=data[y+3][x+1], p17=data[y+3][x+2], p18=data[y+3][x+3], p19=data[y+3][x+4];
|
||||
DATA_TYPE p20=data[y+4][x], p21=data[y+4][x+1], p22=data[y+4][x+2], p23=data[y+4][x+3], p24=data[y+4][x+4];
|
||||
DATA_TYPE mid;
|
||||
|
||||
op(p1, p2); op(p0, p1); op(p1, p2); op(p4, p5); op(p3, p4);
|
||||
op(p4, p5); op(p0, p3); op(p2, p5); op(p2, p3); op(p1, p4);
|
||||
op(p1, p2); op(p3, p4); op(p7, p8); op(p6, p7); op(p7, p8);
|
||||
op(p10, p11); op(p9, p10); op(p10, p11); op(p6, p9); op(p8, p11);
|
||||
op(p8, p9); op(p7, p10); op(p7, p8); op(p9, p10); op(p0, p6);
|
||||
op(p4, p10); op(p4, p6); op(p2, p8); op(p2, p4); op(p6, p8);
|
||||
op(p1, p7); op(p5, p11); op(p5, p7); op(p3, p9); op(p3, p5);
|
||||
op(p7, p9); op(p1, p2); op(p3, p4); op(p5, p6); op(p7, p8);
|
||||
op(p9, p10); op(p13, p14); op(p12, p13); op(p13, p14); op(p16, p17);
|
||||
op(p15, p16); op(p16, p17); op(p12, p15); op(p14, p17); op(p14, p15);
|
||||
op(p13, p16); op(p13, p14); op(p15, p16); op(p19, p20); op(p18, p19);
|
||||
op(p19, p20); op(p21, p22); op(p23, p24); op(p21, p23); op(p22, p24);
|
||||
op(p22, p23); op(p18, p21); op(p20, p23); op(p20, p21); op(p19, p22);
|
||||
op(p22, p24); op(p19, p20); op(p21, p22); op(p23, p24); op(p12, p18);
|
||||
op(p16, p22); op(p16, p18); op(p14, p20); op(p20, p24); op(p14, p16);
|
||||
op(p18, p20); op(p22, p24); op(p13, p19); op(p17, p23); op(p17, p19);
|
||||
op(p15, p21); op(p15, p17); op(p19, p21); op(p13, p14); op(p15, p16);
|
||||
op(p17, p18); op(p19, p20); op(p21, p22); op(p23, p24); op(p0, p12);
|
||||
op(p8, p20); op(p8, p12); op(p4, p16); op(p16, p24); op(p12, p16);
|
||||
op(p2, p14); op(p10, p22); op(p10, p14); op(p6, p18); op(p6, p10);
|
||||
op(p10, p12); op(p1, p13); op(p9, p21); op(p9, p13); op(p5, p17);
|
||||
op(p13, p17); op(p3, p15); op(p11, p23); op(p11, p15); op(p7, p19);
|
||||
op(p7, p11); op(p11, p13); op(p11, p12);
|
||||
|
||||
int dst_index = mad24( gy, dstStep, dstOffset + gx * scnbytes);
|
||||
|
||||
if( gy < rows && gx < cols)
|
||||
{
|
||||
__global DATA_TYPE* dst = (__global DATA_TYPE *)(dstptr + dst_index);
|
||||
dst[0] = p12;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/* See LICENSE file in the root OpenCV directory */
|
||||
|
||||
#if TILE_SIZE != 32
|
||||
#error "TILE SIZE should be 32"
|
||||
#endif
|
||||
|
||||
__kernel void moments(__global const uchar* src, int src_step, int src_offset,
|
||||
int src_rows, int src_cols, __global int* mom0, int xtiles)
|
||||
{
|
||||
int x0 = get_global_id(0);
|
||||
int y0 = get_group_id(1);
|
||||
int x, y = get_local_id(1);
|
||||
int x_min = x0*TILE_SIZE;
|
||||
int ypix = y0*TILE_SIZE + y;
|
||||
__local int mom[TILE_SIZE][10];
|
||||
|
||||
if( x_min < src_cols && y0*TILE_SIZE < src_rows )
|
||||
{
|
||||
if( ypix < src_rows )
|
||||
{
|
||||
int x_max = min(src_cols - x_min, TILE_SIZE);
|
||||
__global const uchar* ptr = src + src_offset + ypix*src_step + x_min;
|
||||
int4 S = (int4)(0,0,0,0), p;
|
||||
|
||||
#define SUM_ELEM(elem, ofs) \
|
||||
(int4)(1, (ofs), (ofs)*(ofs), (ofs)*(ofs)*(ofs))*elem
|
||||
|
||||
x = x_max & -4;
|
||||
if( x_max >= 4 )
|
||||
{
|
||||
p = convert_int4(vload4(0, ptr));
|
||||
S += SUM_ELEM(p.s0, 0) + SUM_ELEM(p.s1, 1) + SUM_ELEM(p.s2, 2) + SUM_ELEM(p.s3, 3);
|
||||
|
||||
if( x_max >= 8 )
|
||||
{
|
||||
p = convert_int4(vload4(0, ptr+4));
|
||||
S += SUM_ELEM(p.s0, 4) + SUM_ELEM(p.s1, 5) + SUM_ELEM(p.s2, 6) + SUM_ELEM(p.s3, 7);
|
||||
|
||||
if( x_max >= 12 )
|
||||
{
|
||||
p = convert_int4(vload4(0, ptr+8));
|
||||
S += SUM_ELEM(p.s0, 8) + SUM_ELEM(p.s1, 9) + SUM_ELEM(p.s2, 10) + SUM_ELEM(p.s3, 11);
|
||||
|
||||
if( x_max >= 16 )
|
||||
{
|
||||
p = convert_int4(vload4(0, ptr+12));
|
||||
S += SUM_ELEM(p.s0, 12) + SUM_ELEM(p.s1, 13) + SUM_ELEM(p.s2, 14) + SUM_ELEM(p.s3, 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( x_max >= 20 )
|
||||
{
|
||||
p = convert_int4(vload4(0, ptr+16));
|
||||
S += SUM_ELEM(p.s0, 16) + SUM_ELEM(p.s1, 17) + SUM_ELEM(p.s2, 18) + SUM_ELEM(p.s3, 19);
|
||||
|
||||
if( x_max >= 24 )
|
||||
{
|
||||
p = convert_int4(vload4(0, ptr+20));
|
||||
S += SUM_ELEM(p.s0, 20) + SUM_ELEM(p.s1, 21) + SUM_ELEM(p.s2, 22) + SUM_ELEM(p.s3, 23);
|
||||
|
||||
if( x_max >= 28 )
|
||||
{
|
||||
p = convert_int4(vload4(0, ptr+24));
|
||||
S += SUM_ELEM(p.s0, 24) + SUM_ELEM(p.s1, 25) + SUM_ELEM(p.s2, 26) + SUM_ELEM(p.s3, 27);
|
||||
|
||||
if( x_max >= 32 )
|
||||
{
|
||||
p = convert_int4(vload4(0, ptr+28));
|
||||
S += SUM_ELEM(p.s0, 28) + SUM_ELEM(p.s1, 29) + SUM_ELEM(p.s2, 30) + SUM_ELEM(p.s3, 31);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( x < x_max )
|
||||
{
|
||||
int ps = ptr[x];
|
||||
S += SUM_ELEM(ps, x);
|
||||
if( x+1 < x_max )
|
||||
{
|
||||
ps = ptr[x+1];
|
||||
S += SUM_ELEM(ps, x+1);
|
||||
if( x+2 < x_max )
|
||||
{
|
||||
ps = ptr[x+2];
|
||||
S += SUM_ELEM(ps, x+2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int sy = y*y;
|
||||
|
||||
mom[y][0] = S.s0;
|
||||
mom[y][1] = S.s1;
|
||||
mom[y][2] = y*S.s0;
|
||||
mom[y][3] = S.s2;
|
||||
mom[y][4] = y*S.s1;
|
||||
mom[y][5] = sy*S.s0;
|
||||
mom[y][6] = S.s3;
|
||||
mom[y][7] = y*S.s2;
|
||||
mom[y][8] = sy*S.s1;
|
||||
mom[y][9] = y*sy*S.s0;
|
||||
}
|
||||
else
|
||||
mom[y][0] = mom[y][1] = mom[y][2] = mom[y][3] = mom[y][4] =
|
||||
mom[y][5] = mom[y][6] = mom[y][7] = mom[y][8] = mom[y][9] = 0;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
#define REDUCE(d) \
|
||||
if( y < d ) \
|
||||
{ \
|
||||
mom[y][0] += mom[y+d][0]; \
|
||||
mom[y][1] += mom[y+d][1]; \
|
||||
mom[y][2] += mom[y+d][2]; \
|
||||
mom[y][3] += mom[y+d][3]; \
|
||||
mom[y][4] += mom[y+d][4]; \
|
||||
mom[y][5] += mom[y+d][5]; \
|
||||
mom[y][6] += mom[y+d][6]; \
|
||||
mom[y][7] += mom[y+d][7]; \
|
||||
mom[y][8] += mom[y+d][8]; \
|
||||
mom[y][9] += mom[y+d][9]; \
|
||||
} \
|
||||
barrier(CLK_LOCAL_MEM_FENCE)
|
||||
|
||||
REDUCE(16);
|
||||
REDUCE(8);
|
||||
REDUCE(4);
|
||||
REDUCE(2);
|
||||
|
||||
if( y == 0 )
|
||||
{
|
||||
__global int* momout = mom0 + (y0*xtiles + x0)*10;
|
||||
momout[0] = mom[0][0] + mom[1][0];
|
||||
momout[1] = mom[0][1] + mom[1][1];
|
||||
momout[2] = mom[0][2] + mom[1][2];
|
||||
momout[3] = mom[0][3] + mom[1][3];
|
||||
momout[4] = mom[0][4] + mom[1][4];
|
||||
momout[5] = mom[0][5] + mom[1][5];
|
||||
momout[6] = mom[0][6] + mom[1][6];
|
||||
momout[7] = mom[0][7] + mom[1][7];
|
||||
momout[8] = mom[0][8] + mom[1][8];
|
||||
momout[9] = mom[0][9] + mom[1][9];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
// Zero Lin, zero.lin@amd.com
|
||||
// Yao Wang, bitwangyaoyao@gmail.com
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
|
||||
#ifdef DOUBLE_SUPPORT
|
||||
#ifdef cl_amd_fp64
|
||||
#pragma OPENCL EXTENSION cl_amd_fp64:enable
|
||||
#elif defined (cl_khr_fp64)
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DEPTH_0
|
||||
#ifdef ERODE
|
||||
#define VAL 255
|
||||
#endif
|
||||
#ifdef DILATE
|
||||
#define VAL 0
|
||||
#endif
|
||||
#endif
|
||||
#ifdef DEPTH_5
|
||||
#ifdef ERODE
|
||||
#define VAL FLT_MAX
|
||||
#endif
|
||||
#ifdef DILATE
|
||||
#define VAL -FLT_MAX
|
||||
#endif
|
||||
#endif
|
||||
#ifdef DEPTH_6
|
||||
#ifdef ERODE
|
||||
#define VAL DBL_MAX
|
||||
#endif
|
||||
#ifdef DILATE
|
||||
#define VAL -DBL_MAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ERODE
|
||||
#define MORPH_OP(A,B) min((A),(B))
|
||||
#endif
|
||||
#ifdef DILATE
|
||||
#define MORPH_OP(A,B) max((A),(B))
|
||||
#endif
|
||||
//BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii
|
||||
#define ELEM(i,l_edge,r_edge,elem1,elem2) (i)<(l_edge) | (i) >= (r_edge) ? (elem1) : (elem2)
|
||||
|
||||
__kernel void morph(__global const uchar * restrict srcptr, int src_step, int src_offset,
|
||||
__global uchar * dstptr, int dst_step, int dst_offset,
|
||||
int src_offset_x, int src_offset_y,
|
||||
int cols, int rows,
|
||||
__constant uchar * mat_kernel,
|
||||
int src_whole_cols, int src_whole_rows)
|
||||
{
|
||||
int l_x = get_local_id(0);
|
||||
int l_y = get_local_id(1);
|
||||
int x = get_group_id(0)*LSIZE0;
|
||||
int y = get_group_id(1)*LSIZE1;
|
||||
int start_x = x+src_offset_x-RADIUSX;
|
||||
int end_x = x + src_offset_x+LSIZE0+RADIUSX;
|
||||
int width = end_x -(x+src_offset_x-RADIUSX)+1;
|
||||
int start_y = y+src_offset_y-RADIUSY;
|
||||
int point1 = mad24(l_y,LSIZE0,l_x);
|
||||
int point2 = point1 + LSIZE0*LSIZE1;
|
||||
int tl_x = point1 % width;
|
||||
int tl_y = point1 / width;
|
||||
int tl_x2 = point2 % width;
|
||||
int tl_y2 = point2 / width;
|
||||
int cur_x = start_x + tl_x;
|
||||
int cur_y = start_y + tl_y;
|
||||
int cur_x2 = start_x + tl_x2;
|
||||
int cur_y2 = start_y + tl_y2;
|
||||
int start_addr = mad24(cur_y,src_step, cur_x*(int)sizeof(GENTYPE));
|
||||
int start_addr2 = mad24(cur_y2,src_step, cur_x2*(int)sizeof(GENTYPE));
|
||||
GENTYPE temp0,temp1;
|
||||
__local GENTYPE LDS_DAT[2*LSIZE1*LSIZE0];
|
||||
|
||||
int end_addr = mad24(src_whole_rows - 1,src_step,src_whole_cols*(int)sizeof(GENTYPE));
|
||||
//read pixels from src
|
||||
start_addr = ((start_addr < end_addr) && (start_addr > 0)) ? start_addr : 0;
|
||||
start_addr2 = ((start_addr2 < end_addr) && (start_addr2 > 0)) ? start_addr2 : 0;
|
||||
__global const GENTYPE * src;
|
||||
src = (__global const GENTYPE *)(srcptr+start_addr);
|
||||
temp0 = src[0];
|
||||
src = (__global const GENTYPE *)(srcptr+start_addr2);
|
||||
temp1 = src[0];
|
||||
//judge if read out of boundary
|
||||
temp0= ELEM(cur_x,0,src_whole_cols,(GENTYPE)VAL,temp0);
|
||||
temp0= ELEM(cur_y,0,src_whole_rows,(GENTYPE)VAL,temp0);
|
||||
|
||||
temp1= ELEM(cur_x2,0,src_whole_cols,(GENTYPE)VAL,temp1);
|
||||
temp1= ELEM(cur_y2,0,src_whole_rows,(GENTYPE)VAL,temp1);
|
||||
|
||||
LDS_DAT[point1] = temp0;
|
||||
LDS_DAT[point2] = temp1;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
GENTYPE res = (GENTYPE)VAL;
|
||||
for(int i=0; i<2*RADIUSY+1; i++)
|
||||
for(int j=0; j<2*RADIUSX+1; j++)
|
||||
{
|
||||
res =
|
||||
#ifndef RECTKERNEL
|
||||
mat_kernel[i*(2*RADIUSX+1)+j] ?
|
||||
#endif
|
||||
MORPH_OP(res,LDS_DAT[mad24(l_y+i,width,l_x+j)])
|
||||
#ifndef RECTKERNEL
|
||||
:res
|
||||
#endif
|
||||
;
|
||||
}
|
||||
int gidx = get_global_id(0);
|
||||
int gidy = get_global_id(1);
|
||||
if(gidx<cols && gidy<rows)
|
||||
{
|
||||
int dst_index = mad24(gidy, dst_step, dst_offset + gidx * (int)sizeof(GENTYPE));
|
||||
__global GENTYPE * dst = (__global GENTYPE *)(dstptr + dst_index);
|
||||
dst[0] = res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Shengen Yan,yanshengen@gmail.com
|
||||
//
|
||||
// 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*/
|
||||
|
||||
__kernel void preCornerDetect(__global const uchar * Dxptr, int dx_step, int dx_offset,
|
||||
__global const uchar * Dyptr, int dy_step, int dy_offset,
|
||||
__global const uchar * D2xptr, int d2x_step, int d2x_offset,
|
||||
__global const uchar * D2yptr, int d2y_step, int d2y_offset,
|
||||
__global const uchar * Dxyptr, int dxy_step, int dxy_offset,
|
||||
__global uchar * dstptr, int dst_step, int dst_offset,
|
||||
int dst_rows, int dst_cols, float factor)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
int dx_index = mad24(dx_step, y, (int)sizeof(float) * x + dx_offset);
|
||||
int dy_index = mad24(dy_step, y, (int)sizeof(float) * x + dy_offset);
|
||||
int d2x_index = mad24(d2x_step, y, (int)sizeof(float) * x + d2x_offset);
|
||||
int d2y_index = mad24(d2y_step, y, (int)sizeof(float) * x + d2y_offset);
|
||||
int dxy_index = mad24(dxy_step, y, (int)sizeof(float) * x + dxy_offset);
|
||||
int dst_index = mad24(dst_step, y, (int)sizeof(float) * x + dst_offset);
|
||||
|
||||
float dx = *(__global const float *)(Dxptr + dx_index);
|
||||
float dy = *(__global const float *)(Dyptr + dy_index);
|
||||
float d2x = *(__global const float *)(D2xptr + d2x_index);
|
||||
float d2y = *(__global const float *)(D2yptr + d2y_index);
|
||||
float dxy = *(__global const float *)(Dxyptr + dxy_index);
|
||||
__global float * dst = (__global float *)(dstptr + dst_index);
|
||||
|
||||
dst[0] = factor * (dx*dx*d2y + dy*dy*d2x - 2*dx*dy*dxy);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Dachuan Zhao, dachuan@multicorewareinc.com
|
||||
//
|
||||
// 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*/
|
||||
|
||||
#ifdef DOUBLE_SUPPORT
|
||||
#ifdef cl_amd_fp64
|
||||
#pragma OPENCL EXTENSION cl_amd_fp64:enable
|
||||
#elif defined (cl_khr_fp64)
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define noconvert
|
||||
|
||||
inline int idx_row_low(int y, int last_row)
|
||||
{
|
||||
return abs(y) % (last_row + 1);
|
||||
}
|
||||
|
||||
inline int idx_row_high(int y, int last_row)
|
||||
{
|
||||
return abs(last_row - (int)abs(last_row - y)) % (last_row + 1);
|
||||
}
|
||||
|
||||
inline int idx_row(int y, int last_row)
|
||||
{
|
||||
return idx_row_low(idx_row_high(y, last_row), last_row);
|
||||
}
|
||||
|
||||
inline int idx_col_low(int x, int last_col)
|
||||
{
|
||||
return abs(x) % (last_col + 1);
|
||||
}
|
||||
|
||||
inline int idx_col_high(int x, int last_col)
|
||||
{
|
||||
return abs(last_col - (int)abs(last_col - x)) % (last_col + 1);
|
||||
}
|
||||
|
||||
inline int idx_col(int x, int last_col)
|
||||
{
|
||||
return idx_col_low(idx_col_high(x, last_col), last_col);
|
||||
}
|
||||
|
||||
__kernel void pyrDown(__global const uchar * src, int src_step, int src_offset, int src_rows, int src_cols,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols)
|
||||
{
|
||||
const int x = get_global_id(0);
|
||||
const int y = get_group_id(1);
|
||||
|
||||
__local FT smem[256 + 4];
|
||||
__global T * dstData = (__global T *)(dst + dst_offset);
|
||||
__global const uchar * srcData = (__global const uchar*)(src + src_offset);
|
||||
|
||||
FT sum;
|
||||
FT co1 = 0.375f;
|
||||
FT co2 = 0.25f;
|
||||
FT co3 = 0.0625f;
|
||||
|
||||
const int src_y = 2*y;
|
||||
const int last_row = src_rows - 1;
|
||||
const int last_col = src_cols - 1;
|
||||
|
||||
if (src_y >= 2 && src_y < src_rows - 2 && x >= 2 && x < src_cols - 2)
|
||||
{
|
||||
sum = co3 * convertToFT(((__global T*)(srcData + (src_y - 2) * src_step))[x]);
|
||||
sum = sum + co2 * convertToFT(((__global T*)(srcData + (src_y - 1) * src_step))[x]);
|
||||
sum = sum + co1 * convertToFT(((__global T*)(srcData + (src_y ) * src_step))[x]);
|
||||
sum = sum + co2 * convertToFT(((__global T*)(srcData + (src_y + 1) * src_step))[x]);
|
||||
sum = sum + co3 * convertToFT(((__global T*)(srcData + (src_y + 2) * src_step))[x]);
|
||||
|
||||
smem[2 + get_local_id(0)] = sum;
|
||||
|
||||
if (get_local_id(0) < 2)
|
||||
{
|
||||
const int left_x = x - 2;
|
||||
|
||||
sum = co3 * convertToFT(((__global T*)(srcData + (src_y - 2) * src_step))[left_x]);
|
||||
sum = sum + co2 * convertToFT(((__global T*)(srcData + (src_y - 1) * src_step))[left_x]);
|
||||
sum = sum + co1 * convertToFT(((__global T*)(srcData + (src_y ) * src_step))[left_x]);
|
||||
sum = sum + co2 * convertToFT(((__global T*)(srcData + (src_y + 1) * src_step))[left_x]);
|
||||
sum = sum + co3 * convertToFT(((__global T*)(srcData + (src_y + 2) * src_step))[left_x]);
|
||||
|
||||
smem[get_local_id(0)] = sum;
|
||||
}
|
||||
|
||||
if (get_local_id(0) > 253)
|
||||
{
|
||||
const int right_x = x + 2;
|
||||
|
||||
sum = co3 * convertToFT(((__global T*)(srcData + (src_y - 2) * src_step))[right_x]);
|
||||
sum = sum + co2 * convertToFT(((__global T*)(srcData + (src_y - 1) * src_step))[right_x]);
|
||||
sum = sum + co1 * convertToFT(((__global T*)(srcData + (src_y ) * src_step))[right_x]);
|
||||
sum = sum + co2 * convertToFT(((__global T*)(srcData + (src_y + 1) * src_step))[right_x]);
|
||||
sum = sum + co3 * convertToFT(((__global T*)(srcData + (src_y + 2) * src_step))[right_x]);
|
||||
|
||||
smem[4 + get_local_id(0)] = sum;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int col = idx_col(x, last_col);
|
||||
|
||||
sum = co3 * convertToFT(((__global T*)(srcData + idx_row(src_y - 2, last_row) * src_step))[col]);
|
||||
sum = sum + co2 * convertToFT(((__global T*)(srcData + idx_row(src_y - 1, last_row) * src_step))[col]);
|
||||
sum = sum + co1 * convertToFT(((__global T*)(srcData + idx_row(src_y , last_row) * src_step))[col]);
|
||||
sum = sum + co2 * convertToFT(((__global T*)(srcData + idx_row(src_y + 1, last_row) * src_step))[col]);
|
||||
sum = sum + co3 * convertToFT(((__global T*)(srcData + idx_row(src_y + 2, last_row) * src_step))[col]);
|
||||
|
||||
smem[2 + get_local_id(0)] = sum;
|
||||
|
||||
if (get_local_id(0) < 2)
|
||||
{
|
||||
const int left_x = x - 2;
|
||||
|
||||
col = idx_col(left_x, last_col);
|
||||
|
||||
sum = co3 * convertToFT(((__global T*)(srcData + idx_row(src_y - 2, last_row) * src_step))[col]);
|
||||
sum = sum + co2 * convertToFT(((__global T*)(srcData + idx_row(src_y - 1, last_row) * src_step))[col]);
|
||||
sum = sum + co1 * convertToFT(((__global T*)(srcData + idx_row(src_y , last_row) * src_step))[col]);
|
||||
sum = sum + co2 * convertToFT(((__global T*)(srcData + idx_row(src_y + 1, last_row) * src_step))[col]);
|
||||
sum = sum + co3 * convertToFT(((__global T*)(srcData + idx_row(src_y + 2, last_row) * src_step))[col]);
|
||||
|
||||
smem[get_local_id(0)] = sum;
|
||||
}
|
||||
|
||||
if (get_local_id(0) > 253)
|
||||
{
|
||||
const int right_x = x + 2;
|
||||
|
||||
col = idx_col(right_x, last_col);
|
||||
|
||||
sum = co3 * convertToFT(((__global T*)(srcData + idx_row(src_y - 2, last_row) * src_step))[col]);
|
||||
sum = sum + co2 * convertToFT(((__global T*)(srcData + idx_row(src_y - 1, last_row) * src_step))[col]);
|
||||
sum = sum + co1 * convertToFT(((__global T*)(srcData + idx_row(src_y , last_row) * src_step))[col]);
|
||||
sum = sum + co2 * convertToFT(((__global T*)(srcData + idx_row(src_y + 1, last_row) * src_step))[col]);
|
||||
sum = sum + co3 * convertToFT(((__global T*)(srcData + idx_row(src_y + 2, last_row) * src_step))[col]);
|
||||
|
||||
smem[4 + get_local_id(0)] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
if (get_local_id(0) < 128)
|
||||
{
|
||||
const int tid2 = get_local_id(0) * 2;
|
||||
|
||||
sum = co3 * smem[2 + tid2 - 2];
|
||||
sum = sum + co2 * smem[2 + tid2 - 1];
|
||||
sum = sum + co1 * smem[2 + tid2 ];
|
||||
sum = sum + co2 * smem[2 + tid2 + 1];
|
||||
sum = sum + co3 * smem[2 + tid2 + 2];
|
||||
|
||||
const int dst_x = (get_group_id(0) * get_local_size(0) + tid2) / 2;
|
||||
|
||||
if (dst_x < dst_cols)
|
||||
dstData[y * dst_step / ((int)sizeof(T)) + dst_x] = convertToT(sum);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Zhang Chunpeng chunpeng@multicorewareinc.com
|
||||
// Dachuan Zhao, dachuan@multicorewareinc.com
|
||||
// Yao Wang, yao@multicorewareinc.com
|
||||
// Peng Xiao, pengxiao@outlook.com
|
||||
//
|
||||
// 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*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//////////////////////// Generic PyrUp //////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef DOUBLE_SUPPORT
|
||||
#ifdef cl_amd_fp64
|
||||
#pragma OPENCL EXTENSION cl_amd_fp64:enable
|
||||
#elif defined (cl_khr_fp64)
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define noconvert
|
||||
|
||||
|
||||
__kernel void pyrUp(__global const uchar * src, int src_step, int src_offset, int src_rows, int src_cols,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols)
|
||||
{
|
||||
const int x = get_global_id(0);
|
||||
const int y = get_global_id(1);
|
||||
|
||||
const int lsizex = get_local_size(0);
|
||||
const int lsizey = get_local_size(1);
|
||||
|
||||
const int tidx = get_local_id(0);
|
||||
const int tidy = get_local_id(1);
|
||||
|
||||
__local FT s_srcPatch[10][10];
|
||||
__local FT s_dstPatch[20][16];
|
||||
|
||||
__global T * dstData = (__global T *)(dst + dst_offset);
|
||||
__global const T * srcData = (__global const T *)(src + src_offset);
|
||||
|
||||
if( tidx < 10 && tidy < 10 )
|
||||
{
|
||||
int srcx = mad24((int)get_group_id(0), lsizex>>1, tidx) - 1;
|
||||
int srcy = mad24((int)get_group_id(1), lsizey>>1, tidy) - 1;
|
||||
|
||||
srcx = abs(srcx);
|
||||
srcx = min(src_cols - 1, srcx);
|
||||
|
||||
srcy = abs(srcy);
|
||||
srcy = min(src_rows - 1, srcy);
|
||||
|
||||
s_srcPatch[tidy][tidx] = convertToFT(srcData[srcx + srcy * src_step / (int) sizeof(T)]);
|
||||
}
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
FT sum = 0.f;
|
||||
const FT evenFlag = (FT)((tidx & 1) == 0);
|
||||
const FT oddFlag = (FT)((tidx & 1) != 0);
|
||||
const bool eveny = ((tidy & 1) == 0);
|
||||
|
||||
const FT co1 = 0.375f;
|
||||
const FT co2 = 0.25f;
|
||||
const FT co3 = 0.0625f;
|
||||
|
||||
if(eveny)
|
||||
{
|
||||
sum = ( evenFlag* co3 ) * s_srcPatch[1 + (tidy >> 1)][1 + ((tidx - 2) >> 1)];
|
||||
sum = sum + ( oddFlag * co2 ) * s_srcPatch[1 + (tidy >> 1)][1 + ((tidx - 1) >> 1)];
|
||||
sum = sum + ( evenFlag* co1 ) * s_srcPatch[1 + (tidy >> 1)][1 + ((tidx ) >> 1)];
|
||||
sum = sum + ( oddFlag * co2 ) * s_srcPatch[1 + (tidy >> 1)][1 + ((tidx + 1) >> 1)];
|
||||
sum = sum + ( evenFlag* co3 ) * s_srcPatch[1 + (tidy >> 1)][1 + ((tidx + 2) >> 1)];
|
||||
}
|
||||
|
||||
s_dstPatch[2 + tidy][tidx] = sum;
|
||||
|
||||
if (tidy < 2)
|
||||
{
|
||||
sum = 0;
|
||||
|
||||
if (eveny)
|
||||
{
|
||||
sum = (evenFlag * co3 ) * s_srcPatch[lsizey-16][1 + ((tidx - 2) >> 1)];
|
||||
sum = sum + ( oddFlag * co2 ) * s_srcPatch[lsizey-16][1 + ((tidx - 1) >> 1)];
|
||||
sum = sum + (evenFlag * co1 ) * s_srcPatch[lsizey-16][1 + ((tidx ) >> 1)];
|
||||
sum = sum + ( oddFlag * co2 ) * s_srcPatch[lsizey-16][1 + ((tidx + 1) >> 1)];
|
||||
sum = sum + (evenFlag * co3 ) * s_srcPatch[lsizey-16][1 + ((tidx + 2) >> 1)];
|
||||
}
|
||||
|
||||
s_dstPatch[tidy][tidx] = sum;
|
||||
}
|
||||
|
||||
if (tidy > 13)
|
||||
{
|
||||
sum = 0;
|
||||
|
||||
if (eveny)
|
||||
{
|
||||
sum = (evenFlag * co3) * s_srcPatch[lsizey-7][1 + ((tidx - 2) >> 1)];
|
||||
sum = sum + ( oddFlag * co2) * s_srcPatch[lsizey-7][1 + ((tidx - 1) >> 1)];
|
||||
sum = sum + (evenFlag * co1) * s_srcPatch[lsizey-7][1 + ((tidx ) >> 1)];
|
||||
sum = sum + ( oddFlag * co2) * s_srcPatch[lsizey-7][1 + ((tidx + 1) >> 1)];
|
||||
sum = sum + (evenFlag * co3) * s_srcPatch[lsizey-7][1 + ((tidx + 2) >> 1)];
|
||||
}
|
||||
s_dstPatch[4 + tidy][tidx] = sum;
|
||||
}
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
sum = co3 * s_dstPatch[2 + tidy - 2][tidx];
|
||||
sum = sum + co2 * s_dstPatch[2 + tidy - 1][tidx];
|
||||
sum = sum + co1 * s_dstPatch[2 + tidy ][tidx];
|
||||
sum = sum + co2 * s_dstPatch[2 + tidy + 1][tidx];
|
||||
sum = sum + co3 * s_dstPatch[2 + tidy + 2][tidx];
|
||||
|
||||
if ((x < dst_cols) && (y < dst_rows))
|
||||
dstData[x + y * dst_step / (int)sizeof(T)] = convertToT(4.0f * sum);
|
||||
}
|
||||
@@ -50,12 +50,21 @@
|
||||
#define INTER_RESIZE_COEF_BITS 11
|
||||
#define INTER_RESIZE_COEF_SCALE (1 << INTER_RESIZE_COEF_BITS)
|
||||
#define CAST_BITS (INTER_RESIZE_COEF_BITS << 1)
|
||||
#define CAST_SCALE (1.0f/(1<<CAST_BITS))
|
||||
#define INC(x,l) min(x+1,l-1)
|
||||
|
||||
#define PIXSIZE ((int)sizeof(PIXTYPE))
|
||||
|
||||
#define noconvert(x) (x)
|
||||
|
||||
#if cn != 3
|
||||
#define loadpix(addr) *(__global const PIXTYPE*)(addr)
|
||||
#define storepix(val, addr) *(__global PIXTYPE*)(addr) = val
|
||||
#define PIXSIZE ((int)sizeof(PIXTYPE))
|
||||
#else
|
||||
#define loadpix(addr) vload3(0, (__global const PIXTYPE1*)(addr))
|
||||
#define storepix(val, addr) vstore3(val, 0, (__global PIXTYPE1*)(addr))
|
||||
#define PIXSIZE ((int)sizeof(PIXTYPE1)*3)
|
||||
#endif
|
||||
|
||||
#if defined INTER_LINEAR
|
||||
|
||||
__kernel void resizeLN(__global const uchar* srcptr, int srcstep, int srcoffset,
|
||||
@@ -79,7 +88,6 @@ __kernel void resizeLN(__global const uchar* srcptr, int srcstep, int srcoffset,
|
||||
|
||||
int y_ = INC(y,srcrows);
|
||||
int x_ = INC(x,srccols);
|
||||
__global const PIXTYPE* src = (__global const PIXTYPE*)(srcptr + mad24(y, srcstep, srcoffset + x*PIXSIZE));
|
||||
|
||||
#if depth <= 4
|
||||
|
||||
@@ -91,10 +99,10 @@ __kernel void resizeLN(__global const uchar* srcptr, int srcstep, int srcoffset,
|
||||
int U1 = rint(INTER_RESIZE_COEF_SCALE - u);
|
||||
int V1 = rint(INTER_RESIZE_COEF_SCALE - v);
|
||||
|
||||
WORKTYPE data0 = convertToWT(*(__global const PIXTYPE*)(srcptr + mad24(y, srcstep, srcoffset + x*PIXSIZE)));
|
||||
WORKTYPE data1 = convertToWT(*(__global const PIXTYPE*)(srcptr + mad24(y, srcstep, srcoffset + x_*PIXSIZE)));
|
||||
WORKTYPE data2 = convertToWT(*(__global const PIXTYPE*)(srcptr + mad24(y_, srcstep, srcoffset + x*PIXSIZE)));
|
||||
WORKTYPE data3 = convertToWT(*(__global const PIXTYPE*)(srcptr + mad24(y_, srcstep, srcoffset + x_*PIXSIZE)));
|
||||
WORKTYPE data0 = convertToWT(loadpix(srcptr + mad24(y, srcstep, srcoffset + x*PIXSIZE)));
|
||||
WORKTYPE data1 = convertToWT(loadpix(srcptr + mad24(y, srcstep, srcoffset + x_*PIXSIZE)));
|
||||
WORKTYPE data2 = convertToWT(loadpix(srcptr + mad24(y_, srcstep, srcoffset + x*PIXSIZE)));
|
||||
WORKTYPE data3 = convertToWT(loadpix(srcptr + mad24(y_, srcstep, srcoffset + x_*PIXSIZE)));
|
||||
|
||||
WORKTYPE val = mul24((WORKTYPE)mul24(U1, V1), data0) + mul24((WORKTYPE)mul24(U, V1), data1) +
|
||||
mul24((WORKTYPE)mul24(U1, V), data2) + mul24((WORKTYPE)mul24(U, V), data3);
|
||||
@@ -104,10 +112,10 @@ __kernel void resizeLN(__global const uchar* srcptr, int srcstep, int srcoffset,
|
||||
#else
|
||||
float u1 = 1.f - u;
|
||||
float v1 = 1.f - v;
|
||||
WORKTYPE data0 = convertToWT(*(__global const PIXTYPE*)(srcptr + mad24(y, srcstep, srcoffset + x*PIXSIZE)));
|
||||
WORKTYPE data1 = convertToWT(*(__global const PIXTYPE*)(srcptr + mad24(y, srcstep, srcoffset + x_*PIXSIZE)));
|
||||
WORKTYPE data2 = convertToWT(*(__global const PIXTYPE*)(srcptr + mad24(y_, srcstep, srcoffset + x*PIXSIZE)));
|
||||
WORKTYPE data3 = convertToWT(*(__global const PIXTYPE*)(srcptr + mad24(y_, srcstep, srcoffset + x_*PIXSIZE)));
|
||||
WORKTYPE data0 = convertToWT(loadpix(srcptr + mad24(y, srcstep, srcoffset + x*PIXSIZE)));
|
||||
WORKTYPE data1 = convertToWT(loadpix(srcptr + mad24(y, srcstep, srcoffset + x_*PIXSIZE)));
|
||||
WORKTYPE data2 = convertToWT(loadpix(srcptr + mad24(y_, srcstep, srcoffset + x*PIXSIZE)));
|
||||
WORKTYPE data3 = convertToWT(loadpix(srcptr + mad24(y_, srcstep, srcoffset + x_*PIXSIZE)));
|
||||
|
||||
PIXTYPE uval = u1 * v1 * data0 + u * v1 * data1 + u1 * v *data2 + u * v *data3;
|
||||
|
||||
@@ -115,8 +123,7 @@ __kernel void resizeLN(__global const uchar* srcptr, int srcstep, int srcoffset,
|
||||
|
||||
if(dx < dstcols && dy < dstrows)
|
||||
{
|
||||
__global PIXTYPE* dst = (__global PIXTYPE*)(dstptr + mad24(dy, dststep, dstoffset + dx*PIXSIZE));
|
||||
dst[0] = uval;
|
||||
storepix(uval, dstptr + mad24(dy, dststep, dstoffset + dx*PIXSIZE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,17 +145,13 @@ __kernel void resizeNN(__global const uchar* srcptr, int srcstep, int srcoffset,
|
||||
int sx = min(convert_int_rtz(s1), srccols-1);
|
||||
int sy = min(convert_int_rtz(s2), srcrows-1);
|
||||
|
||||
__global PIXTYPE* dst = (__global PIXTYPE*)(dstptr + mad24(dy, dststep, dstoffset + dx*PIXSIZE));
|
||||
__global const PIXTYPE* src = (__global const PIXTYPE*)(srcptr + mad24(sy, srcstep, srcoffset + sx*PIXSIZE));
|
||||
|
||||
dst[0] = src[0];
|
||||
storepix(loadpix(srcptr + mad24(sy, srcstep, srcoffset + sx*PIXSIZE)),
|
||||
dstptr + mad24(dy, dststep, dstoffset + dx*PIXSIZE));
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined INTER_AREA
|
||||
|
||||
#define TSIZE ((int)(sizeof(T)))
|
||||
|
||||
#ifdef INTER_AREA_FAST
|
||||
|
||||
__kernel void resizeAREA_FAST(__global const uchar * src, int src_step, int src_offset, int src_rows, int src_cols,
|
||||
@@ -176,10 +179,10 @@ __kernel void resizeAREA_FAST(__global const uchar * src, int src_step, int src_
|
||||
int src_index = mad24(symap_tab[y + sy], src_step, src_offset);
|
||||
#pragma unroll
|
||||
for (int x = 0; x < XSCALE; ++x)
|
||||
sum += convertToWTV(((__global const T*)(src + src_index))[sxmap_tab[sx + x]]);
|
||||
sum += convertToWTV(loadpix(src + src_index + sxmap_tab[sx + x]*PIXSIZE));
|
||||
}
|
||||
|
||||
((__global T*)(dst + dst_index))[dx] = convertToT(convertToWT2V(sum) * (WT2V)(SCALE));
|
||||
storepix(convertToPIXTYPE(convertToWT2V(sum) * (WT2V)(SCALE)), dst + dst_index + dx*PIXSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,12 +224,12 @@ __kernel void resizeAREA(__global const uchar * src, int src_step, int src_offse
|
||||
for (int sx = sx0, xk = xk0; sx <= sx1; ++sx, ++xk)
|
||||
{
|
||||
WTV alpha = (WTV)(xalpha_tab[xk]);
|
||||
buf += convertToWTV(((__global const T*)(src + src_index))[sx]) * alpha;
|
||||
buf += convertToWTV(loadpix(src + src_index + sx*PIXSIZE)) * alpha;
|
||||
}
|
||||
sum += buf * beta;
|
||||
}
|
||||
|
||||
((__global T*)(dst + dst_index))[dx] = convertToT(sum);
|
||||
storepix(convertToPIXTYPE(sum), dst + dst_index + dx*PIXSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,11 +64,31 @@
|
||||
|
||||
#define noconvert
|
||||
|
||||
#ifndef ST
|
||||
#define ST T
|
||||
#endif
|
||||
|
||||
#if cn != 3
|
||||
#define loadpix(addr) *(__global const T*)(addr)
|
||||
#define storepix(val, addr) *(__global T*)(addr) = val
|
||||
#define scalar scalar_
|
||||
#define pixsize (int)sizeof(T)
|
||||
#else
|
||||
#define loadpix(addr) vload3(0, (__global const T1*)(addr))
|
||||
#define storepix(val, addr) vstore3(val, 0, (__global T1*)(addr))
|
||||
#ifdef INTER_NEAREST
|
||||
#define scalar (T)(scalar_.x, scalar_.y, scalar_.z)
|
||||
#else
|
||||
#define scalar (WT)(scalar_.x, scalar_.y, scalar_.z)
|
||||
#endif
|
||||
#define pixsize ((int)sizeof(T1)*3)
|
||||
#endif
|
||||
|
||||
#ifdef INTER_NEAREST
|
||||
|
||||
__kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_offset, int src_rows, int src_cols,
|
||||
__global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
__constant CT * M, T scalar)
|
||||
__constant CT * M, ST scalar_)
|
||||
{
|
||||
int dx = get_global_id(0);
|
||||
int dy = get_global_id(1);
|
||||
@@ -85,17 +105,15 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of
|
||||
short sx = convert_short_sat(X0 >> AB_BITS);
|
||||
short sy = convert_short_sat(Y0 >> AB_BITS);
|
||||
|
||||
int dst_index = mad24(dy, dst_step, dst_offset + dx * (int)sizeof(T));
|
||||
__global T * dst = (__global T *)(dstptr + dst_index);
|
||||
int dst_index = mad24(dy, dst_step, dst_offset + dx * pixsize);
|
||||
|
||||
if (sx >= 0 && sx < src_cols && sy >= 0 && sy < src_rows)
|
||||
{
|
||||
int src_index = mad24(sy, src_step, src_offset + sx * (int)sizeof(T));
|
||||
__global const T * src = (__global const T *)(srcptr + src_index);
|
||||
dst[0] = src[0];
|
||||
int src_index = mad24(sy, src_step, src_offset + sx * pixsize);
|
||||
storepix(loadpix(srcptr + src_index), dstptr + dst_index);
|
||||
}
|
||||
else
|
||||
dst[0] = scalar;
|
||||
storepix(scalar, dstptr + dst_index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +121,7 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of
|
||||
|
||||
__kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_offset, int src_rows, int src_cols,
|
||||
__global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
__constant CT * M, WT scalar)
|
||||
__constant CT * M, ST scalar_)
|
||||
{
|
||||
int dx = get_global_id(0);
|
||||
int dy = get_global_id(1);
|
||||
@@ -126,19 +144,18 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of
|
||||
short ay = convert_short(Y0 & (INTER_TAB_SIZE-1));
|
||||
|
||||
WT v0 = (sx >= 0 && sx < src_cols && sy >= 0 && sy < src_rows) ?
|
||||
convertToWT(*(__global const T *)(srcptr + mad24(sy, src_step, src_offset + sx * (int)sizeof(T)))) : scalar;
|
||||
convertToWT(loadpix(srcptr + mad24(sy, src_step, src_offset + sx * pixsize))) : scalar;
|
||||
WT v1 = (sx+1 >= 0 && sx+1 < src_cols && sy >= 0 && sy < src_rows) ?
|
||||
convertToWT(*(__global const T *)(srcptr + mad24(sy, src_step, src_offset + (sx+1) * (int)sizeof(T)))) : scalar;
|
||||
convertToWT(loadpix(srcptr + mad24(sy, src_step, src_offset + (sx+1) * pixsize))) : scalar;
|
||||
WT v2 = (sx >= 0 && sx < src_cols && sy+1 >= 0 && sy+1 < src_rows) ?
|
||||
convertToWT(*(__global const T *)(srcptr + mad24(sy+1, src_step, src_offset + sx * (int)sizeof(T)))) : scalar;
|
||||
convertToWT(loadpix(srcptr + mad24(sy+1, src_step, src_offset + sx * pixsize))) : scalar;
|
||||
WT v3 = (sx+1 >= 0 && sx+1 < src_cols && sy+1 >= 0 && sy+1 < src_rows) ?
|
||||
convertToWT(*(__global const T *)(srcptr + mad24(sy+1, src_step, src_offset + (sx+1) * (int)sizeof(T)))) : scalar;
|
||||
convertToWT(loadpix(srcptr + mad24(sy+1, src_step, src_offset + (sx+1) * pixsize))) : scalar;
|
||||
|
||||
float taby = 1.f/INTER_TAB_SIZE*ay;
|
||||
float tabx = 1.f/INTER_TAB_SIZE*ax;
|
||||
|
||||
int dst_index = mad24(dy, dst_step, dst_offset + dx * (int)sizeof(T));
|
||||
__global T * dst = (__global T *)(dstptr + dst_index);
|
||||
int dst_index = mad24(dy, dst_step, dst_offset + dx * pixsize);
|
||||
|
||||
#if depth <= 4
|
||||
int itab0 = convert_short_sat_rte( (1.0f-taby)*(1.0f-tabx) * INTER_REMAP_COEF_SCALE );
|
||||
@@ -147,11 +164,11 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of
|
||||
int itab3 = convert_short_sat_rte( taby*tabx * INTER_REMAP_COEF_SCALE );
|
||||
|
||||
WT val = v0 * itab0 + v1 * itab1 + v2 * itab2 + v3 * itab3;
|
||||
dst[0] = convertToT((val + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS);
|
||||
storepix(convertToT((val + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS), dstptr + dst_index);
|
||||
#else
|
||||
float tabx2 = 1.0f - tabx, taby2 = 1.0f - taby;
|
||||
WT val = v0 * tabx2 * taby2 + v1 * tabx * taby2 + v2 * tabx2 * taby + v3 * tabx * taby;
|
||||
dst[0] = convertToT(val);
|
||||
storepix(convertToT(val), dstptr + dst_index);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -170,7 +187,7 @@ inline void interpolateCubic( float x, float* coeffs )
|
||||
|
||||
__kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_offset, int src_rows, int src_cols,
|
||||
__global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
__constant CT * M, WT scalar)
|
||||
__constant CT * M, ST scalar_)
|
||||
{
|
||||
int dx = get_global_id(0);
|
||||
int dy = get_global_id(1);
|
||||
@@ -198,7 +215,7 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of
|
||||
#pragma unroll
|
||||
for (int x = 0; x < 4; x++)
|
||||
v[mad24(y, 4, x)] = (sx+x >= 0 && sx+x < src_cols && sy+y >= 0 && sy+y < src_rows) ?
|
||||
convertToWT(*(__global const T *)(srcptr + mad24(sy+y, src_step, src_offset + (sx+x) * (int)sizeof(T)))) : scalar;
|
||||
convertToWT(loadpix(srcptr + mad24(sy+y, src_step, src_offset + (sx+x) * pixsize))) : scalar;
|
||||
|
||||
float tab1y[4], tab1x[4];
|
||||
|
||||
@@ -207,8 +224,7 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of
|
||||
interpolateCubic(ayy, tab1y);
|
||||
interpolateCubic(axx, tab1x);
|
||||
|
||||
int dst_index = mad24(dy, dst_step, dst_offset + dx * (int)sizeof(T));
|
||||
__global T * dst = (__global T *)(dstptr + dst_index);
|
||||
int dst_index = mad24(dy, dst_step, dst_offset + dx * pixsize);
|
||||
|
||||
WT sum = (WT)(0);
|
||||
#if depth <= 4
|
||||
@@ -221,12 +237,12 @@ __kernel void warpAffine(__global const uchar * srcptr, int src_step, int src_of
|
||||
#pragma unroll
|
||||
for (int i = 0; i < 16; i++)
|
||||
sum += v[i] * itab[i];
|
||||
dst[0] = convertToT( (sum + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS );
|
||||
storepix(convertToT( (sum + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ), dstptr + dst_index);
|
||||
#else
|
||||
#pragma unroll
|
||||
for (int i = 0; i < 16; i++)
|
||||
sum += v[i] * tab1y[(i>>2)] * tab1x[(i&3)];
|
||||
dst[0] = convertToT( sum );
|
||||
storepix(convertToT( sum ), dstptr + dst_index);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,11 +64,31 @@
|
||||
|
||||
#define noconvert
|
||||
|
||||
#ifndef ST
|
||||
#define ST T
|
||||
#endif
|
||||
|
||||
#if cn != 3
|
||||
#define loadpix(addr) *(__global const T*)(addr)
|
||||
#define storepix(val, addr) *(__global T*)(addr) = val
|
||||
#define scalar scalar_
|
||||
#define pixsize (int)sizeof(T)
|
||||
#else
|
||||
#define loadpix(addr) vload3(0, (__global const T1*)(addr))
|
||||
#define storepix(val, addr) vstore3(val, 0, (__global T1*)(addr))
|
||||
#ifdef INTER_NEAREST
|
||||
#define scalar (T)(scalar_.x, scalar_.y, scalar_.z)
|
||||
#else
|
||||
#define scalar (WT)(scalar_.x, scalar_.y, scalar_.z)
|
||||
#endif
|
||||
#define pixsize ((int)sizeof(T1)*3)
|
||||
#endif
|
||||
|
||||
#ifdef INTER_NEAREST
|
||||
|
||||
__kernel void warpPerspective(__global const uchar * srcptr, int src_step, int src_offset, int src_rows, int src_cols,
|
||||
__global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
__constant CT * M, T scalar)
|
||||
__constant CT * M, ST scalar_)
|
||||
{
|
||||
int dx = get_global_id(0);
|
||||
int dy = get_global_id(1);
|
||||
@@ -82,17 +102,15 @@ __kernel void warpPerspective(__global const uchar * srcptr, int src_step, int s
|
||||
short sx = convert_short_sat_rte(X0*W);
|
||||
short sy = convert_short_sat_rte(Y0*W);
|
||||
|
||||
int dst_index = mad24(dy, dst_step, dx * (int)sizeof(T) + dst_offset);
|
||||
__global T * dst = (__global T *)(dstptr + dst_index);
|
||||
int dst_index = mad24(dy, dst_step, dx * pixsize + dst_offset);
|
||||
|
||||
if (sx >= 0 && sx < src_cols && sy >= 0 && sy < src_rows)
|
||||
{
|
||||
int src_index = mad24(sy, src_step, sx * (int)sizeof(T) + src_offset);
|
||||
__global const T * src = (__global const T *)(srcptr + src_index);
|
||||
dst[0] = src[0];
|
||||
int src_index = mad24(sy, src_step, sx * pixsize + src_offset);
|
||||
storepix(loadpix(srcptr + src_index), dstptr + dst_index);
|
||||
}
|
||||
else
|
||||
dst[0] = scalar;
|
||||
storepix(scalar, dstptr + dst_index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +118,7 @@ __kernel void warpPerspective(__global const uchar * srcptr, int src_step, int s
|
||||
|
||||
__kernel void warpPerspective(__global const uchar * srcptr, int src_step, int src_offset, int src_rows, int src_cols,
|
||||
__global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
__constant CT * M, WT scalar)
|
||||
__constant CT * M, ST scalar_)
|
||||
{
|
||||
int dx = get_global_id(0);
|
||||
int dy = get_global_id(1);
|
||||
@@ -119,19 +137,18 @@ __kernel void warpPerspective(__global const uchar * srcptr, int src_step, int s
|
||||
short ax = (short)(X & (INTER_TAB_SIZE - 1));
|
||||
|
||||
WT v0 = (sx >= 0 && sx < src_cols && sy >= 0 && sy < src_rows) ?
|
||||
convertToWT(*(__global const T *)(srcptr + mad24(sy, src_step, src_offset + sx * (int)sizeof(T)))) : scalar;
|
||||
convertToWT(loadpix(srcptr + mad24(sy, src_step, src_offset + sx * pixsize))) : scalar;
|
||||
WT v1 = (sx+1 >= 0 && sx+1 < src_cols && sy >= 0 && sy < src_rows) ?
|
||||
convertToWT(*(__global const T *)(srcptr + mad24(sy, src_step, src_offset + (sx+1) * (int)sizeof(T)))) : scalar;
|
||||
convertToWT(loadpix(srcptr + mad24(sy, src_step, src_offset + (sx+1) * pixsize))) : scalar;
|
||||
WT v2 = (sx >= 0 && sx < src_cols && sy+1 >= 0 && sy+1 < src_rows) ?
|
||||
convertToWT(*(__global const T *)(srcptr + mad24(sy+1, src_step, src_offset + sx * (int)sizeof(T)))) : scalar;
|
||||
convertToWT(loadpix(srcptr + mad24(sy+1, src_step, src_offset + sx * pixsize))) : scalar;
|
||||
WT v3 = (sx+1 >= 0 && sx+1 < src_cols && sy+1 >= 0 && sy+1 < src_rows) ?
|
||||
convertToWT(*(__global const T *)(srcptr + mad24(sy+1, src_step, src_offset + (sx+1) * (int)sizeof(T)))) : scalar;
|
||||
convertToWT(loadpix(srcptr + mad24(sy+1, src_step, src_offset + (sx+1) * pixsize))) : scalar;
|
||||
|
||||
float taby = 1.f/INTER_TAB_SIZE*ay;
|
||||
float tabx = 1.f/INTER_TAB_SIZE*ax;
|
||||
|
||||
int dst_index = mad24(dy, dst_step, dst_offset + dx * (int)sizeof(T));
|
||||
__global T * dst = (__global T *)(dstptr + dst_index);
|
||||
int dst_index = mad24(dy, dst_step, dst_offset + dx * pixsize);
|
||||
|
||||
#if depth <= 4
|
||||
int itab0 = convert_short_sat_rte( (1.0f-taby)*(1.0f-tabx) * INTER_REMAP_COEF_SCALE );
|
||||
@@ -140,11 +157,11 @@ __kernel void warpPerspective(__global const uchar * srcptr, int src_step, int s
|
||||
int itab3 = convert_short_sat_rte( taby*tabx * INTER_REMAP_COEF_SCALE );
|
||||
|
||||
WT val = v0 * itab0 + v1 * itab1 + v2 * itab2 + v3 * itab3;
|
||||
dst[0] = convertToT((val + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS);
|
||||
storepix(convertToT((val + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS), dstptr + dst_index);
|
||||
#else
|
||||
float tabx2 = 1.0f - tabx, taby2 = 1.0f - taby;
|
||||
WT val = v0 * tabx2 * taby2 + v1 * tabx * taby2 + v2 * tabx2 * taby + v3 * tabx * taby;
|
||||
dst[0] = convertToT(val);
|
||||
storepix(convertToT(val), dstptr + dst_index);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -163,7 +180,7 @@ inline void interpolateCubic( float x, float* coeffs )
|
||||
|
||||
__kernel void warpPerspective(__global const uchar * srcptr, int src_step, int src_offset, int src_rows, int src_cols,
|
||||
__global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
__constant CT * M, WT scalar)
|
||||
__constant CT * M, ST scalar_)
|
||||
{
|
||||
int dx = get_global_id(0);
|
||||
int dy = get_global_id(1);
|
||||
@@ -187,7 +204,7 @@ __kernel void warpPerspective(__global const uchar * srcptr, int src_step, int s
|
||||
#pragma unroll
|
||||
for (int x = 0; x < 4; x++)
|
||||
v[mad24(y, 4, x)] = (sx+x >= 0 && sx+x < src_cols && sy+y >= 0 && sy+y < src_rows) ?
|
||||
convertToWT(*(__global const T *)(srcptr + mad24(sy+y, src_step, src_offset + (sx+x) * (int)sizeof(T)))) : scalar;
|
||||
convertToWT(loadpix(srcptr + mad24(sy+y, src_step, src_offset + (sx+x) * pixsize))) : scalar;
|
||||
|
||||
float tab1y[4], tab1x[4];
|
||||
|
||||
@@ -196,8 +213,7 @@ __kernel void warpPerspective(__global const uchar * srcptr, int src_step, int s
|
||||
interpolateCubic(ayy, tab1y);
|
||||
interpolateCubic(axx, tab1x);
|
||||
|
||||
int dst_index = mad24(dy, dst_step, dst_offset + dx * (int)sizeof(T));
|
||||
__global T * dst = (__global T *)(dstptr + dst_index);
|
||||
int dst_index = mad24(dy, dst_step, dst_offset + dx * pixsize);
|
||||
|
||||
WT sum = (WT)(0);
|
||||
#if depth <= 4
|
||||
@@ -210,12 +226,12 @@ __kernel void warpPerspective(__global const uchar * srcptr, int src_step, int s
|
||||
#pragma unroll
|
||||
for (int i = 0; i < 16; i++)
|
||||
sum += v[i] * itab[i];
|
||||
dst[0] = convertToT( (sum + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS );
|
||||
storepix(convertToT( (sum + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ), dstptr + dst_index);
|
||||
#else
|
||||
#pragma unroll
|
||||
for (int i = 0; i < 16; i++)
|
||||
sum += v[i] * tab1y[(i>>2)] * tab1x[(i&3)];
|
||||
dst[0] = convertToT( sum );
|
||||
storepix(convertToT( sum ), dstptr + dst_index);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -576,20 +576,23 @@ void cv::createHanningWindow(OutputArray _dst, cv::Size winSize, int type)
|
||||
_dst.create(winSize, type);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
int rows = dst.rows;
|
||||
int cols = dst.cols;
|
||||
int rows = dst.rows, cols = dst.cols;
|
||||
|
||||
AutoBuffer<double> _wc(cols);
|
||||
double * const wc = (double *)_wc;
|
||||
|
||||
double coeff0 = 2.0 * CV_PI / (double)(cols - 1), coeff1 = 2.0f * CV_PI / (double)(rows - 1);
|
||||
for(int j = 0; j < cols; j++)
|
||||
wc[j] = 0.5 * (1.0 - cos(coeff0 * j));
|
||||
|
||||
if(dst.depth() == CV_32F)
|
||||
{
|
||||
for(int i = 0; i < rows; i++)
|
||||
{
|
||||
float* dstData = dst.ptr<float>(i);
|
||||
double wr = 0.5 * (1.0f - cos(2.0f * CV_PI * (double)i / (double)(rows - 1)));
|
||||
double wr = 0.5 * (1.0 - cos(coeff1 * i));
|
||||
for(int j = 0; j < cols; j++)
|
||||
{
|
||||
double wc = 0.5 * (1.0f - cos(2.0f * CV_PI * (double)j / (double)(cols - 1)));
|
||||
dstData[j] = (float)(wr * wc);
|
||||
}
|
||||
dstData[j] = (float)(wr * wc[j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -597,12 +600,9 @@ void cv::createHanningWindow(OutputArray _dst, cv::Size winSize, int type)
|
||||
for(int i = 0; i < rows; i++)
|
||||
{
|
||||
double* dstData = dst.ptr<double>(i);
|
||||
double wr = 0.5 * (1.0 - cos(2.0 * CV_PI * (double)i / (double)(rows - 1)));
|
||||
double wr = 0.5 * (1.0 - cos(coeff1 * i));
|
||||
for(int j = 0; j < cols; j++)
|
||||
{
|
||||
double wc = 0.5 * (1.0 - cos(2.0 * CV_PI * (double)j / (double)(cols - 1)));
|
||||
dstData[j] = wr * wc;
|
||||
}
|
||||
dstData[j] = wr * wc[j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
@@ -400,12 +401,96 @@ pyrUp_( const Mat& _src, Mat& _dst, int)
|
||||
|
||||
typedef void (*PyrFunc)(const Mat&, Mat&, int);
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType)
|
||||
{
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
|
||||
|
||||
if ((channels != 1 && channels != 2 && channels != 4) || borderType != BORDER_DEFAULT)
|
||||
return false;
|
||||
|
||||
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
||||
if ((depth == CV_64F) && !(doubleSupport))
|
||||
return false;
|
||||
|
||||
Size ssize = _src.size();
|
||||
Size dsize = _dsz.area() == 0 ? Size((ssize.width + 1) / 2, (ssize.height + 1) / 2) : _dsz;
|
||||
CV_Assert( ssize.width > 0 && ssize.height > 0 &&
|
||||
std::abs(dsize.width*2 - ssize.width) <= 2 &&
|
||||
std::abs(dsize.height*2 - ssize.height) <= 2 );
|
||||
|
||||
UMat src = _src.getUMat();
|
||||
_dst.create( dsize, src.type() );
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
int float_depth = depth == CV_64F ? CV_64F : CV_32F;
|
||||
char cvt[2][50];
|
||||
ocl::Kernel k("pyrDown", ocl::imgproc::pyr_down_oclsrc,
|
||||
format("-D T=%s -D FT=%s -D convertToT=%s -D convertToFT=%s%s",
|
||||
ocl::typeToStr(type), ocl::typeToStr(CV_MAKETYPE(float_depth, channels)),
|
||||
ocl::convertTypeStr(float_depth, depth, channels, cvt[0]),
|
||||
ocl::convertTypeStr(depth, float_depth, channels, cvt[1]),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : ""));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst));
|
||||
|
||||
size_t localThreads[2] = { 256, 1 };
|
||||
size_t globalThreads[2] = { src.cols, dst.rows };
|
||||
return k.run(2, globalThreads, localThreads, false);
|
||||
}
|
||||
|
||||
static bool ocl_pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType)
|
||||
{
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
|
||||
|
||||
if ((channels != 1 && channels != 2 && channels != 4) || borderType != BORDER_DEFAULT)
|
||||
return false;
|
||||
|
||||
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
||||
if (depth == CV_64F && !doubleSupport)
|
||||
return false;
|
||||
|
||||
Size ssize = _src.size();
|
||||
if ((_dsz.area() != 0) && (_dsz != Size(ssize.width * 2, ssize.height * 2)))
|
||||
return false;
|
||||
|
||||
UMat src = _src.getUMat();
|
||||
Size dsize = Size(ssize.width * 2, ssize.height * 2);
|
||||
_dst.create( dsize, src.type() );
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
int float_depth = depth == CV_64F ? CV_64F : CV_32F;
|
||||
char cvt[2][50];
|
||||
ocl::Kernel k("pyrUp", ocl::imgproc::pyr_up_oclsrc,
|
||||
format("-D T=%s -D FT=%s -D convertToT=%s -D convertToFT=%s%s",
|
||||
ocl::typeToStr(type), ocl::typeToStr(CV_MAKETYPE(float_depth, channels)),
|
||||
ocl::convertTypeStr(float_depth, depth, channels, cvt[0]),
|
||||
ocl::convertTypeStr(depth, float_depth, channels, cvt[1]),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : ""));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst));
|
||||
size_t globalThreads[2] = {dst.cols, dst.rows};
|
||||
size_t localThreads[2] = {16, 16};
|
||||
|
||||
return k.run(2, globalThreads, localThreads, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void cv::pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType )
|
||||
{
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_pyrDown(_src, _dst, _dsz, borderType))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Size dsz = _dsz == Size() ? Size((src.cols + 1)/2, (src.rows + 1)/2) : _dsz;
|
||||
Size dsz = _dsz.area() == 0 ? Size((src.cols + 1)/2, (src.rows + 1)/2) : _dsz;
|
||||
_dst.create( dsz, src.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
@@ -434,8 +519,11 @@ void cv::pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borde
|
||||
|
||||
void cv::pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType )
|
||||
{
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_pyrUp(_src, _dst, _dsz, borderType))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Size dsz = _dsz == Size() ? Size(src.cols*2, src.rows*2) : _dsz;
|
||||
Size dsz = _dsz.area() == 0 ? Size(src.cols*2, src.rows*2) : _dsz;
|
||||
_dst.create( dsz, src.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
@@ -464,6 +552,16 @@ void cv::pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int borderT
|
||||
|
||||
void cv::buildPyramid( InputArray _src, OutputArrayOfArrays _dst, int maxlevel, int borderType )
|
||||
{
|
||||
if (_src.dims() <= 2 && _dst.isUMatVector())
|
||||
{
|
||||
UMat src = _src.getUMat();
|
||||
_dst.create( maxlevel + 1, 1, 0 );
|
||||
_dst.getUMatRef(0) = src;
|
||||
for( int i = 1; i <= maxlevel; i++ )
|
||||
pyrDown( _dst.getUMatRef(i-1), _dst.getUMatRef(i), Size(), borderType );
|
||||
return;
|
||||
}
|
||||
|
||||
Mat src = _src.getMat();
|
||||
_dst.create( maxlevel + 1, 1, 0 );
|
||||
_dst.getMatRef(0) = src;
|
||||
|
||||
+310
-307
@@ -67,15 +67,18 @@ namespace cv
|
||||
Box Filter
|
||||
\****************************************************************************************/
|
||||
|
||||
template<typename T, typename ST> struct RowSum : public BaseRowFilter
|
||||
template<typename T, typename ST>
|
||||
struct RowSum :
|
||||
public BaseRowFilter
|
||||
{
|
||||
RowSum( int _ksize, int _anchor )
|
||||
RowSum( int _ksize, int _anchor ) :
|
||||
BaseRowFilter()
|
||||
{
|
||||
ksize = _ksize;
|
||||
anchor = _anchor;
|
||||
}
|
||||
|
||||
void operator()(const uchar* src, uchar* dst, int width, int cn)
|
||||
virtual void operator()(const uchar* src, uchar* dst, int width, int cn)
|
||||
{
|
||||
const T* S = (const T*)src;
|
||||
ST* D = (ST*)dst;
|
||||
@@ -98,9 +101,12 @@ template<typename T, typename ST> struct RowSum : public BaseRowFilter
|
||||
};
|
||||
|
||||
|
||||
template<typename ST, typename T> struct ColumnSum : public BaseColumnFilter
|
||||
template<typename ST, typename T>
|
||||
struct ColumnSum :
|
||||
public BaseColumnFilter
|
||||
{
|
||||
ColumnSum( int _ksize, int _anchor, double _scale )
|
||||
ColumnSum( int _ksize, int _anchor, double _scale ) :
|
||||
BaseColumnFilter()
|
||||
{
|
||||
ksize = _ksize;
|
||||
anchor = _anchor;
|
||||
@@ -108,9 +114,9 @@ template<typename ST, typename T> struct ColumnSum : public BaseColumnFilter
|
||||
sumCount = 0;
|
||||
}
|
||||
|
||||
void reset() { sumCount = 0; }
|
||||
virtual void reset() { sumCount = 0; }
|
||||
|
||||
void operator()(const uchar** src, uchar* dst, int dststep, int count, int width)
|
||||
virtual void operator()(const uchar** src, uchar* dst, int dststep, int count, int width)
|
||||
{
|
||||
int i;
|
||||
ST* SUM;
|
||||
@@ -198,9 +204,12 @@ template<typename ST, typename T> struct ColumnSum : public BaseColumnFilter
|
||||
};
|
||||
|
||||
|
||||
template<> struct ColumnSum<int, uchar> : public BaseColumnFilter
|
||||
template<>
|
||||
struct ColumnSum<int, uchar> :
|
||||
public BaseColumnFilter
|
||||
{
|
||||
ColumnSum( int _ksize, int _anchor, double _scale )
|
||||
ColumnSum( int _ksize, int _anchor, double _scale ) :
|
||||
BaseColumnFilter()
|
||||
{
|
||||
ksize = _ksize;
|
||||
anchor = _anchor;
|
||||
@@ -208,9 +217,9 @@ template<> struct ColumnSum<int, uchar> : public BaseColumnFilter
|
||||
sumCount = 0;
|
||||
}
|
||||
|
||||
void reset() { sumCount = 0; }
|
||||
virtual void reset() { sumCount = 0; }
|
||||
|
||||
void operator()(const uchar** src, uchar* dst, int dststep, int count, int width)
|
||||
virtual void operator()(const uchar** src, uchar* dst, int dststep, int count, int width)
|
||||
{
|
||||
int i;
|
||||
int* SUM;
|
||||
@@ -339,9 +348,12 @@ template<> struct ColumnSum<int, uchar> : public BaseColumnFilter
|
||||
std::vector<int> sum;
|
||||
};
|
||||
|
||||
template<> struct ColumnSum<int, short> : public BaseColumnFilter
|
||||
template<>
|
||||
struct ColumnSum<int, short> :
|
||||
public BaseColumnFilter
|
||||
{
|
||||
ColumnSum( int _ksize, int _anchor, double _scale )
|
||||
ColumnSum( int _ksize, int _anchor, double _scale ) :
|
||||
BaseColumnFilter()
|
||||
{
|
||||
ksize = _ksize;
|
||||
anchor = _anchor;
|
||||
@@ -349,9 +361,9 @@ template<> struct ColumnSum<int, short> : public BaseColumnFilter
|
||||
sumCount = 0;
|
||||
}
|
||||
|
||||
void reset() { sumCount = 0; }
|
||||
virtual void reset() { sumCount = 0; }
|
||||
|
||||
void operator()(const uchar** src, uchar* dst, int dststep, int count, int width)
|
||||
virtual void operator()(const uchar** src, uchar* dst, int dststep, int count, int width)
|
||||
{
|
||||
int i;
|
||||
int* SUM;
|
||||
@@ -477,9 +489,12 @@ template<> struct ColumnSum<int, short> : public BaseColumnFilter
|
||||
};
|
||||
|
||||
|
||||
template<> struct ColumnSum<int, ushort> : public BaseColumnFilter
|
||||
template<>
|
||||
struct ColumnSum<int, ushort> :
|
||||
public BaseColumnFilter
|
||||
{
|
||||
ColumnSum( int _ksize, int _anchor, double _scale )
|
||||
ColumnSum( int _ksize, int _anchor, double _scale ) :
|
||||
BaseColumnFilter()
|
||||
{
|
||||
ksize = _ksize;
|
||||
anchor = _anchor;
|
||||
@@ -487,9 +502,9 @@ template<> struct ColumnSum<int, ushort> : public BaseColumnFilter
|
||||
sumCount = 0;
|
||||
}
|
||||
|
||||
void reset() { sumCount = 0; }
|
||||
virtual void reset() { sumCount = 0; }
|
||||
|
||||
void operator()(const uchar** src, uchar* dst, int dststep, int count, int width)
|
||||
virtual void operator()(const uchar** src, uchar* dst, int dststep, int count, int width)
|
||||
{
|
||||
int i;
|
||||
int* SUM;
|
||||
@@ -611,9 +626,117 @@ template<> struct ColumnSum<int, ushort> : public BaseColumnFilter
|
||||
std::vector<int> sum;
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
#define DIVUP(total, grain) ((total + grain - 1) / (grain))
|
||||
|
||||
static bool ocl_boxFilter( InputArray _src, OutputArray _dst, int ddepth,
|
||||
Size ksize, Point anchor, int borderType, bool normalize, bool sqr = false )
|
||||
{
|
||||
int type = _src.type(), sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), esz = CV_ELEM_SIZE(type);
|
||||
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
||||
|
||||
if (ddepth < 0)
|
||||
ddepth = sdepth;
|
||||
|
||||
if (!(cn == 1 || cn == 2 || cn == 4) || (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F)) ||
|
||||
_src.offset() % esz != 0 || _src.step() % esz != 0)
|
||||
return false;
|
||||
|
||||
if (anchor.x < 0)
|
||||
anchor.x = ksize.width / 2;
|
||||
if (anchor.y < 0)
|
||||
anchor.y = ksize.height / 2;
|
||||
|
||||
int computeUnits = ocl::Device::getDefault().maxComputeUnits();
|
||||
float alpha = 1.0f / (ksize.height * ksize.width);
|
||||
Size size = _src.size(), wholeSize;
|
||||
bool isolated = (borderType & BORDER_ISOLATED) != 0;
|
||||
borderType &= ~BORDER_ISOLATED;
|
||||
int wdepth = std::max(CV_32F, std::max(ddepth, sdepth));
|
||||
|
||||
const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", 0, "BORDER_REFLECT_101" };
|
||||
size_t globalsize[2] = { size.width, size.height };
|
||||
size_t localsize[2] = { 0, 1 };
|
||||
|
||||
UMat src = _src.getUMat();
|
||||
if (!isolated)
|
||||
{
|
||||
Point ofs;
|
||||
src.locateROI(wholeSize, ofs);
|
||||
}
|
||||
|
||||
int h = isolated ? size.height : wholeSize.height;
|
||||
int w = isolated ? size.width : wholeSize.width;
|
||||
|
||||
size_t maxWorkItemSizes[32];
|
||||
ocl::Device::getDefault().maxWorkItemSizes(maxWorkItemSizes);
|
||||
int tryWorkItems = (int)maxWorkItemSizes[0];
|
||||
|
||||
ocl::Kernel kernel;
|
||||
for ( ; ; )
|
||||
{
|
||||
int BLOCK_SIZE_X = tryWorkItems, BLOCK_SIZE_Y = std::min(ksize.height * 10, size.height);
|
||||
|
||||
while (BLOCK_SIZE_X > 32 && BLOCK_SIZE_X >= ksize.width * 2 && BLOCK_SIZE_X > size.width * 2)
|
||||
BLOCK_SIZE_X /= 2;
|
||||
while (BLOCK_SIZE_Y < BLOCK_SIZE_X / 8 && BLOCK_SIZE_Y * computeUnits * 32 < size.height)
|
||||
BLOCK_SIZE_Y *= 2;
|
||||
|
||||
if (ksize.width > BLOCK_SIZE_X || w < ksize.width || h < ksize.height)
|
||||
return false;
|
||||
|
||||
char cvt[2][50];
|
||||
String opts = format("-D LOCAL_SIZE_X=%d -D BLOCK_SIZE_Y=%d -D ST=%s -D DT=%s -D WT=%s -D convertToDT=%s -D convertToWT=%s "
|
||||
"-D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d -D %s%s%s%s%s",
|
||||
BLOCK_SIZE_X, BLOCK_SIZE_Y, ocl::typeToStr(type), ocl::typeToStr(CV_MAKE_TYPE(ddepth, cn)),
|
||||
ocl::typeToStr(CV_MAKE_TYPE(wdepth, cn)),
|
||||
ocl::convertTypeStr(wdepth, ddepth, cn, cvt[0]),
|
||||
ocl::convertTypeStr(sdepth, wdepth, cn, cvt[1]),
|
||||
anchor.x, anchor.y, ksize.width, ksize.height, borderMap[borderType],
|
||||
isolated ? " -D BORDER_ISOLATED" : "", doubleSupport ? " -D DOUBLE_SUPPORT" : "",
|
||||
normalize ? " -D NORMALIZE" : "", sqr ? " -D SQR" : "");
|
||||
|
||||
localsize[0] = BLOCK_SIZE_X;
|
||||
globalsize[0] = DIVUP(size.width, BLOCK_SIZE_X - (ksize.width - 1)) * BLOCK_SIZE_X;
|
||||
globalsize[1] = DIVUP(size.height, BLOCK_SIZE_Y);
|
||||
|
||||
kernel.create("boxFilter", cv::ocl::imgproc::boxFilter_oclsrc, opts);
|
||||
|
||||
size_t kernelWorkGroupSize = kernel.workGroupSize();
|
||||
if (localsize[0] <= kernelWorkGroupSize)
|
||||
break;
|
||||
if (BLOCK_SIZE_X < (int)kernelWorkGroupSize)
|
||||
return false;
|
||||
|
||||
tryWorkItems = (int)kernelWorkGroupSize;
|
||||
}
|
||||
|
||||
_dst.create(size, CV_MAKETYPE(ddepth, cn));
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
int idxArg = kernel.set(0, ocl::KernelArg::PtrReadOnly(src));
|
||||
idxArg = kernel.set(idxArg, (int)src.step);
|
||||
int srcOffsetX = (int)((src.offset % src.step) / src.elemSize());
|
||||
int srcOffsetY = (int)(src.offset / src.step);
|
||||
int srcEndX = isolated ? srcOffsetX + size.width : wholeSize.width;
|
||||
int srcEndY = isolated ? srcOffsetY + size.height : wholeSize.height;
|
||||
idxArg = kernel.set(idxArg, srcOffsetX);
|
||||
idxArg = kernel.set(idxArg, srcOffsetY);
|
||||
idxArg = kernel.set(idxArg, srcEndX);
|
||||
idxArg = kernel.set(idxArg, srcEndY);
|
||||
idxArg = kernel.set(idxArg, ocl::KernelArg::WriteOnly(dst));
|
||||
if (normalize)
|
||||
idxArg = kernel.set(idxArg, (float)alpha);
|
||||
|
||||
return kernel.run(2, globalsize, localsize, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
cv::Ptr<cv::BaseRowFilter> cv::getRowSumFilter(int srcType, int sumType, int ksize, int anchor)
|
||||
{
|
||||
int sdepth = CV_MAT_DEPTH(srcType), ddepth = CV_MAT_DEPTH(sumType);
|
||||
@@ -713,13 +836,15 @@ void cv::boxFilter( InputArray _src, OutputArray _dst, int ddepth,
|
||||
Size ksize, Point anchor,
|
||||
bool normalize, int borderType )
|
||||
{
|
||||
CV_OCL_RUN(_dst.isUMat(), ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType, normalize))
|
||||
|
||||
Mat src = _src.getMat();
|
||||
int sdepth = src.depth(), cn = src.channels();
|
||||
if( ddepth < 0 )
|
||||
ddepth = sdepth;
|
||||
_dst.create( src.size(), CV_MAKETYPE(ddepth, cn) );
|
||||
Mat dst = _dst.getMat();
|
||||
if( borderType != BORDER_CONSTANT && normalize )
|
||||
if( borderType != BORDER_CONSTANT && normalize && (borderType & BORDER_ISOLATED) != 0 )
|
||||
{
|
||||
if( src.rows == 1 )
|
||||
ksize.height = 1;
|
||||
@@ -742,6 +867,122 @@ void cv::blur( InputArray src, OutputArray dst,
|
||||
boxFilter( src, dst, -1, ksize, anchor, true, borderType );
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
Squared Box Filter
|
||||
\****************************************************************************************/
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
template<typename T, typename ST>
|
||||
struct SqrRowSum :
|
||||
public BaseRowFilter
|
||||
{
|
||||
SqrRowSum( int _ksize, int _anchor ) :
|
||||
BaseRowFilter()
|
||||
{
|
||||
ksize = _ksize;
|
||||
anchor = _anchor;
|
||||
}
|
||||
|
||||
virtual void operator()(const uchar* src, uchar* dst, int width, int cn)
|
||||
{
|
||||
const T* S = (const T*)src;
|
||||
ST* D = (ST*)dst;
|
||||
int i = 0, k, ksz_cn = ksize*cn;
|
||||
|
||||
width = (width - 1)*cn;
|
||||
for( k = 0; k < cn; k++, S++, D++ )
|
||||
{
|
||||
ST s = 0;
|
||||
for( i = 0; i < ksz_cn; i += cn )
|
||||
{
|
||||
ST val = (ST)S[i];
|
||||
s += val*val;
|
||||
}
|
||||
D[0] = s;
|
||||
for( i = 0; i < width; i += cn )
|
||||
{
|
||||
ST val0 = (ST)S[i], val1 = (ST)S[i + ksz_cn];
|
||||
s += val1*val1 - val0*val0;
|
||||
D[i+cn] = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static Ptr<BaseRowFilter> getSqrRowSumFilter(int srcType, int sumType, int ksize, int anchor)
|
||||
{
|
||||
int sdepth = CV_MAT_DEPTH(srcType), ddepth = CV_MAT_DEPTH(sumType);
|
||||
CV_Assert( CV_MAT_CN(sumType) == CV_MAT_CN(srcType) );
|
||||
|
||||
if( anchor < 0 )
|
||||
anchor = ksize/2;
|
||||
|
||||
if( sdepth == CV_8U && ddepth == CV_32S )
|
||||
return makePtr<SqrRowSum<uchar, int> >(ksize, anchor);
|
||||
if( sdepth == CV_8U && ddepth == CV_64F )
|
||||
return makePtr<SqrRowSum<uchar, double> >(ksize, anchor);
|
||||
if( sdepth == CV_16U && ddepth == CV_64F )
|
||||
return makePtr<SqrRowSum<ushort, double> >(ksize, anchor);
|
||||
if( sdepth == CV_16S && ddepth == CV_64F )
|
||||
return makePtr<SqrRowSum<short, double> >(ksize, anchor);
|
||||
if( sdepth == CV_32F && ddepth == CV_64F )
|
||||
return makePtr<SqrRowSum<float, double> >(ksize, anchor);
|
||||
if( sdepth == CV_64F && ddepth == CV_64F )
|
||||
return makePtr<SqrRowSum<double, double> >(ksize, anchor);
|
||||
|
||||
CV_Error_( CV_StsNotImplemented,
|
||||
("Unsupported combination of source format (=%d), and buffer format (=%d)",
|
||||
srcType, sumType));
|
||||
|
||||
return Ptr<BaseRowFilter>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cv::sqrBoxFilter( InputArray _src, OutputArray _dst, int ddepth,
|
||||
Size ksize, Point anchor,
|
||||
bool normalize, int borderType )
|
||||
{
|
||||
int srcType = _src.type(), sdepth = CV_MAT_DEPTH(srcType), cn = CV_MAT_CN(srcType);
|
||||
Size size = _src.size();
|
||||
|
||||
if( ddepth < 0 )
|
||||
ddepth = sdepth < CV_32F ? CV_32F : CV_64F;
|
||||
|
||||
if( borderType != BORDER_CONSTANT && normalize )
|
||||
{
|
||||
if( size.height == 1 )
|
||||
ksize.height = 1;
|
||||
if( size.width == 1 )
|
||||
ksize.width = 1;
|
||||
}
|
||||
|
||||
CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
|
||||
ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType, normalize, true))
|
||||
|
||||
int sumDepth = CV_64F;
|
||||
if( sdepth == CV_8U )
|
||||
sumDepth = CV_32S;
|
||||
int sumType = CV_MAKETYPE( sumDepth, cn ), dstType = CV_MAKETYPE(ddepth, cn);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
_dst.create( size, dstType );
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
Ptr<BaseRowFilter> rowFilter = getSqrRowSumFilter(srcType, sumType, ksize.width, anchor.x );
|
||||
Ptr<BaseColumnFilter> columnFilter = getColumnSumFilter(sumType,
|
||||
dstType, ksize.height, anchor.y,
|
||||
normalize ? 1./(ksize.width*ksize.height) : 1);
|
||||
|
||||
Ptr<FilterEngine> f = makePtr<FilterEngine>(Ptr<BaseFilter>(), rowFilter, columnFilter,
|
||||
srcType, dstType, sumType, borderType );
|
||||
f->apply( src, dst );
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
Gaussian Blur
|
||||
\****************************************************************************************/
|
||||
@@ -1659,21 +1900,59 @@ medianBlur_SortNet( const Mat& _src, Mat& _dst, int m )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_medianFilter ( InputArray _src, OutputArray _dst, int m)
|
||||
{
|
||||
int type = _src.type();
|
||||
int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
|
||||
if (!((depth == CV_8U || depth == CV_16U || depth == CV_16S || depth == CV_32F) && (cn != 3 && cn <= 4)))
|
||||
return false;
|
||||
|
||||
const char * kernelName;
|
||||
|
||||
if (m == 3)
|
||||
kernelName = "medianFilter3";
|
||||
else if (m == 5)
|
||||
kernelName = "medianFilter5";
|
||||
else
|
||||
return false;
|
||||
|
||||
ocl::Kernel k(kernelName,ocl::imgproc::medianFilter_oclsrc,format("-D type=%s",ocl::typeToStr(type)));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat src = _src.getUMat();
|
||||
_dst.create(_src.size(),type);
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
size_t globalsize[2] = {(src.cols + 18) / 16 * 16, (src.rows + 15) / 16 * 16};
|
||||
size_t localsize[2] = {16, 16};
|
||||
|
||||
return k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst)).run(2,globalsize,localsize,false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void cv::medianBlur( InputArray _src0, OutputArray _dst, int ksize )
|
||||
{
|
||||
Mat src0 = _src0.getMat();
|
||||
_dst.create( src0.size(), src0.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
CV_Assert( (ksize % 2 == 1) && (_src0.dims() <= 2 ));
|
||||
|
||||
if( ksize <= 1 )
|
||||
{
|
||||
src0.copyTo(dst);
|
||||
_src0.copyTo(_dst);
|
||||
return;
|
||||
}
|
||||
|
||||
CV_Assert( ksize % 2 == 1 );
|
||||
CV_OCL_RUN(_src0.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_medianFilter(_src0,_dst, ksize))
|
||||
|
||||
Mat src0 = _src0.getMat();
|
||||
_dst.create( src0.size(), src0.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
if (tegra::medianBlur(src0, dst, ksize))
|
||||
@@ -1925,6 +2204,8 @@ private:
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_bilateralFilter_8u(InputArray _src, OutputArray _dst, int d,
|
||||
double sigma_color, double sigma_space,
|
||||
int borderType)
|
||||
@@ -2000,6 +2281,8 @@ static bool ocl_bilateralFilter_8u(InputArray _src, OutputArray _dst, int d,
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
bilateralFilter_8u( const Mat& src, Mat& dst, int d,
|
||||
double sigma_color, double sigma_space,
|
||||
@@ -2350,9 +2633,8 @@ void cv::bilateralFilter( InputArray _src, OutputArray _dst, int d,
|
||||
{
|
||||
_dst.create( _src.size(), _src.type() );
|
||||
|
||||
if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() &&
|
||||
ocl_bilateralFilter_8u(_src, _dst, d, sigmaColor, sigmaSpace, borderType))
|
||||
return;
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_bilateralFilter_8u(_src, _dst, d, sigmaColor, sigmaSpace, borderType))
|
||||
|
||||
Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
|
||||
@@ -2365,285 +2647,6 @@ void cv::bilateralFilter( InputArray _src, OutputArray _dst, int d,
|
||||
"Bilateral filtering is only implemented for 8u and 32f images" );
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
Adaptive Bilateral Filtering
|
||||
\****************************************************************************************/
|
||||
|
||||
namespace cv
|
||||
{
|
||||
#ifndef ABF_CALCVAR
|
||||
#define ABF_CALCVAR 1
|
||||
#endif
|
||||
|
||||
#ifndef ABF_FIXED_WEIGHT
|
||||
#define ABF_FIXED_WEIGHT 0
|
||||
#endif
|
||||
|
||||
#ifndef ABF_GAUSSIAN
|
||||
#define ABF_GAUSSIAN 1
|
||||
#endif
|
||||
|
||||
class adaptiveBilateralFilter_8u_Invoker :
|
||||
public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
adaptiveBilateralFilter_8u_Invoker(Mat& _dest, const Mat& _temp, Size _ksize, double _sigma_space, double _maxSigmaColor, Point _anchor) :
|
||||
temp(&_temp), dest(&_dest), ksize(_ksize), sigma_space(_sigma_space), maxSigma_Color(_maxSigmaColor), anchor(_anchor)
|
||||
{
|
||||
if( sigma_space <= 0 )
|
||||
sigma_space = 1;
|
||||
CV_Assert((ksize.width & 1) && (ksize.height & 1));
|
||||
space_weight.resize(ksize.width * ksize.height);
|
||||
double sigma2 = sigma_space * sigma_space;
|
||||
int idx = 0;
|
||||
int w = ksize.width / 2;
|
||||
int h = ksize.height / 2;
|
||||
for(int y=-h; y<=h; y++)
|
||||
for(int x=-w; x<=w; x++)
|
||||
{
|
||||
#if ABF_GAUSSIAN
|
||||
space_weight[idx++] = (float)exp ( -0.5*(x * x + y * y)/sigma2);
|
||||
#else
|
||||
space_weight[idx++] = (float)(sigma2 / (sigma2 + x * x + y * y));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
virtual void operator()(const Range& range) const
|
||||
{
|
||||
int cn = dest->channels();
|
||||
int anX = anchor.x;
|
||||
|
||||
const uchar *tptr;
|
||||
|
||||
for(int i = range.start;i < range.end; i++)
|
||||
{
|
||||
int startY = i;
|
||||
if(cn == 1)
|
||||
{
|
||||
float var;
|
||||
int currVal;
|
||||
int sumVal = 0;
|
||||
int sumValSqr = 0;
|
||||
int currValCenter;
|
||||
int currWRTCenter;
|
||||
float weight;
|
||||
float totalWeight = 0.;
|
||||
float tmpSum = 0.;
|
||||
|
||||
for(int j = 0;j < dest->cols *cn; j+=cn)
|
||||
{
|
||||
sumVal = 0;
|
||||
sumValSqr= 0;
|
||||
totalWeight = 0.;
|
||||
tmpSum = 0.;
|
||||
|
||||
// Top row: don't sum the very last element
|
||||
int startLMJ = 0;
|
||||
int endLMJ = ksize.width - 1;
|
||||
int howManyAll = (anX *2 +1)*(ksize.width );
|
||||
#if ABF_CALCVAR
|
||||
for(int x = startLMJ; x< endLMJ; x++)
|
||||
{
|
||||
tptr = temp->ptr(startY + x) +j;
|
||||
for(int y=-anX; y<=anX; y++)
|
||||
{
|
||||
currVal = tptr[cn*(y+anX)];
|
||||
sumVal += currVal;
|
||||
sumValSqr += (currVal *currVal);
|
||||
}
|
||||
}
|
||||
var = ( (sumValSqr * howManyAll)- sumVal * sumVal ) / ( (float)(howManyAll*howManyAll));
|
||||
|
||||
if(var < 0.01)
|
||||
var = 0.01f;
|
||||
else if(var > (float)(maxSigma_Color*maxSigma_Color) )
|
||||
var = (float)(maxSigma_Color*maxSigma_Color) ;
|
||||
|
||||
#else
|
||||
var = maxSigmaColor*maxSigmaColor;
|
||||
#endif
|
||||
startLMJ = 0;
|
||||
endLMJ = ksize.width;
|
||||
tptr = temp->ptr(startY + (startLMJ+ endLMJ)/2);
|
||||
currValCenter =tptr[j+cn*anX];
|
||||
for(int x = startLMJ; x< endLMJ; x++)
|
||||
{
|
||||
tptr = temp->ptr(startY + x) +j;
|
||||
for(int y=-anX; y<=anX; y++)
|
||||
{
|
||||
#if ABF_FIXED_WEIGHT
|
||||
weight = 1.0;
|
||||
#else
|
||||
currVal = tptr[cn*(y+anX)];
|
||||
currWRTCenter = currVal - currValCenter;
|
||||
|
||||
#if ABF_GAUSSIAN
|
||||
weight = exp ( -0.5f * currWRTCenter * currWRTCenter/var ) * space_weight[x*ksize.width+y+anX];
|
||||
#else
|
||||
weight = var / ( var + (currWRTCenter * currWRTCenter) ) * space_weight[x*ksize.width+y+anX];
|
||||
#endif
|
||||
|
||||
#endif
|
||||
tmpSum += ((float)tptr[cn*(y+anX)] * weight);
|
||||
totalWeight += weight;
|
||||
}
|
||||
}
|
||||
tmpSum /= totalWeight;
|
||||
|
||||
dest->at<uchar>(startY ,j)= static_cast<uchar>(tmpSum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(cn == 3);
|
||||
float var_b, var_g, var_r;
|
||||
int currVal_b, currVal_g, currVal_r;
|
||||
int sumVal_b= 0, sumVal_g= 0, sumVal_r= 0;
|
||||
int sumValSqr_b= 0, sumValSqr_g= 0, sumValSqr_r= 0;
|
||||
int currValCenter_b= 0, currValCenter_g= 0, currValCenter_r= 0;
|
||||
int currWRTCenter_b, currWRTCenter_g, currWRTCenter_r;
|
||||
float weight_b, weight_g, weight_r;
|
||||
float totalWeight_b= 0., totalWeight_g= 0., totalWeight_r= 0.;
|
||||
float tmpSum_b = 0., tmpSum_g= 0., tmpSum_r = 0.;
|
||||
|
||||
for(int j = 0;j < dest->cols *cn; j+=cn)
|
||||
{
|
||||
sumVal_b= 0, sumVal_g= 0, sumVal_r= 0;
|
||||
sumValSqr_b= 0, sumValSqr_g= 0, sumValSqr_r= 0;
|
||||
totalWeight_b= 0., totalWeight_g= 0., totalWeight_r= 0.;
|
||||
tmpSum_b = 0., tmpSum_g= 0., tmpSum_r = 0.;
|
||||
|
||||
// Top row: don't sum the very last element
|
||||
int startLMJ = 0;
|
||||
int endLMJ = ksize.width - 1;
|
||||
int howManyAll = (anX *2 +1)*(ksize.width);
|
||||
#if ABF_CALCVAR
|
||||
float max_var = (float)( maxSigma_Color*maxSigma_Color);
|
||||
for(int x = startLMJ; x< endLMJ; x++)
|
||||
{
|
||||
tptr = temp->ptr(startY + x) +j;
|
||||
for(int y=-anX; y<=anX; y++)
|
||||
{
|
||||
currVal_b = tptr[cn*(y+anX)], currVal_g = tptr[cn*(y+anX)+1], currVal_r =tptr[cn*(y+anX)+2];
|
||||
sumVal_b += currVal_b;
|
||||
sumVal_g += currVal_g;
|
||||
sumVal_r += currVal_r;
|
||||
sumValSqr_b += (currVal_b *currVal_b);
|
||||
sumValSqr_g += (currVal_g *currVal_g);
|
||||
sumValSqr_r += (currVal_r *currVal_r);
|
||||
}
|
||||
}
|
||||
var_b = ( (sumValSqr_b * howManyAll)- sumVal_b * sumVal_b ) / ( (float)(howManyAll*howManyAll));
|
||||
var_g = ( (sumValSqr_g * howManyAll)- sumVal_g * sumVal_g ) / ( (float)(howManyAll*howManyAll));
|
||||
var_r = ( (sumValSqr_r * howManyAll)- sumVal_r * sumVal_r ) / ( (float)(howManyAll*howManyAll));
|
||||
|
||||
if(var_b < 0.01)
|
||||
var_b = 0.01f;
|
||||
else if(var_b > max_var )
|
||||
var_b = (float)(max_var) ;
|
||||
|
||||
if(var_g < 0.01)
|
||||
var_g = 0.01f;
|
||||
else if(var_g > max_var )
|
||||
var_g = (float)(max_var) ;
|
||||
|
||||
if(var_r < 0.01)
|
||||
var_r = 0.01f;
|
||||
else if(var_r > max_var )
|
||||
var_r = (float)(max_var) ;
|
||||
|
||||
#else
|
||||
var_b = maxSigma_Color*maxSigma_Color; var_g = maxSigma_Color*maxSigma_Color; var_r = maxSigma_Color*maxSigma_Color;
|
||||
#endif
|
||||
startLMJ = 0;
|
||||
endLMJ = ksize.width;
|
||||
tptr = temp->ptr(startY + (startLMJ+ endLMJ)/2) + j;
|
||||
currValCenter_b =tptr[cn*anX], currValCenter_g =tptr[cn*anX+1], currValCenter_r =tptr[cn*anX+2];
|
||||
for(int x = startLMJ; x< endLMJ; x++)
|
||||
{
|
||||
tptr = temp->ptr(startY + x) +j;
|
||||
for(int y=-anX; y<=anX; y++)
|
||||
{
|
||||
#if ABF_FIXED_WEIGHT
|
||||
weight_b = 1.0;
|
||||
weight_g = 1.0;
|
||||
weight_r = 1.0;
|
||||
#else
|
||||
currVal_b = tptr[cn*(y+anX)];currVal_g=tptr[cn*(y+anX)+1];currVal_r=tptr[cn*(y+anX)+2];
|
||||
currWRTCenter_b = currVal_b - currValCenter_b;
|
||||
currWRTCenter_g = currVal_g - currValCenter_g;
|
||||
currWRTCenter_r = currVal_r - currValCenter_r;
|
||||
|
||||
float cur_spw = space_weight[x*ksize.width+y+anX];
|
||||
|
||||
#if ABF_GAUSSIAN
|
||||
weight_b = exp( -0.5f * currWRTCenter_b * currWRTCenter_b/ var_b ) * cur_spw;
|
||||
weight_g = exp( -0.5f * currWRTCenter_g * currWRTCenter_g/ var_g ) * cur_spw;
|
||||
weight_r = exp( -0.5f * currWRTCenter_r * currWRTCenter_r/ var_r ) * cur_spw;
|
||||
#else
|
||||
weight_b = var_b / ( var_b + (currWRTCenter_b * currWRTCenter_b) ) * cur_spw;
|
||||
weight_g = var_g / ( var_g + (currWRTCenter_g * currWRTCenter_g) ) * cur_spw;
|
||||
weight_r = var_r / ( var_r + (currWRTCenter_r * currWRTCenter_r) ) * cur_spw;
|
||||
#endif
|
||||
#endif
|
||||
tmpSum_b += ((float)tptr[cn*(y+anX)] * weight_b);
|
||||
tmpSum_g += ((float)tptr[cn*(y+anX)+1] * weight_g);
|
||||
tmpSum_r += ((float)tptr[cn*(y+anX)+2] * weight_r);
|
||||
totalWeight_b += weight_b, totalWeight_g += weight_g, totalWeight_r += weight_r;
|
||||
}
|
||||
}
|
||||
tmpSum_b /= totalWeight_b;
|
||||
tmpSum_g /= totalWeight_g;
|
||||
tmpSum_r /= totalWeight_r;
|
||||
|
||||
dest->at<uchar>(startY,j )= static_cast<uchar>(tmpSum_b);
|
||||
dest->at<uchar>(startY,j+1)= static_cast<uchar>(tmpSum_g);
|
||||
dest->at<uchar>(startY,j+2)= static_cast<uchar>(tmpSum_r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
const Mat *temp;
|
||||
Mat *dest;
|
||||
Size ksize;
|
||||
double sigma_space;
|
||||
double maxSigma_Color;
|
||||
Point anchor;
|
||||
std::vector<float> space_weight;
|
||||
};
|
||||
static void adaptiveBilateralFilter_8u( const Mat& src, Mat& dst, Size ksize, double sigmaSpace, double maxSigmaColor, Point anchor, int borderType )
|
||||
{
|
||||
Size size = src.size();
|
||||
|
||||
CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_8UC3) &&
|
||||
src.type() == dst.type() && src.size() == dst.size() &&
|
||||
src.data != dst.data );
|
||||
Mat temp;
|
||||
copyMakeBorder(src, temp, anchor.x, anchor.y, anchor.x, anchor.y, borderType);
|
||||
|
||||
adaptiveBilateralFilter_8u_Invoker body(dst, temp, ksize, sigmaSpace, maxSigmaColor, anchor);
|
||||
parallel_for_(Range(0, size.height), body, dst.total()/(double)(1<<16));
|
||||
}
|
||||
}
|
||||
void cv::adaptiveBilateralFilter( InputArray _src, OutputArray _dst, Size ksize,
|
||||
double sigmaSpace, double maxSigmaColor, Point anchor, int borderType )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
_dst.create(src.size(), src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3);
|
||||
|
||||
anchor = normalizeAnchor(anchor,ksize);
|
||||
if( src.depth() == CV_8U )
|
||||
adaptiveBilateralFilter_8u( src, dst, ksize, sigmaSpace, maxSigmaColor, anchor, borderType );
|
||||
else
|
||||
CV_Error( CV_StsUnsupportedFormat,
|
||||
"Adaptive Bilateral filtering is only implemented for 8u images" );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CV_IMPL void
|
||||
|
||||
@@ -233,6 +233,8 @@ typedef void (*IntegralFunc)(const uchar* src, size_t srcstep, uchar* sum, size_
|
||||
uchar* sqsum, size_t sqsumstep, uchar* tilted, size_t tstep,
|
||||
Size size, int cn );
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
enum { vlen = 4 };
|
||||
|
||||
static bool ocl_integral( InputArray _src, OutputArray _sum, int sdepth )
|
||||
@@ -326,6 +328,8 @@ static bool ocl_integral( InputArray _src, OutputArray _sum, OutputArray _sqsum,
|
||||
return k2.run(1, >2, <2, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -338,63 +342,15 @@ void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, Output
|
||||
sqdepth = CV_64F;
|
||||
sdepth = CV_MAT_DEPTH(sdepth), sqdepth = CV_MAT_DEPTH(sqdepth);
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
if (ocl::useOpenCL() && _sum.isUMat() && !_tilted.needed())
|
||||
{
|
||||
if (!_sqsum.needed())
|
||||
{
|
||||
if (ocl_integral(_src, _sum, sdepth))
|
||||
return;
|
||||
CV_OCL_RUN(ocl::useOpenCL(), ocl_integral(_src, _sum, sdepth))
|
||||
}
|
||||
else if (_sqsum.isUMat())
|
||||
{
|
||||
if (ocl_integral(_src, _sum, _sqsum, sdepth, sqdepth))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
if( ( depth == CV_8U ) && ( !_tilted.needed() ) )
|
||||
{
|
||||
if( sdepth == CV_32F )
|
||||
{
|
||||
if( cn == 1 )
|
||||
{
|
||||
IppiSize srcRoiSize = ippiSize( src.cols, src.rows );
|
||||
_sum.create( isize, CV_MAKETYPE( sdepth, cn ) );
|
||||
sum = _sum.getMat();
|
||||
if( _sqsum.needed() && sqdepth == CV_64F )
|
||||
{
|
||||
_sqsum.create( isize, CV_MAKETYPE( sqdepth, cn ) );
|
||||
sqsum = _sqsum.getMat();
|
||||
ippiSqrIntegral_8u32f64f_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32f*)sum.data, (int)sum.step, (Ipp64f*)sqsum.data, (int)sqsum.step, srcRoiSize, 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
ippiIntegral_8u32f_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32f*)sum.data, (int)sum.step, srcRoiSize, 0 );
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( sdepth == CV_32S )
|
||||
{
|
||||
if( cn == 1 )
|
||||
{
|
||||
IppiSize srcRoiSize = ippiSize( src.cols, src.rows );
|
||||
_sum.create( isize, CV_MAKETYPE( sdepth, cn ) );
|
||||
sum = _sum.getMat();
|
||||
if( _sqsum.needed() && sqdepth == CV_64F )
|
||||
{
|
||||
_sqsum.create( isize, CV_MAKETYPE( sqdepth, cn ) );
|
||||
sqsum = _sqsum.getMat();
|
||||
ippiSqrIntegral_8u32s64f_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32s*)sum.data, (int)sum.step, (Ipp64f*)sqsum.data, (int)sqsum.step, srcRoiSize, 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
ippiIntegral_8u32s_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32s*)sum.data, (int)sum.step, srcRoiSize, 0 );
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
CV_OCL_RUN(ocl::useOpenCL(), ocl_integral(_src, _sum, _sqsum, sdepth, sqdepth))
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -406,7 +362,37 @@ void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, Output
|
||||
{
|
||||
_sqsum.create( isize, CV_MAKETYPE(sqdepth, cn) );
|
||||
sqsum = _sqsum.getMat();
|
||||
};
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
if( ( depth == CV_8U ) && ( sdepth == CV_32F || sdepth == CV_32S ) && ( !_tilted.needed() ) && ( !_sqsum.needed() || sqdepth == CV_64F ) && ( cn == 1 ) )
|
||||
{
|
||||
IppiSize srcRoiSize = ippiSize( src.cols, src.rows );
|
||||
if( sdepth == CV_32F )
|
||||
{
|
||||
if( _sqsum.needed() )
|
||||
{
|
||||
ippiSqrIntegral_8u32f64f_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32f*)sum.data, (int)sum.step, (Ipp64f*)sqsum.data, (int)sqsum.step, srcRoiSize, 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
ippiIntegral_8u32f_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32f*)sum.data, (int)sum.step, srcRoiSize, 0 );
|
||||
}
|
||||
}
|
||||
else if( sdepth == CV_32S )
|
||||
{
|
||||
if( _sqsum.needed() )
|
||||
{
|
||||
ippiSqrIntegral_8u32s64f_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32s*)sum.data, (int)sum.step, (Ipp64f*)sqsum.data, (int)sqsum.step, srcRoiSize, 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
ippiIntegral_8u32s_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32s*)sum.data, (int)sum.step, srcRoiSize, 0 );
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( _tilted.needed() )
|
||||
{
|
||||
|
||||
@@ -40,10 +40,307 @@
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
////////////////////////////////////////////////// matchTemplate //////////////////////////////////////////////////////////
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
/////////////////////////////////////////////////// CCORR //////////////////////////////////////////////////////////////
|
||||
|
||||
enum
|
||||
{
|
||||
SUM_1 = 0, SUM_2 = 1
|
||||
};
|
||||
|
||||
static bool sumTemplate(InputArray _src, UMat & result)
|
||||
{
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
int wdepth = std::max(CV_32S, depth), wtype = CV_MAKE_TYPE(wdepth, cn);
|
||||
size_t wgs = ocl::Device::getDefault().maxWorkGroupSize();
|
||||
|
||||
int wgs2_aligned = 1;
|
||||
while (wgs2_aligned < (int)wgs)
|
||||
wgs2_aligned <<= 1;
|
||||
wgs2_aligned >>= 1;
|
||||
|
||||
char cvt[40];
|
||||
ocl::Kernel k("calcSum", ocl::imgproc::match_template_oclsrc,
|
||||
format("-D CALC_SUM -D T=%s -D WT=%s -D cn=%d -D convertToWT=%s -D WGS=%d -D WGS2_ALIGNED=%d -D wdepth=%d",
|
||||
ocl::typeToStr(type), ocl::typeToStr(wtype), cn,
|
||||
ocl::convertTypeStr(depth, wdepth, cn, cvt),
|
||||
(int)wgs, wgs2_aligned, wdepth));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat src = _src.getUMat();
|
||||
result.create(1, 1, CV_32FC1);
|
||||
|
||||
ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
|
||||
resarg = ocl::KernelArg::PtrWriteOnly(result);
|
||||
|
||||
k.args(srcarg, src.cols, (int)src.total(), resarg);
|
||||
|
||||
size_t globalsize = wgs;
|
||||
return k.run(1, &globalsize, &wgs, false);
|
||||
}
|
||||
|
||||
static bool matchTemplateNaive_CCORR(InputArray _image, InputArray _templ, OutputArray _result)
|
||||
{
|
||||
int type = _image.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
int wdepth = std::max(depth, CV_32S), wtype = CV_MAKE_TYPE(wdepth, cn);
|
||||
|
||||
char cvt[40];
|
||||
ocl::Kernel k("matchTemplate_Naive_CCORR", ocl::imgproc::match_template_oclsrc,
|
||||
format("-D CCORR -D T=%s -D WT=%s -D convertToWT=%s -D cn=%d -D wdepth=%d", ocl::typeToStr(type), ocl::typeToStr(wtype),
|
||||
ocl::convertTypeStr(depth, wdepth, cn, cvt), cn, wdepth));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat image = _image.getUMat(), templ = _templ.getUMat();
|
||||
_result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32FC1);
|
||||
UMat result = _result.getUMat();
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ),
|
||||
ocl::KernelArg::WriteOnly(result));
|
||||
|
||||
size_t globalsize[2] = { result.cols, result.rows };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
static bool matchTemplate_CCORR_NORMED(InputArray _image, InputArray _templ, OutputArray _result)
|
||||
{
|
||||
matchTemplate(_image, _templ, _result, CV_TM_CCORR);
|
||||
|
||||
int type = _image.type(), cn = CV_MAT_CN(type);
|
||||
|
||||
ocl::Kernel k("matchTemplate_CCORR_NORMED", ocl::imgproc::match_template_oclsrc,
|
||||
format("-D CCORR_NORMED -D T=%s -D cn=%d", ocl::typeToStr(type), cn));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat image = _image.getUMat(), templ = _templ.getUMat();
|
||||
_result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32FC1);
|
||||
UMat result = _result.getUMat();
|
||||
|
||||
UMat image_sums, image_sqsums;
|
||||
integral(image.reshape(1), image_sums, image_sqsums, CV_32F, CV_32F);
|
||||
|
||||
UMat templ_sqsum;
|
||||
if (!sumTemplate(templ, templ_sqsum))
|
||||
return false;
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::ReadWrite(result),
|
||||
templ.rows, templ.cols, ocl::KernelArg::PtrReadOnly(templ_sqsum));
|
||||
|
||||
size_t globalsize[2] = { result.cols, result.rows };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
////////////////////////////////////// SQDIFF //////////////////////////////////////////////////////////////
|
||||
|
||||
static bool matchTemplateNaive_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result)
|
||||
{
|
||||
int type = _image.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
int wdepth = std::max(depth, CV_32S), wtype = CV_MAKE_TYPE(wdepth, cn);
|
||||
|
||||
char cvt[40];
|
||||
ocl::Kernel k("matchTemplate_Naive_SQDIFF", ocl::imgproc::match_template_oclsrc,
|
||||
format("-D SQDIFF -D T=%s -D WT=%s -D convertToWT=%s -D cn=%d -D wdepth=%d", ocl::typeToStr(type),
|
||||
ocl::typeToStr(wtype), ocl::convertTypeStr(depth, wdepth, cn, cvt), cn, wdepth));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat image = _image.getUMat(), templ = _templ.getUMat();
|
||||
_result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F);
|
||||
UMat result = _result.getUMat();
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ),
|
||||
ocl::KernelArg::WriteOnly(result));
|
||||
|
||||
size_t globalsize[2] = { result.cols, result.rows };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
static bool matchTemplate_SQDIFF_NORMED(InputArray _image, InputArray _templ, OutputArray _result)
|
||||
{
|
||||
matchTemplate(_image, _templ, _result, CV_TM_CCORR);
|
||||
|
||||
int type = _image.type(), cn = CV_MAT_CN(type);
|
||||
|
||||
ocl::Kernel k("matchTemplate_SQDIFF_NORMED", ocl::imgproc::match_template_oclsrc,
|
||||
format("-D SQDIFF_NORMED -D T=%s -D cn=%d", ocl::typeToStr(type), cn));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat image = _image.getUMat(), templ = _templ.getUMat();
|
||||
_result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F);
|
||||
UMat result = _result.getUMat();
|
||||
|
||||
UMat image_sums, image_sqsums;
|
||||
integral(image.reshape(1), image_sums, image_sqsums, CV_32F, CV_32F);
|
||||
|
||||
UMat templ_sqsum;
|
||||
if (!sumTemplate(_templ, templ_sqsum))
|
||||
return false;
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::ReadWrite(result),
|
||||
templ.rows, templ.cols, ocl::KernelArg::PtrReadOnly(templ_sqsum));
|
||||
|
||||
size_t globalsize[2] = { result.cols, result.rows };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
///////////////////////////////////// CCOEFF /////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool matchTemplate_CCOEFF(InputArray _image, InputArray _templ, OutputArray _result)
|
||||
{
|
||||
matchTemplate(_image, _templ, _result, CV_TM_CCORR);
|
||||
|
||||
UMat image_sums, temp;
|
||||
integral(_image, temp);
|
||||
|
||||
if (temp.depth() == CV_64F)
|
||||
temp.convertTo(image_sums, CV_32F);
|
||||
else
|
||||
image_sums = temp;
|
||||
|
||||
int type = image_sums.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
|
||||
ocl::Kernel k("matchTemplate_Prepared_CCOEFF", ocl::imgproc::match_template_oclsrc,
|
||||
format("-D CCOEFF -D T=%s -D elem_type=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat templ = _templ.getUMat();
|
||||
Size size = _image.size(), tsize = templ.size();
|
||||
_result.create(size.height - templ.rows + 1, size.width - templ.cols + 1, CV_32F);
|
||||
UMat result = _result.getUMat();
|
||||
|
||||
if (cn == 1)
|
||||
{
|
||||
float templ_sum = static_cast<float>(sum(_templ)[0]) / tsize.area();
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadWrite(result),
|
||||
templ.rows, templ.cols, templ_sum);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec4f templ_sum = Vec4f::all(0);
|
||||
templ_sum = sum(templ) / tsize.area();
|
||||
|
||||
if (cn == 2)
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols,
|
||||
templ_sum[0], templ_sum[1]);
|
||||
else
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols,
|
||||
templ_sum[0], templ_sum[1], templ_sum[2], templ_sum[3]);
|
||||
}
|
||||
|
||||
size_t globalsize[2] = { result.cols, result.rows };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
static bool matchTemplate_CCOEFF_NORMED(InputArray _image, InputArray _templ, OutputArray _result)
|
||||
{
|
||||
matchTemplate(_image, _templ, _result, CV_TM_CCORR);
|
||||
|
||||
UMat temp, image_sums, image_sqsums;
|
||||
integral(_image, image_sums, image_sqsums, CV_32F, CV_32F);
|
||||
|
||||
int type = image_sums.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
|
||||
ocl::Kernel k("matchTemplate_CCOEFF_NORMED", ocl::imgproc::match_template_oclsrc,
|
||||
format("-D CCOEFF_NORMED -D type=%s -D elem_type=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat templ = _templ.getUMat();
|
||||
Size size = _image.size(), tsize = templ.size();
|
||||
_result.create(size.height - templ.rows + 1, size.width - templ.cols + 1, CV_32F);
|
||||
UMat result = _result.getUMat();
|
||||
|
||||
float scale = 1.f / tsize.area();
|
||||
|
||||
if (cn == 1)
|
||||
{
|
||||
float templ_sum = (float)sum(templ)[0];
|
||||
|
||||
multiply(templ, templ, temp, 1, CV_32F);
|
||||
float templ_sqsum = (float)sum(temp)[0];
|
||||
|
||||
templ_sqsum -= scale * templ_sum * templ_sum;
|
||||
templ_sum *= scale;
|
||||
|
||||
if (templ_sqsum < DBL_EPSILON)
|
||||
{
|
||||
result = Scalar::all(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums),
|
||||
ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, scale, templ_sum, templ_sqsum);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec4f templ_sum = Vec4f::all(0), templ_sqsum = Vec4f::all(0);
|
||||
templ_sum = sum(templ);
|
||||
|
||||
multiply(templ, templ, temp, 1, CV_32F);
|
||||
templ_sqsum = sum(temp);
|
||||
|
||||
float templ_sqsum_sum = 0;
|
||||
for (int i = 0; i < cn; i ++)
|
||||
templ_sqsum_sum += templ_sqsum[i] - scale * templ_sum[i] * templ_sum[i];
|
||||
|
||||
templ_sum *= scale;
|
||||
|
||||
if (templ_sqsum_sum < DBL_EPSILON)
|
||||
{
|
||||
result = Scalar::all(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cn == 2)
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums),
|
||||
ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, scale,
|
||||
templ_sum[0], templ_sum[1], templ_sqsum_sum);
|
||||
else
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums),
|
||||
ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, scale,
|
||||
templ_sum[0], templ_sum[1], templ_sum[2], templ_sum[3], templ_sqsum_sum);
|
||||
}
|
||||
|
||||
size_t globalsize[2] = { result.cols, result.rows };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool ocl_matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method)
|
||||
{
|
||||
int cn = _img.channels();
|
||||
|
||||
if (cn == 3 || cn > 4)
|
||||
return false;
|
||||
|
||||
typedef bool (*Caller)(InputArray _img, InputArray _templ, OutputArray _result);
|
||||
|
||||
static const Caller callers[] =
|
||||
{
|
||||
matchTemplateNaive_SQDIFF, matchTemplate_SQDIFF_NORMED, matchTemplateNaive_CCORR,
|
||||
matchTemplate_CCORR_NORMED, matchTemplate_CCOEFF, matchTemplate_CCOEFF_NORMED
|
||||
};
|
||||
const Caller caller = callers[method];
|
||||
|
||||
return caller(_img, _templ, _result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void crossCorr( const Mat& img, const Mat& _templ, Mat& corr,
|
||||
Size corrsize, int ctype,
|
||||
Point anchor, double delta, int borderType )
|
||||
@@ -226,14 +523,23 @@ void crossCorr( const Mat& img, const Mat& _templ, Mat& corr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************************/
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method )
|
||||
{
|
||||
CV_Assert( CV_TM_SQDIFF <= method && method <= CV_TM_CCOEFF_NORMED );
|
||||
CV_Assert( (_img.depth() == CV_8U || _img.depth() == CV_32F) && _img.type() == _templ.type() && _img.dims() <= 2 );
|
||||
|
||||
bool needswap = _img.size().height < _templ.size().height || _img.size().width < _templ.size().width;
|
||||
if (needswap)
|
||||
{
|
||||
CV_Assert(_img.size().height <= _templ.size().height && _img.size().width <= _templ.size().width);
|
||||
}
|
||||
|
||||
CV_OCL_RUN(_img.dims() <= 2 && _result.isUMat(),
|
||||
(!needswap ? ocl_matchTemplate(_img, _templ, _result, method) : ocl_matchTemplate(_templ, _img, _result, method)))
|
||||
|
||||
int numType = method == CV_TM_CCORR || method == CV_TM_CCORR_NORMED ? 0 :
|
||||
method == CV_TM_CCOEFF || method == CV_TM_CCOEFF_NORMED ? 1 : 2;
|
||||
@@ -242,14 +548,9 @@ void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result,
|
||||
method == CV_TM_CCOEFF_NORMED;
|
||||
|
||||
Mat img = _img.getMat(), templ = _templ.getMat();
|
||||
if( img.rows < templ.rows || img.cols < templ.cols )
|
||||
if (needswap)
|
||||
std::swap(img, templ);
|
||||
|
||||
CV_Assert( (img.depth() == CV_8U || img.depth() == CV_32F) &&
|
||||
img.type() == templ.type() );
|
||||
|
||||
CV_Assert( img.rows >= templ.rows && img.cols >= templ.cols);
|
||||
|
||||
Size corrSize(img.cols - templ.cols + 1, img.rows - templ.rows + 1);
|
||||
_result.create(corrSize, CV_32F);
|
||||
Mat result = _result.getMat();
|
||||
|
||||
@@ -706,6 +706,8 @@ private:
|
||||
int thresholdType;
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_threshold( InputArray _src, OutputArray _dst, double & thresh, double maxval, int thresh_type )
|
||||
{
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), ktype = CV_MAKE_TYPE(depth, 1);
|
||||
@@ -739,13 +741,14 @@ static bool ocl_threshold( InputArray _src, OutputArray _dst, double & thresh, d
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double maxval, int type )
|
||||
{
|
||||
if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() &&
|
||||
ocl_threshold(_src, _dst, thresh, maxval, type))
|
||||
return thresh;
|
||||
CV_OCL_RUN_(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_threshold(_src, _dst, thresh, maxval, type), thresh)
|
||||
|
||||
Mat src = _src.getMat();
|
||||
bool use_otsu = (type & THRESH_OTSU) != 0;
|
||||
|
||||
Reference in New Issue
Block a user