improved cv::matchTemplate OpenCL part
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#define CV_OPENCL_RUN_ASSERT
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
////////////////////////////////////////////////// matchTemplate //////////////////////////////////////////////////////////
|
||||
@@ -49,80 +50,87 @@ namespace cv
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool useNaive(int method, int depth, const Size & size)
|
||||
{
|
||||
#ifdef HAVE_CLAMDFFT
|
||||
if (method == TM_SQDIFF && depth == CV_32F)
|
||||
return true;
|
||||
else if(method == TM_CCORR || (method == TM_SQDIFF && depth == CV_8U))
|
||||
return size.height < 18 && size.width < 18;
|
||||
else
|
||||
return false;
|
||||
#else
|
||||
(void)(method);
|
||||
(void)(depth);
|
||||
(void)(size);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////// CCORR //////////////////////////////////////////////////////////////
|
||||
|
||||
enum
|
||||
{
|
||||
SUM_1 = 0, SUM_2 = 1
|
||||
};
|
||||
|
||||
static bool sumTemplate(InputArray _templ, UMat & result, int sum_type)
|
||||
{
|
||||
CV_Assert(sum_type == SUM_1 || sum_type == SUM_2);
|
||||
|
||||
int type = _templ.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
int wdepth = std::max(CV_32S, depth), wtype = CV_MAKE_TYPE(wdepth, cn);
|
||||
|
||||
char cvt[40];
|
||||
const char * const sumTypeToStr[] = { "SUM_1", "SUM_2" };
|
||||
ocl::Kernel k("calcSum", ocl::imgproc::match_template_oclsrc,
|
||||
format("-D CALC_SUM -D %s -D T=%s -D WT=%s -D convertToWT=%s -D cn=%d -D wdepth=%d",
|
||||
sumTypeToStr[sum_type], ocl::typeToStr(type), ocl::typeToStr(wtype),
|
||||
ocl::convertTypeStr(depth, wdepth, cn, cvt), cn, wdepth));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
result.create(1, 1, CV_32FC1);
|
||||
UMat templ = _templ.getUMat();
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::PtrWriteOnly(result));
|
||||
|
||||
return k.runTask(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 type=%s -D elem_type=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn));
|
||||
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_32F);
|
||||
_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.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ),
|
||||
ocl::KernelArg::WriteOnly(result)).run(2, globalsize, NULL, false);
|
||||
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(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
int type = _image.type(), cn = CV_MAT_CN(type);
|
||||
|
||||
ocl::Kernel k("matchTemplate_CCORR_NORMED", ocl::imgproc::match_template_oclsrc,
|
||||
format("-D type=%s -D elem_type=%s -D cn=%d", ocl::typeToStr(type),
|
||||
ocl::typeToStr(depth), cn));
|
||||
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_32F);
|
||||
_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 temp;
|
||||
multiply(templ, templ, temp, 1, CV_32F);
|
||||
Scalar s = sum(temp);
|
||||
float templ_sqsum = 0;
|
||||
for (int i = 0; i < cn; ++i)
|
||||
templ_sqsum += static_cast<float>(s[i]);
|
||||
UMat templ_sqsum;
|
||||
if (!sumTemplate(templ, templ_sqsum, SUM_2))
|
||||
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.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::ReadWrite(result),
|
||||
templ.rows, templ.cols, templ_sqsum).run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
static bool matchTemplate_CCORR(InputArray _image, InputArray _templ, OutputArray _result)
|
||||
{
|
||||
if (useNaive(TM_CCORR, _image.depth(), _templ.size()) )
|
||||
return matchTemplateNaive_CCORR(_image, _templ, _result);
|
||||
else
|
||||
return false;
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
////////////////////////////////////// SQDIFF //////////////////////////////////////////////////////////////
|
||||
@@ -130,10 +138,12 @@ static bool matchTemplate_CCORR(InputArray _image, InputArray _templ, OutputArra
|
||||
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 type=%s -D elem_type=%s -D cn=%d", ocl::typeToStr(type),
|
||||
ocl::typeToStr(depth), cn));
|
||||
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;
|
||||
|
||||
@@ -141,20 +151,21 @@ static bool matchTemplateNaive_SQDIFF(InputArray _image, InputArray _templ, Outp
|
||||
_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.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ),
|
||||
ocl::KernelArg::WriteOnly(result)).run(2, globalsize, NULL, false);
|
||||
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(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
int type = _image.type(), cn = CV_MAT_CN(type);
|
||||
|
||||
ocl::Kernel k("matchTemplate_SQDIFF_NORMED", ocl::imgproc::match_template_oclsrc,
|
||||
format("-D type=%s -D elem_type=%s -D cn=%d",
|
||||
ocl::typeToStr(type), ocl::typeToStr(depth), cn));
|
||||
format("-D SQDIFF_NORMED -D T=%s -D cn=%d", ocl::typeToStr(type), cn));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
@@ -165,24 +176,15 @@ static bool matchTemplate_SQDIFF_NORMED(InputArray _image, InputArray _templ, Ou
|
||||
UMat image_sums, image_sqsums;
|
||||
integral(image.reshape(1), image_sums, image_sqsums, CV_32F, CV_32F);
|
||||
|
||||
UMat temp;
|
||||
multiply(templ, templ, temp, 1, CV_32F);
|
||||
Scalar s = sum(temp);
|
||||
float templ_sqsum = 0;
|
||||
for (int i = 0; i < cn; ++i)
|
||||
templ_sqsum += (float)s[i];
|
||||
UMat templ_sqsum;
|
||||
if (!sumTemplate(_templ, templ_sqsum, SUM_2))
|
||||
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.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::ReadWrite(result),
|
||||
templ.rows, templ.cols, templ_sqsum).run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
static bool matchTemplate_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result)
|
||||
{
|
||||
if (useNaive(TM_SQDIFF, _image.depth(), _templ.size()))
|
||||
return matchTemplateNaive_SQDIFF(_image, _templ, _result);
|
||||
else
|
||||
return false;
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
///////////////////////////////////// CCOEFF /////////////////////////////////////////////////////////////////
|
||||
@@ -194,15 +196,15 @@ static bool matchTemplate_CCOEFF(InputArray _image, InputArray _templ, OutputArr
|
||||
UMat image_sums, temp;
|
||||
integral(_image, temp);
|
||||
|
||||
if(temp.depth() == CV_64F)
|
||||
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(cv::format("matchTemplate_Prepared_CCOEFF_C%d", cn).c_str(), ocl::imgproc::match_template_oclsrc,
|
||||
format("-D type=%s -D elem_type=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn));
|
||||
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;
|
||||
|
||||
@@ -211,25 +213,28 @@ static bool matchTemplate_CCOEFF(InputArray _image, InputArray _templ, OutputArr
|
||||
_result.create(size.height - templ.rows + 1, size.width - templ.cols + 1, CV_32F);
|
||||
UMat result = _result.getUMat();
|
||||
|
||||
size_t globalsize[2] = { result.cols, result.rows };
|
||||
|
||||
if (cn == 1)
|
||||
{
|
||||
float templ_sum = static_cast<float>(sum(_templ)[0]) / tsize.area();
|
||||
return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadWrite(result),
|
||||
templ.rows, templ.cols, templ_sum).run(2, globalsize, NULL, false);
|
||||
|
||||
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)
|
||||
return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols,
|
||||
templ_sum[0], templ_sum[1]).run(2, globalsize, NULL, false);
|
||||
|
||||
return 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]).run(2, globalsize, NULL, false);
|
||||
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)
|
||||
@@ -241,8 +246,8 @@ static bool matchTemplate_CCOEFF_NORMED(InputArray _image, InputArray _templ, Ou
|
||||
|
||||
int type = image_sums.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
|
||||
ocl::Kernel k(format("matchTemplate_CCOEFF_NORMED_C%d", cn).c_str(), ocl::imgproc::match_template_oclsrc,
|
||||
format("-D type=%s -D elem_type=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn));
|
||||
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;
|
||||
|
||||
@@ -251,7 +256,6 @@ static bool matchTemplate_CCOEFF_NORMED(InputArray _image, InputArray _templ, Ou
|
||||
_result.create(size.height - templ.rows + 1, size.width - templ.cols + 1, CV_32F);
|
||||
UMat result = _result.getUMat();
|
||||
|
||||
size_t globalsize[2] = { result.cols, result.rows };
|
||||
float scale = 1.f / tsize.area();
|
||||
|
||||
if (cn == 1)
|
||||
@@ -270,9 +274,8 @@ static bool matchTemplate_CCOEFF_NORMED(InputArray _image, InputArray _templ, Ou
|
||||
return true;
|
||||
}
|
||||
|
||||
return 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)
|
||||
.run(2,globalsize,NULL,false);
|
||||
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
|
||||
{
|
||||
@@ -295,15 +298,17 @@ static bool matchTemplate_CCOEFF_NORMED(InputArray _image, InputArray _templ, Ou
|
||||
}
|
||||
|
||||
if (cn == 2)
|
||||
return 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).run(2, globalsize, NULL, false);
|
||||
|
||||
return 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).run(2, globalsize, NULL, false);
|
||||
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);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -319,7 +324,7 @@ static bool ocl_matchTemplate( InputArray _img, InputArray _templ, OutputArray _
|
||||
|
||||
static const Caller callers[] =
|
||||
{
|
||||
matchTemplate_SQDIFF, matchTemplate_SQDIFF_NORMED, matchTemplate_CCORR,
|
||||
matchTemplateNaive_SQDIFF, matchTemplate_SQDIFF_NORMED, matchTemplateNaive_CCORR,
|
||||
matchTemplate_CCORR_NORMED, matchTemplate_CCOEFF, matchTemplate_CCOEFF_NORMED
|
||||
};
|
||||
const Caller caller = callers[method];
|
||||
|
Reference in New Issue
Block a user