1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 00:03:03 +04:00

added cv::dft T-API test

This commit is contained in:
Ilya Lavrenov
2013-12-17 17:36:26 +04:00
parent bd91b39593
commit c8cbfe5382
10 changed files with 510 additions and 38 deletions
+42 -22
View File
@@ -48,43 +48,53 @@ using namespace cv;
using namespace cv::ocl;
#if !defined HAVE_CLAMDFFT
void cv::ocl::dft(const oclMat&, oclMat&, Size, int)
{
CV_Error(Error::OpenCLNoAMDBlasFft, "OpenCL DFT is not implemented");
}
namespace cv { namespace ocl {
void fft_teardown();
}}
void cv::ocl::fft_teardown(){}
} }
void cv::ocl::fft_teardown() { }
#else
#include "opencv2/core/opencl/runtime/opencl_clamdfft.hpp"
namespace cv
{
namespace ocl
{
void fft_setup();
void fft_teardown();
enum FftType
{
C2R = 1, // complex to complex
R2C = 2, // real to opencl HERMITIAN_INTERLEAVED
C2C = 3 // opencl HERMITIAN_INTERLEAVED to real
};
struct FftPlan
{
protected:
clAmdFftPlanHandle plHandle;
FftPlan& operator=(const FftPlan&);
public:
FftPlan(Size _dft_size, int _src_step, int _dst_step, int _flags, FftType _type);
FftPlan(Size _dft_size, int _src_step, int _dst_step, int _depth, int _flags, FftType _type);
~FftPlan();
inline clAmdFftPlanHandle getPlanHandle() { return plHandle; }
const Size dft_size;
const int src_step, dst_step;
const int depth;
const int flags;
const FftType type;
};
class PlanCache
{
protected:
@@ -105,10 +115,11 @@ namespace cv
planCache = new PlanCache();
return planCache;
}
// return a baked plan->
// if there is one matched plan, return it
// if not, bake a new one, put it into the planStore and return it.
static FftPlan* getPlan(Size _dft_size, int _src_step, int _dst_step, int _flags, FftType _type);
static FftPlan* getPlan(Size _dft_size, int _src_step, int _dst_step, int _depth, int _flags, FftType _type);
// remove a single plan from the store
// return true if the plan is successfully removed
@@ -117,6 +128,7 @@ namespace cv
};
}
}
PlanCache* PlanCache::planCache = NULL;
void cv::ocl::fft_setup()
@@ -128,9 +140,11 @@ void cv::ocl::fft_setup()
}
if (pCache.setupData == NULL)
pCache.setupData = new clAmdFftSetupData;
openCLSafeCall(clAmdFftInitSetupData( pCache.setupData ));
pCache.started = true;
}
void cv::ocl::fft_teardown()
{
PlanCache& pCache = *PlanCache::getPlanCache();
@@ -154,8 +168,8 @@ void cv::ocl::fft_teardown()
}
// bake a new plan
cv::ocl::FftPlan::FftPlan(Size _dft_size, int _src_step, int _dst_step, int _flags, FftType _type)
: plHandle(0), dft_size(_dft_size), src_step(_src_step), dst_step(_dst_step), flags(_flags), type(_type)
cv::ocl::FftPlan::FftPlan(Size _dft_size, int _src_step, int _dst_step, int _depth, int _flags, FftType _type)
: plHandle(0), dft_size(_dft_size), src_step(_src_step), depth(_depth), dst_step(_dst_step), flags(_flags), type(_type)
{
fft_setup();
@@ -184,20 +198,20 @@ cv::ocl::FftPlan::FftPlan(Size _dft_size, int _src_step, int _dst_step, int _fla
case C2C:
inLayout = CLFFT_COMPLEX_INTERLEAVED;
outLayout = CLFFT_COMPLEX_INTERLEAVED;
clStridesIn[1] = src_step / (2*sizeof(float));
clStridesOut[1] = clStridesIn[1];
clStridesIn[1] = src_step / (2*CV_ELEM_SIZE(_depth));
clStridesOut[1] = dst_step / (2*CV_ELEM_SIZE(_depth));
break;
case R2C:
inLayout = CLFFT_REAL;
outLayout = CLFFT_HERMITIAN_INTERLEAVED;
clStridesIn[1] = src_step / sizeof(float);
clStridesOut[1] = dst_step / (2*sizeof(float));
clStridesIn[1] = src_step / CV_ELEM_SIZE(_depth);
clStridesOut[1] = dst_step / (2*CV_ELEM_SIZE(_depth));
break;
case C2R:
inLayout = CLFFT_HERMITIAN_INTERLEAVED;
outLayout = CLFFT_REAL;
clStridesIn[1] = src_step / (2*sizeof(float));
clStridesOut[1] = dst_step / sizeof(float);
clStridesIn[1] = src_step / (2*CV_ELEM_SIZE(_depth));
clStridesOut[1] = dst_step / CV_ELEM_SIZE(_depth);
break;
default:
//std::runtime_error("does not support this convertion!");
@@ -211,6 +225,7 @@ cv::ocl::FftPlan::FftPlan(Size _dft_size, int _src_step, int _dst_step, int _fla
openCLSafeCall( clAmdFftCreateDefaultPlan( &plHandle, *(cl_context*)getClContextPtr(), dim, clLengthsIn ) );
openCLSafeCall( clAmdFftSetPlanPrecision( plHandle, depth == CV_64F ? CLFFT_DOUBLE : CLFFT_SINGLE ) );
openCLSafeCall( clAmdFftSetResultLocation( plHandle, CLFFT_OUTOFPLACE ) );
openCLSafeCall( clAmdFftSetLayout( plHandle, inLayout, outLayout ) );
openCLSafeCall( clAmdFftSetPlanBatchSize( plHandle, batchSize ) );
@@ -225,6 +240,7 @@ cv::ocl::FftPlan::FftPlan(Size _dft_size, int _src_step, int _dst_step, int _fla
//ready to bake
openCLSafeCall( clAmdFftBakePlan( plHandle, 1, (cl_command_queue*)getClCommandQueuePtr(), NULL, NULL ) );
}
cv::ocl::FftPlan::~FftPlan()
{
openCLSafeCall( clAmdFftDestroyPlan( &plHandle ) );
@@ -242,7 +258,7 @@ cv::ocl::PlanCache::~PlanCache()
fft_teardown();
}
FftPlan* cv::ocl::PlanCache::getPlan(Size _dft_size, int _src_step, int _dst_step, int _flags, FftType _type)
FftPlan* cv::ocl::PlanCache::getPlan(Size _dft_size, int _src_step, int _dst_step, int _depth, int _flags, FftType _type)
{
PlanCache& pCache = *PlanCache::getPlanCache();
std::vector<FftPlan *>& pStore = pCache.planStore;
@@ -256,6 +272,7 @@ FftPlan* cv::ocl::PlanCache::getPlan(Size _dft_size, int _src_step, int _dst_ste
plan->flags == _flags &&
plan->src_step == _src_step &&
plan->dst_step == _dst_step &&
plan->depth == _depth &&
plan->type == _type
)
{
@@ -263,7 +280,7 @@ FftPlan* cv::ocl::PlanCache::getPlan(Size _dft_size, int _src_step, int _dst_ste
}
}
// no baked plan is found
FftPlan *newPlan = new FftPlan(_dft_size, _src_step, _dst_step, _flags, _type);
FftPlan *newPlan = new FftPlan(_dft_size, _src_step, _dst_step, _depth, _flags, _type);
pStore.push_back(newPlan);
return newPlan;
}
@@ -286,6 +303,8 @@ bool cv::ocl::PlanCache::removePlan(clAmdFftPlanHandle plHandle)
void cv::ocl::dft(const oclMat &src, oclMat &dst, Size dft_size, int flags)
{
CV_Assert(cv::ocl::haveAmdFft());
if(dft_size == Size(0, 0))
{
dft_size = src.size();
@@ -296,9 +315,6 @@ void cv::ocl::dft(const oclMat &src, oclMat &dst, Size dft_size, int flags)
// the two flags are not compatible
CV_Assert( !((flags & DFT_SCALE) && (flags & DFT_ROWS)) );
// similar assertions with cuda module
CV_Assert(src.type() == CV_32F || src.type() == CV_32FC2);
//bool is_1d_input = (src.rows == 1);
//int is_row_dft = flags & DFT_ROWS;
//int is_scaled_dft = flags & DFT_SCALE;
@@ -306,6 +322,7 @@ void cv::ocl::dft(const oclMat &src, oclMat &dst, Size dft_size, int flags)
bool is_complex_input = src.channels() == 2;
bool is_complex_output = !(flags & DFT_REAL_OUTPUT);
int depth = src.depth();
// We don't support real-to-real transform
CV_Assert(is_complex_input || is_complex_output);
@@ -314,14 +331,17 @@ void cv::ocl::dft(const oclMat &src, oclMat &dst, Size dft_size, int flags)
switch(type)
{
case C2C:
dst.create(src.rows, src.cols, CV_32FC2);
dst.create(src.rows, src.cols, CV_MAKE_TYPE(depth, 2));
printf("C2C\n");
break;
case R2C:
dst.create(src.rows, src.cols / 2 + 1, CV_32FC2);
dst.create(src.rows, src.cols / 2 + 1, CV_MAKE_TYPE(depth, 2));
printf("R2C\n");
break;
case C2R:
CV_Assert(dft_size.width / 2 + 1 == src.cols && dft_size.height == src.rows);
dst.create(src.rows, dft_size.width, CV_32FC1);
dst.create(src.rows, dft_size.width, CV_MAKE_TYPE(depth, 1));
printf("C2R\n");
break;
default:
//std::runtime_error("does not support this convertion!");
@@ -329,7 +349,7 @@ void cv::ocl::dft(const oclMat &src, oclMat &dst, Size dft_size, int flags)
throw std::exception();
break;
}
clAmdFftPlanHandle plHandle = PlanCache::getPlan(dft_size, src.step, dst.step, flags, type)->getPlanHandle();
clAmdFftPlanHandle plHandle = PlanCache::getPlan(dft_size, src.step, dst.step, depth, flags, type)->getPlanHandle();
//get the buffersize
size_t buffersize = 0;
@@ -356,7 +376,7 @@ void cv::ocl::dft(const oclMat &src, oclMat &dst, Size dft_size, int flags)
{
openCLFree(clMedBuffer);
}
//fft_teardown();
fft_teardown();
}
#endif
+1
View File
@@ -75,6 +75,7 @@
#include "opencv2/core/utility.hpp"
#include "opencv2/core/private.hpp"
#include "opencv2/core/ocl.hpp"
#define __ATI__
+9 -5
View File
@@ -50,32 +50,36 @@ using namespace std;
////////////////////////////////////////////////////////////////////////////
// Dft
PARAM_TEST_CASE(Dft, cv::Size, int)
PARAM_TEST_CASE(Dft, cv::Size, int, bool)
{
cv::Size dft_size;
int dft_flags;
bool doubleFP;
virtual void SetUp()
{
dft_size = GET_PARAM(0);
dft_flags = GET_PARAM(1);
doubleFP = GET_PARAM(2);
}
};
OCL_TEST_P(Dft, C2C)
{
cv::Mat a = randomMat(dft_size, CV_32FC2, 0.0, 100.0);
cv::Mat a = randomMat(dft_size, doubleFP ? CV_64FC2 : CV_32FC2, 0.0, 100.0);
cv::Mat b_gold;
cv::ocl::oclMat d_b;
cv::dft(a, b_gold, dft_flags);
cv::ocl::dft(cv::ocl::oclMat(a), d_b, a.size(), dft_flags);
EXPECT_MAT_NEAR(b_gold, cv::Mat(d_b), a.size().area() * 1e-4);
}
OCL_TEST_P(Dft, R2C)
{
cv::Mat a = randomMat(dft_size, CV_32FC1, 0.0, 100.0);
cv::Mat a = randomMat(dft_size, doubleFP ? CV_64FC1 : CV_32FC1, 0.0, 100.0);
cv::Mat b_gold, b_gold_roi;
cv::ocl::oclMat d_b, d_c;
@@ -92,7 +96,7 @@ OCL_TEST_P(Dft, R2C)
OCL_TEST_P(Dft, R2CthenC2R)
{
cv::Mat a = randomMat(dft_size, CV_32FC1, 0.0, 10.0);
cv::Mat a = randomMat(dft_size, doubleFP ? CV_64FC1 : CV_32FC1, 0.0, 10.0);
cv::ocl::oclMat d_b, d_c;
cv::ocl::dft(cv::ocl::oclMat(a), d_b, a.size(), 0);
@@ -102,7 +106,7 @@ OCL_TEST_P(Dft, R2CthenC2R)
INSTANTIATE_TEST_CASE_P(OCL_ImgProc, Dft, testing::Combine(
testing::Values(cv::Size(2, 3), cv::Size(5, 4), cv::Size(25, 20), cv::Size(512, 1), cv::Size(1024, 768)),
testing::Values(0, (int)cv::DFT_ROWS, (int)cv::DFT_SCALE) ));
testing::Values(0, (int)cv::DFT_ROWS, (int)cv::DFT_SCALE), testing::Bool()));
////////////////////////////////////////////////////////////////////////////
// MulSpectrums