From e51c0810b6bd6e5cdd934d172feb8b983bf7a407 Mon Sep 17 00:00:00 2001 From: Alexander Karsakov Date: Thu, 24 Jul 2014 13:11:58 +0400 Subject: [PATCH] Added accuracy and performance tests for DFT all modes. --- modules/core/perf/opencl/perf_dxt.cpp | 37 +++++++++++---- modules/core/test/ocl/test_dft.cpp | 65 ++++++++++++++++++--------- 2 files changed, 73 insertions(+), 29 deletions(-) diff --git a/modules/core/perf/opencl/perf_dxt.cpp b/modules/core/perf/opencl/perf_dxt.cpp index d0219913b..c0e41485e 100644 --- a/modules/core/perf/opencl/perf_dxt.cpp +++ b/modules/core/perf/opencl/perf_dxt.cpp @@ -54,23 +54,42 @@ namespace ocl { ///////////// dft //////////////////////// -typedef tuple DftParams; +enum OCL_FFT_TYPE +{ + R2R = 0, + C2R = 1, + R2C = 2, + C2C = 3 +}; + +typedef tuple DftParams; typedef TestBaseWithParam DftFixture; -OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3), - Values((int)DFT_ROWS, (int)DFT_SCALE, (int)DFT_INVERSE, - (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE))) +OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(C2C, R2R, C2R, R2C), + Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3, Size(512, 512), Size(1024, 1024), Size(2048, 2048)), + Values((int) 0, (int)DFT_ROWS, (int)DFT_SCALE, (int)DFT_INVERSE, + (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE))) { const DftParams params = GetParam(); - const Size srcSize = get<0>(params); - const int flags = get<1>(params); + const int dft_type = get<0>(params); + const Size srcSize = get<1>(params); + int flags = get<2>(params); - UMat src(srcSize, CV_32FC2), dst(srcSize, CV_32FC2); + int in_cn, out_cn; + switch (dft_type) + { + case R2R: flags |= cv::DFT_REAL_OUTPUT; in_cn = 1; out_cn = 1; break; + case C2R: flags |= cv::DFT_REAL_OUTPUT; in_cn = 2; out_cn = 2; break; + case R2C: flags |= cv::DFT_COMPLEX_OUTPUT; in_cn = 1; out_cn = 2; break; + case C2C: flags |= cv::DFT_COMPLEX_OUTPUT; in_cn = 2; out_cn = 2; break; + } + + UMat src(srcSize, CV_MAKE_TYPE(CV_32F, in_cn)), dst(srcSize, CV_MAKE_TYPE(CV_32F, out_cn)); declare.in(src, WARMUP_RNG).out(dst); - OCL_TEST_CYCLE() cv::dft(src, dst, flags | DFT_COMPLEX_OUTPUT); + OCL_TEST_CYCLE() cv::dft(src, dst, flags); - SANITY_CHECK(dst, 1e-3); + SANITY_CHECK(dst, 1e-5, ERROR_RELATIVE); } ///////////// MulSpectrums //////////////////////// diff --git a/modules/core/test/ocl/test_dft.cpp b/modules/core/test/ocl/test_dft.cpp index 1f0e43b20..cd0c1f07d 100644 --- a/modules/core/test/ocl/test_dft.cpp +++ b/modules/core/test/ocl/test_dft.cpp @@ -48,17 +48,26 @@ #ifdef HAVE_OPENCL +enum OCL_FFT_TYPE +{ + R2R = 0, + C2R = 1, + R2C = 2, + C2C = 3 +}; + namespace cvtest { namespace ocl { //////////////////////////////////////////////////////////////////////////// // Dft -PARAM_TEST_CASE(Dft, cv::Size, MatDepth, bool, bool, bool, bool) +PARAM_TEST_CASE(Dft, cv::Size, OCL_FFT_TYPE, bool, bool, bool, bool) { cv::Size dft_size; - int dft_flags, depth; - bool inplace; + int dft_flags, depth, cn, dft_type; + bool hint; + bool is1d; TEST_DECLARE_INPUT_PARAMETER(src); TEST_DECLARE_OUTPUT_PARAMETER(dst); @@ -66,34 +75,50 @@ PARAM_TEST_CASE(Dft, cv::Size, MatDepth, bool, bool, bool, bool) virtual void SetUp() { dft_size = GET_PARAM(0); - depth = GET_PARAM(1); - inplace = GET_PARAM(2); + dft_type = GET_PARAM(1); + depth = CV_32F; dft_flags = 0; + switch (dft_type) + { + case R2R: dft_flags |= cv::DFT_REAL_OUTPUT; cn = 1; break; + case C2R: dft_flags |= cv::DFT_REAL_OUTPUT; cn = 2; break; + case R2C: dft_flags |= cv::DFT_COMPLEX_OUTPUT; cn = 1; break; + case C2C: dft_flags |= cv::DFT_COMPLEX_OUTPUT; cn = 2; break; + } + + if (GET_PARAM(2)) + dft_flags |= cv::DFT_INVERSE; if (GET_PARAM(3)) dft_flags |= cv::DFT_ROWS; if (GET_PARAM(4)) dft_flags |= cv::DFT_SCALE; - if (GET_PARAM(5)) - dft_flags |= cv::DFT_INVERSE; + hint = GET_PARAM(5); + is1d = (dft_flags & DFT_ROWS) != 0 || dft_size.height == 1; } - void generateTestData(int cn = 2) + void generateTestData() { src = randomMat(dft_size, CV_MAKE_TYPE(depth, cn), 0.0, 100.0); usrc = src.getUMat(ACCESS_READ); - - if (inplace) - dst = src, udst = usrc; } }; -OCL_TEST_P(Dft, C2C) +OCL_TEST_P(Dft, Mat) { generateTestData(); - OCL_OFF(cv::dft(src, dst, dft_flags | cv::DFT_COMPLEX_OUTPUT)); - OCL_ON(cv::dft(usrc, udst, dft_flags | cv::DFT_COMPLEX_OUTPUT)); + int nonzero_rows = hint ? src.cols - randomInt(1, src.rows-1) : 0; + OCL_OFF(cv::dft(src, dst, dft_flags, nonzero_rows)); + OCL_ON(cv::dft(usrc, udst, dft_flags, nonzero_rows)); + + // In case forward R2C 1d tranform dst contains only half of output + // without complex conjugate + if (dft_type == R2C && is1d && (dft_flags & cv::DFT_INVERSE) == 0) + { + dst = dst(cv::Range(0, dst.rows), cv::Range(0, dst.cols/2 + 1)); + udst = udst(cv::Range(0, udst.rows), cv::Range(0, udst.cols/2 + 1)); + } double eps = src.size().area() * 1e-4; EXPECT_MAT_NEAR(dst, udst, eps); @@ -150,15 +175,15 @@ OCL_TEST_P(MulSpectrums, Mat) OCL_INSTANTIATE_TEST_CASE_P(OCL_ImgProc, MulSpectrums, testing::Combine(Bool(), Bool())); -OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(2, 3), cv::Size(5, 4), cv::Size(25, 20), - cv::Size(512, 1), cv::Size(1024, 768)), - Values(CV_32F, CV_64F), - Bool(), // inplace +OCL_INSTANTIATE_TEST_CASE_P(Core, Dft, Combine(Values(cv::Size(10, 10), cv::Size(36, 36), cv::Size(512, 1), cv::Size(1280, 768)), + Values((OCL_FFT_TYPE) R2C, (OCL_FFT_TYPE) C2C, (OCL_FFT_TYPE) R2R, (OCL_FFT_TYPE) C2R), + Bool(), // DFT_INVERSE Bool(), // DFT_ROWS Bool(), // DFT_SCALE - Bool()) // DFT_INVERSE + Bool() // hint + ) ); } } // namespace cvtest::ocl -#endif // HAVE_OPENCL +#endif // HAVE_OPENCL \ No newline at end of file