diff --git a/modules/core/perf/opencl/perf_channels.cpp b/modules/core/perf/opencl/perf_channels.cpp index 4856ed4c39..3a25bc3094 100644 --- a/modules/core/perf/opencl/perf_channels.cpp +++ b/modules/core/perf/opencl/perf_channels.cpp @@ -154,6 +154,50 @@ OCL_PERF_TEST_P(MixChannelsFixture, MixChannels, SANITY_CHECK(dst1); } +///////////// InsertChannel //////////////////////// + +typedef Size_MatDepth InsertChannelFixture; + +OCL_PERF_TEST_P(InsertChannelFixture, InsertChannel, + ::testing::Combine(Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3), + OCL_PERF_ENUM(CV_8U, CV_32F))) +{ + const Size_MatDepth_t params = GetParam(); + const Size srcSize = get<0>(params); + const int depth = get<1>(params), type = CV_MAKE_TYPE(depth, 3); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, depth), dst(srcSize, type, Scalar::all(17)); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::insertChannel(src, dst, 1); + + SANITY_CHECK(dst); +} + +///////////// ExtractChannel //////////////////////// + +typedef Size_MatDepth ExtractChannelFixture; + +OCL_PERF_TEST_P(ExtractChannelFixture, ExtractChannel, + ::testing::Combine(Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3), + OCL_PERF_ENUM(CV_8U, CV_32F))) +{ + const Size_MatDepth_t params = GetParam(); + const Size srcSize = get<0>(params); + const int depth = get<1>(params), type = CV_MAKE_TYPE(depth, 3); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type), dst(srcSize, depth); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::extractChannel(src, dst, 1); + + SANITY_CHECK(dst); +} + } } // namespace cvtest::ocl #endif // HAVE_OPENCL diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 9778da18e7..4558d09d94 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -763,20 +763,41 @@ void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, void cv::extractChannel(InputArray _src, OutputArray _dst, int coi) { - Mat src = _src.getMat(); - CV_Assert( 0 <= coi && coi < src.channels() ); - _dst.create(src.dims, &src.size[0], src.depth()); - Mat dst = _dst.getMat(); + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + CV_Assert( 0 <= coi && coi < cn ); int ch[] = { coi, 0 }; + + if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat()) + { + UMat src = _src.getUMat(); + _dst.create(src.dims, &src.size[0], depth); + UMat dst = _dst.getUMat(); + mixChannels(std::vector(1, src), std::vector(1, dst), ch, 1); + return; + } + + Mat src = _src.getMat(); + _dst.create(src.dims, &src.size[0], depth); + Mat dst = _dst.getMat(); mixChannels(&src, 1, &dst, 1, ch, 1); } void cv::insertChannel(InputArray _src, InputOutputArray _dst, int coi) { - Mat src = _src.getMat(), dst = _dst.getMat(); - CV_Assert( src.size == dst.size && src.depth() == dst.depth() ); - CV_Assert( 0 <= coi && coi < dst.channels() && src.channels() == 1 ); + 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( _src.sameSize(_dst) && sdepth == ddepth ); + CV_Assert( 0 <= coi && coi < dcn && scn == 1 ); + int ch[] = { 0, coi }; + if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat()) + { + UMat src = _src.getUMat(), dst = _dst.getUMat(); + mixChannels(std::vector(1, src), std::vector(1, dst), ch, 1); + return; + } + + Mat src = _src.getMat(), dst = _dst.getMat(); mixChannels(&src, 1, &dst, 1, ch, 1); } diff --git a/modules/core/test/ocl/test_split_merge.cpp b/modules/core/test/ocl/test_channels.cpp similarity index 82% rename from modules/core/test/ocl/test_split_merge.cpp rename to modules/core/test/ocl/test_channels.cpp index d7fdcea7c7..09d709e911 100644 --- a/modules/core/test/ocl/test_split_merge.cpp +++ b/modules/core/test/ocl/test_channels.cpp @@ -353,11 +353,105 @@ OCL_TEST_P(MixChannels, Accuracy) } } +//////////////////////////////////////// InsertChannel /////////////////////////////////////////////// + +PARAM_TEST_CASE(InsertChannel, MatDepth, Channels, bool) +{ + int depth, cn, coi; + bool use_roi; + + TEST_DECLARE_INPUT_PARAMETER(src) + TEST_DECLARE_OUTPUT_PARAMETER(dst) + + virtual void SetUp() + { + depth = GET_PARAM(0); + cn = GET_PARAM(1); + use_roi = GET_PARAM(2); + } + + void generateTestData() + { + Size roiSize = randomSize(1, MAX_VALUE); + coi = randomInt(0, cn); + + Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, depth, 2, 11); + + Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst, dst_roi, roiSize, dstBorder, CV_MAKE_TYPE(depth, cn), 5, 16); + + UMAT_UPLOAD_INPUT_PARAMETER(src) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst) + } +}; + +OCL_TEST_P(InsertChannel, Accuracy) +{ + for(int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::insertChannel(src_roi, dst_roi, coi)); + OCL_ON(cv::insertChannel(usrc_roi, udst_roi, coi)); + + OCL_EXPECT_MATS_NEAR(dst, 0); + } +} + +//////////////////////////////////////// ExtractChannel /////////////////////////////////////////////// + +PARAM_TEST_CASE(ExtractChannel, MatDepth, Channels, bool) +{ + int depth, cn, coi; + bool use_roi; + + TEST_DECLARE_INPUT_PARAMETER(src) + TEST_DECLARE_OUTPUT_PARAMETER(dst) + + virtual void SetUp() + { + depth = GET_PARAM(0); + cn = GET_PARAM(1); + use_roi = GET_PARAM(2); + } + + void generateTestData() + { + Size roiSize = randomSize(1, MAX_VALUE); + coi = randomInt(0, cn); + + Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, CV_MAKE_TYPE(depth, cn), 2, 11); + + Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst, dst_roi, roiSize, dstBorder, depth, 5, 16); + + UMAT_UPLOAD_INPUT_PARAMETER(src) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst) + } +}; + +OCL_TEST_P(ExtractChannel, Accuracy) +{ + for(int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::extractChannel(src_roi, dst_roi, coi)); + OCL_ON(cv::extractChannel(usrc_roi, udst_roi, coi)); + + OCL_EXPECT_MATS_NEAR(dst, 0); + } +} + //////////////////////////////////////// Instantiation /////////////////////////////////////////////// OCL_INSTANTIATE_TEST_CASE_P(Channels, Merge, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Channels, Split, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Channels, MixChannels, Combine(OCL_ALL_DEPTHS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Channels, InsertChannel, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Channels, ExtractChannel, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); } } // namespace cvtest::ocl diff --git a/modules/ts/include/opencv2/ts/ts_perf.hpp b/modules/ts/include/opencv2/ts/ts_perf.hpp index fa0e5a2575..de674b7f37 100644 --- a/modules/ts/include/opencv2/ts/ts_perf.hpp +++ b/modules/ts/include/opencv2/ts/ts_perf.hpp @@ -379,6 +379,9 @@ template class TestBaseWithParam: public TestBase, public ::testing: typedef std::tr1::tuple Size_MatType_t; typedef TestBaseWithParam Size_MatType; +typedef std::tr1::tuple Size_MatDepth_t; +typedef TestBaseWithParam Size_MatDepth; + /*****************************************************************************************\ * Print functions for googletest * \*****************************************************************************************/