OCL_PERF_TEST_P(CompareFixture, Compare,
::testing::Combine(OCL_TEST_SIZES,
- OCL_TEST_TYPES, CmpCode::all()))
+ OCL_TEST_TYPES_134, CmpCode::all()))
{
const CompareParams params = GetParam();
const Size srcSize = get<0>(params);
checkDeviceMaxMemoryAllocSize(srcSize, type);
- UMat src1(srcSize, type), src2(srcSize, type), dst(srcSize, CV_8UC1);
+ UMat src1(srcSize, type), src2(srcSize, type), dst(srcSize, CV_8UC(CV_MAT_CN(type)));
declare.in(src1, src2, WARMUP_RNG).out(dst);
OCL_TEST_CYCLE() cv::compare(src1, src2, dst, cmpCode);
SANITY_CHECK(dst);
}
+OCL_PERF_TEST_P(CompareFixture, CompareScalar,
+ ::testing::Combine(OCL_TEST_SIZES,
+ OCL_TEST_TYPES_134, CmpCode::all()))
+{
+ const CompareParams params = GetParam();
+ const Size srcSize = get<0>(params);
+ const int type = get<1>(params);
+ const int cmpCode = get<2>(params);
+
+ checkDeviceMaxMemoryAllocSize(srcSize, type);
+
+ UMat src1(srcSize, type), dst(srcSize, CV_8UC(CV_MAT_CN(type)));
+ declare.in(src1, WARMUP_RNG).out(dst);
+
+ OCL_TEST_CYCLE() cv::compare(src1, 32, dst, cmpCode);
+
+ SANITY_CHECK(dst);
+}
+
///////////// pow ////////////////////////
typedef Size_MatType PowFixture;
#ifdef HAVE_OPENCL
-static bool ocl_compare(InputArray _src1, InputArray _src2, OutputArray _dst, int op)
+static bool ocl_compare(InputArray _src1, InputArray _src2, OutputArray _dst, int op, bool haveScalar)
{
- if ( !((_src1.isMat() || _src1.isUMat()) && (_src2.isMat() || _src2.isUMat())) )
- return false;
-
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
- int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), type2 = _src2.type();
- if ( (!doubleSupport && (depth == CV_64F || _src2.depth() == CV_64F)) ||
- !_src1.sameSize(_src2) || type != type2)
+ int type1 = _src1.type(), depth1 = CV_MAT_DEPTH(type1), cn = CV_MAT_CN(type1);
+ int type2 = _src2.type();
+
+ if (!haveScalar)
+ {
+ if ( (!doubleSupport && (depth1 == CV_64F || _src2.depth() == CV_64F)) ||
+ !_src1.sameSize(_src2) || type1 != type2)
+ return false;
+ }
+ else
+ {
+ if (cn > 1 || depth1 <= CV_32S) // FIXIT: if (cn > 4): Need to clear CPU-based compare behavior
+ return false;
+ }
+
+ if (!doubleSupport && depth1 == CV_64F)
return false;
- int kercn = ocl::predictOptimalVectorWidth(_src1, _src2, _dst);
+ int kercn = haveScalar ? cn : ocl::predictOptimalVectorWidth(_src1, _src2, _dst);
+ int scalarcn = kercn == 3 ? 4 : kercn;
+
const char * const operationMap[] = { "==", ">", ">=", "<", "<=", "!=" };
char cvt[40];
- ocl::Kernel k("KF", ocl::core::arithm_oclsrc,
- format("-D BINARY_OP -D srcT1=%s -D dstT=%s -D workT=srcT1 -D cn=%d"
- " -D convertToDT=%s -D OP_CMP -D CMP_OPERATOR=%s%s -D srcT1_C1=%s"
- " -D srcT2_C1=%s -D dstT_C1=%s",
- ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)),
- ocl::typeToStr(CV_8UC(kercn)), kercn,
- ocl::convertTypeStr(depth, CV_8U, kercn, cvt),
- operationMap[op], doubleSupport ? " -D DOUBLE_SUPPORT" : "",
- ocl::typeToStr(depth), ocl::typeToStr(depth), ocl::typeToStr(CV_8U)));
+ String buildOptions = format(
+ "-D %s -D srcT1=%s -D dstT=%s -D workT=srcT1 -D cn=%d"
+ " -D convertToDT=%s -D OP_CMP -D CMP_OPERATOR=%s%s -D srcT1_C1=%s"
+ " -D srcT2_C1=%s -D dstT_C1=%s -D workST=%s%s",
+ (haveScalar ? "UNARY_OP" : "BINARY_OP"),
+ ocl::typeToStr(CV_MAKE_TYPE(depth1, kercn)),
+ ocl::typeToStr(CV_8UC(kercn)), kercn,
+ ocl::convertTypeStr(depth1, CV_8U, kercn, cvt),
+ operationMap[op], doubleSupport ? " -D DOUBLE_SUPPORT" : "",
+ ocl::typeToStr(depth1), ocl::typeToStr(depth1), ocl::typeToStr(CV_8U),
+ ocl::typeToStr(CV_MAKE_TYPE(depth1, scalarcn)),
+ doubleSupport ? " -D DOUBLE_SUPPORT" : ""
+ );
+
+ ocl::Kernel k("KF", ocl::core::arithm_oclsrc, buildOptions);
if (k.empty())
return false;
- CV_Assert(type == type2);
- UMat src1 = _src1.getUMat(), src2 = _src2.getUMat();
+ UMat src1 = _src1.getUMat();
Size size = src1.size();
- CV_Assert(size == src2.size());
-
_dst.create(size, CV_8UC(cn));
UMat dst = _dst.getUMat();
- k.args(ocl::KernelArg::ReadOnlyNoSize(src1),
- ocl::KernelArg::ReadOnlyNoSize(src2),
- ocl::KernelArg::WriteOnly(dst, cn, kercn));
+ if (haveScalar)
+ {
+ size_t esz = CV_ELEM_SIZE1(type1)*scalarcn;
+ double buf[4]={0,0,0,0};
+ Mat src2sc = _src2.getMat();
+
+ if (!src2sc.empty())
+ convertAndUnrollScalar(src2sc, type1, (uchar*)buf, 1);
+
+ ocl::KernelArg scalararg = ocl::KernelArg(0, 0, 0, 0, buf, esz);
+
+ k.args(ocl::KernelArg::ReadOnlyNoSize(src1, cn, kercn),
+ ocl::KernelArg::WriteOnly(dst, cn, kercn),
+ scalararg);
+ }
+ else
+ {
+ CV_DbgAssert(type1 == type2);
+ UMat src2 = _src2.getUMat();
+ CV_DbgAssert(size == src2.size());
+
+ _dst.create(size, CV_8UC(cn));
+
+ k.args(ocl::KernelArg::ReadOnlyNoSize(src1),
+ ocl::KernelArg::ReadOnlyNoSize(src2),
+ ocl::KernelArg::WriteOnly(dst, cn, kercn));
+ }
size_t globalsize[2] = { dst.cols * cn / kercn, dst.rows };
return k.run(2, globalsize, NULL, false);
CV_Assert( op == CMP_LT || op == CMP_LE || op == CMP_EQ ||
op == CMP_NE || op == CMP_GE || op == CMP_GT );
+ bool haveScalar = false;
+
+ if ((_src1.isMatx() + _src2.isMatx()) == 1
+ || !_src1.sameSize(_src2)
+ || _src1.type() != _src2.type())
+ {
+ if (checkScalar(_src1, _src2.type(), _src1.kind(), _src2.kind()))
+ {
+ op = op == CMP_LT ? CMP_GT : op == CMP_LE ? CMP_GE :
+ op == CMP_GE ? CMP_LE : op == CMP_GT ? CMP_LT : op;
+ // src1 is a scalar; swap it with src2
+ compare(_src2, _src1, _dst, op);
+ return;
+ }
+ else if( !checkScalar(_src2, _src1.type(), _src2.kind(), _src1.kind()) )
+ CV_Error( CV_StsUnmatchedSizes,
+ "The operation is neither 'array op array' (where arrays have the same size and the same type), "
+ "nor 'array op scalar', nor 'scalar op array'" );
+ haveScalar = true;
+ }
+
CV_OCL_RUN(_src1.dims() <= 2 && _src2.dims() <= 2 && _dst.isUMat(),
- ocl_compare(_src1, _src2, _dst, op))
+ ocl_compare(_src1, _src2, _dst, op, haveScalar))
int kind1 = _src1.kind(), kind2 = _src2.kind();
Mat src1 = _src1.getMat(), src2 = _src2.getMat();
return;
}
- bool haveScalar = false;
-
- if( (kind1 == _InputArray::MATX) + (kind2 == _InputArray::MATX) == 1 ||
- src1.size != src2.size || src1.type() != src2.type() )
- {
- if( checkScalar(src1, src2.type(), kind1, kind2) )
- {
- // src1 is a scalar; swap it with src2
- swap(src1, src2);
- op = op == CMP_LT ? CMP_GT : op == CMP_LE ? CMP_GE :
- op == CMP_GE ? CMP_LE : op == CMP_GT ? CMP_LT : op;
- }
- else if( !checkScalar(src2, src1.type(), kind2, kind1) )
- CV_Error( CV_StsUnmatchedSizes,
- "The operation is neither 'array op array' (where arrays have the same size and the same type), "
- "nor 'array op scalar', nor 'scalar op array'" );
- haveScalar = true;
- }
-
-
int cn = src1.channels(), depth1 = src1.depth(), depth2 = src2.depth();
_dst.create(src1.dims, src1.size, CV_8UC(cn));
int cn;
bool use_roi;
cv::Scalar val;
+ cv::Scalar val_in_range;
TEST_DECLARE_INPUT_PARAMETER(src1)
TEST_DECLARE_INPUT_PARAMETER(src2)
{
const int type = CV_MAKE_TYPE(depth, cn);
+ double minV = getMinVal(type);
+ double maxV = getMaxVal(type);
+
Size roiSize = randomSize(1, MAX_VALUE);
Border src1Border = randomBorder(0, use_roi ? MAX_VALUE : 0);
- randomSubMat(src1, src1_roi, roiSize, src1Border, type, 2, 11);
+ randomSubMat(src1, src1_roi, roiSize, src1Border, type, minV, maxV);
Border src2Border = randomBorder(0, use_roi ? MAX_VALUE : 0);
- randomSubMat(src2, src2_roi, roiSize, src2Border, type, -1540, 1740);
+ randomSubMat(src2, src2_roi, roiSize, src2Border, type, std::max(-1540., minV), std::min(1740., maxV));
Border dst1Border = randomBorder(0, use_roi ? MAX_VALUE : 0);
randomSubMat(dst1, dst1_roi, roiSize, dst1Border, type, 5, 16);
val = cv::Scalar(rng.uniform(-100.0, 100.0), rng.uniform(-100.0, 100.0),
rng.uniform(-100.0, 100.0), rng.uniform(-100.0, 100.0));
+ val_in_range = cv::Scalar(rng.uniform(minV, maxV), rng.uniform(minV, maxV),
+ rng.uniform(minV, maxV), rng.uniform(minV, maxV));
+
UMAT_UPLOAD_INPUT_PARAMETER(src1)
UMAT_UPLOAD_INPUT_PARAMETER(src2)
UMAT_UPLOAD_INPUT_PARAMETER(mask)
typedef ArithmTestBase Compare;
+static const int cmp_codes[] = { CMP_EQ, CMP_GT, CMP_GE, CMP_LT, CMP_LE, CMP_NE };
+static const char* cmp_strs[] = { "CMP_EQ", "CMP_GT", "CMP_GE", "CMP_LT", "CMP_LE", "CMP_NE" };
+static const int cmp_num = sizeof(cmp_codes) / sizeof(int);
+
OCL_TEST_P(Compare, Mat)
{
- int cmp_codes[] = { CMP_EQ, CMP_GT, CMP_GE, CMP_LT, CMP_LE, CMP_NE };
- int cmp_num = sizeof(cmp_codes) / sizeof(int);
-
for (int i = 0; i < cmp_num; ++i)
+ {
+ SCOPED_TRACE(cmp_strs[i]);
for (int j = 0; j < test_loop_times; j++)
{
generateTestData();
Near(0);
}
+ }
+}
+
+OCL_TEST_P(Compare, Scalar)
+{
+ for (int i = 0; i < cmp_num; ++i)
+ {
+ SCOPED_TRACE(cmp_strs[i]);
+ for (int j = 0; j < test_loop_times; j++)
+ {
+ generateTestData();
+
+ OCL_OFF(cv::compare(src1_roi, val_in_range, dst1_roi, cmp_codes[i]));
+ OCL_ON(cv::compare(usrc1_roi, val_in_range, udst1_roi, cmp_codes[i]));
+
+ Near(0);
+ }
+ }
+}
+
+OCL_TEST_P(Compare, Scalar2)
+{
+ for (int i = 0; i < cmp_num; ++i)
+ {
+ SCOPED_TRACE(cmp_strs[i]);
+ for (int j = 0; j < test_loop_times; j++)
+ {
+ generateTestData();
+
+ OCL_OFF(cv::compare(val_in_range, src1_roi, dst1_roi, cmp_codes[i]));
+ OCL_ON(cv::compare(val_in_range, usrc1_roi, udst1_roi, cmp_codes[i]));
+
+ Near(0);
+ }
+ }
}
//////////////////////////////// Pow /////////////////////////////////////////////////