diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index 8276ffddb..cc26b3eb3 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -485,6 +485,7 @@ void repeat(InputArray _src, int ny, int nx, OutputArray _dst) { Mat src = _src.getMat(); CV_Assert( src.dims <= 2 ); + CV_Assert( ny > 0 && nx > 0 ); _dst.create(src.rows*ny, src.cols*nx, src.type()); Mat dst = _dst.getMat(); diff --git a/modules/ocl/include/opencv2/ocl/ocl.hpp b/modules/ocl/include/opencv2/ocl/ocl.hpp index af24f0aca..601885303 100644 --- a/modules/ocl/include/opencv2/ocl/ocl.hpp +++ b/modules/ocl/include/opencv2/ocl/ocl.hpp @@ -631,6 +631,9 @@ namespace cv //! initializes a scaled identity matrix CV_EXPORTS void setIdentity(oclMat& src, const Scalar & val = Scalar(1)); + //! fills the output array with repeated copies of the input array + CV_EXPORTS void repeat(const oclMat & src, int ny, int nx, oclMat & dst); + //////////////////////////////// Filter Engine //////////////////////////////// /*! diff --git a/modules/ocl/perf/perf_arithm.cpp b/modules/ocl/perf/perf_arithm.cpp index d71901e89..24eab3b91 100644 --- a/modules/ocl/perf/perf_arithm.cpp +++ b/modules/ocl/perf/perf_arithm.cpp @@ -1051,3 +1051,40 @@ PERF_TEST_P(AbsFixture, Abs, else OCL_PERF_ELSE } + +///////////// Repeat //////////////////////// + +typedef Size_MatType RepeatFixture; + +PERF_TEST_P(RepeatFixture, Repeat, + ::testing::Combine(::testing::Values(OCL_SIZE_1000, OCL_SIZE_2000), + OCL_PERF_ENUM(CV_8UC1, CV_8UC4, CV_32FC1, CV_32FC4))) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params); + const int nx = 3, ny = 2; + const Size dstSize(srcSize.width * nx, srcSize.height * ny); + + Mat src(srcSize, type), dst(dstSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + if (RUN_OCL_IMPL) + { + ocl::oclMat oclSrc(src), oclDst(dstSize, type); + + OCL_TEST_CYCLE() cv::ocl::repeat(oclSrc, ny, nx, oclDst); + + oclDst.download(dst); + + SANITY_CHECK(dst); + } + else if (RUN_PLAIN_IMPL) + { + TEST_CYCLE() cv::repeat(src, ny, nx, dst); + + SANITY_CHECK(dst); + } + else + OCL_PERF_ELSE +} diff --git a/modules/ocl/src/arithm.cpp b/modules/ocl/src/arithm.cpp index 9b24b16b0..f8a069082 100644 --- a/modules/ocl/src/arithm.cpp +++ b/modules/ocl/src/arithm.cpp @@ -1706,3 +1706,21 @@ void cv::ocl::setIdentity(oclMat& src, const Scalar & scalar) openCLExecuteKernel(src.clCxt, &arithm_setidentity, "setIdentity", global_threads, local_threads, args, -1, -1, buildOptions.c_str()); } + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////// Repeat //////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +void cv::ocl::repeat(const oclMat & src, int ny, int nx, oclMat & dst) +{ + CV_Assert(nx > 0 && ny > 0); + dst.create(src.rows * ny, src.cols * nx, src.type()); + + for (int y = 0; y < ny; ++y) + for (int x = 0; x < nx; ++x) + { + Rect roi(x * src.cols, y * src.rows, src.cols, src.rows); + oclMat hdr = dst(roi); + src.copyTo(hdr); + } +} diff --git a/modules/ocl/test/test_arithm.cpp b/modules/ocl/test/test_arithm.cpp index 11b945c5b..17260580d 100644 --- a/modules/ocl/test/test_arithm.cpp +++ b/modules/ocl/test/test_arithm.cpp @@ -192,13 +192,13 @@ PARAM_TEST_CASE(ArithmTestBase, MatDepth, Channels, bool) use_roi = GET_PARAM(2); } - void random_roi() + virtual void random_roi() { const int type = CV_MAKE_TYPE(depth, cn); Size roiSize = randomSize(1, MAX_VALUE); - Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(src1, src1_roi, roiSize, srcBorder, type, 2, 11); + Border src1Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src1, src1_roi, roiSize, src1Border, type, 2, 11); Border src2Border = randomBorder(0, use_roi ? MAX_VALUE : 0); randomSubMat(src2, src2_roi, roiSize, src2Border, type, -1540, 1740); @@ -214,7 +214,7 @@ PARAM_TEST_CASE(ArithmTestBase, MatDepth, Channels, bool) cv::threshold(mask, mask, 0.5, 255., CV_8UC1); - generateOclMat(gsrc1_whole, gsrc1_roi, src1, roiSize, srcBorder); + generateOclMat(gsrc1_whole, gsrc1_roi, src1, roiSize, src1Border); generateOclMat(gsrc2_whole, gsrc2_roi, src2, roiSize, src2Border); generateOclMat(gdst1_whole, gdst1_roi, dst1, roiSize, dst1Border); generateOclMat(gdst2_whole, gdst2_roi, dst2, roiSize, dst2Border); @@ -1522,6 +1522,48 @@ OCL_TEST_P(Norm, NORM_L2) } } +//// Repeat + +struct RepeatTestCase : + public ArithmTestBase +{ + int nx, ny; + + virtual void random_roi() + { + const int type = CV_MAKE_TYPE(depth, cn); + + nx = randomInt(1, 4); + ny = randomInt(1, 4); + + Size srcRoiSize = randomSize(1, MAX_VALUE); + Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src1, src1_roi, srcRoiSize, srcBorder, type, 2, 11); + + Size dstRoiSize(srcRoiSize.width * nx, srcRoiSize.height * ny); + Border dst1Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst1, dst1_roi, dstRoiSize, dst1Border, type, 5, 16); + + generateOclMat(gsrc1_whole, gsrc1_roi, src1, srcRoiSize, srcBorder); + generateOclMat(gdst1_whole, gdst1_roi, dst1, dstRoiSize, dst1Border); + } +}; + +typedef RepeatTestCase Repeat; + +OCL_TEST_P(Repeat, Mat) +{ + for (int i = 0; i < LOOP_TIMES; ++i) + { + random_roi(); + + cv::repeat(src1_roi, ny, nx, dst1_roi); + cv::ocl::repeat(gsrc1_roi, ny, nx, gdst1_roi); + + Near(); + } +} + //////////////////////////////////////// Instantiation ///////////////////////////////////////// INSTANTIATE_TEST_CASE_P(Arithm, Lut, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool(), Bool())); @@ -1557,5 +1599,6 @@ INSTANTIATE_TEST_CASE_P(Arithm, AddWeighted, Combine(Values(CV_8U, CV_8S, CV_16U INSTANTIATE_TEST_CASE_P(Arithm, SetIdentity, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); INSTANTIATE_TEST_CASE_P(Arithm, MeanStdDev, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); INSTANTIATE_TEST_CASE_P(Arithm, Norm, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); +INSTANTIATE_TEST_CASE_P(Arithm, Repeat, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); #endif // HAVE_OPENCL