Commit 0318d277 authored by Alexander Karsakov's avatar Alexander Karsakov

Enabled precalculated wave

parent 5dd92638
...@@ -244,6 +244,7 @@ typedef signed char schar; ...@@ -244,6 +244,7 @@ typedef signed char schar;
/* fundamental constants */ /* fundamental constants */
#define CV_PI 3.1415926535897932384626433832795 #define CV_PI 3.1415926535897932384626433832795
#define CV_TWO_PI 6.283185307179586476925286766559
#define CV_LOG2 0.69314718055994530941723212145818 #define CV_LOG2 0.69314718055994530941723212145818
/****************************************************************************************\ /****************************************************************************************\
......
...@@ -57,8 +57,8 @@ namespace ocl { ...@@ -57,8 +57,8 @@ namespace ocl {
typedef tuple<Size, int> DftParams; typedef tuple<Size, int> DftParams;
typedef TestBaseWithParam<DftParams> DftFixture; typedef TestBaseWithParam<DftParams> DftFixture;
OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(/*OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3, */Size(1024, 1024), Size(1024, 2048), Size(512, 512), Size(2048, 2048)), OCL_PERF_TEST_P(DftFixture, Dft, ::testing::Combine(Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3, Size(1024, 1024), Size(1024, 2048), Size(512, 512), Size(2048, 2048)),
Values((int)DFT_ROWS/*, (int) 0/*, (int)DFT_SCALE, (int)DFT_INVERSE, Values((int)DFT_ROWS, (int) 0/*, (int)DFT_SCALE, (int)DFT_INVERSE,
(int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE*/))) (int)DFT_INVERSE | DFT_SCALE, (int)DFT_ROWS | DFT_INVERSE*/)))
{ {
const DftParams params = GetParam(); const DftParams params = GetParam();
......
...@@ -2034,26 +2034,6 @@ namespace cv ...@@ -2034,26 +2034,6 @@ namespace cv
#ifdef HAVE_OPENCL #ifdef HAVE_OPENCL
static bool fft_radixN(InputArray _src, OutputArray _dst, int radix, int block_size, int nonzero_rows, int flags)
{
int N = _src.size().width;
if (N % radix)
return false;
UMat src = _src.getUMat();
UMat dst = _dst.getUMat();
int thread_count = N / radix;
size_t globalsize[2] = { thread_count, nonzero_rows };
String kernel_name = format("fft_radix%d", radix);
ocl::Kernel k(kernel_name.c_str(), ocl::core::fft_oclsrc, (flags & DFT_INVERSE) != 0 ? "-D INVERSE" : "");
if (k.empty())
return false;
k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), block_size, thread_count, nonzero_rows);
return k.run(2, globalsize, NULL, false);
}
static bool ocl_packToCCS(InputArray _buffer, OutputArray _dst, int flags) static bool ocl_packToCCS(InputArray _buffer, OutputArray _dst, int flags)
{ {
UMat buffer = _buffer.getUMat(); UMat buffer = _buffer.getUMat();
...@@ -2098,24 +2078,18 @@ static bool ocl_packToCCS(InputArray _buffer, OutputArray _dst, int flags) ...@@ -2098,24 +2078,18 @@ static bool ocl_packToCCS(InputArray _buffer, OutputArray _dst, int flags)
return true; return true;
} }
static bool ocl_dft_C2C_row(InputArray _src, OutputArray _dst, int nonzero_rows, int flags) static std::vector<int> ocl_getRadixes(int cols, int& min_radix)
{ {
int type = _src.type(), depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
UMat src = _src.getUMat();
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
if (depth == CV_64F && !doubleSupport)
return false;
int factors[34]; int factors[34];
int nf = DFTFactorize( src.cols, factors ); int nf = DFTFactorize( cols, factors );
int n = 1; int n = 1;
int factor_index = 0; int factor_index = 0;
String radix_processing; // choose radix order
int min_radix = INT_MAX; std::vector<int> radixes;
// 1. 2^n transforms
// 2^n transforms
if ( (factors[factor_index] & 1) == 0 ) if ( (factors[factor_index] & 1) == 0 )
{ {
for( ; n < factors[factor_index]; ) for( ; n < factors[factor_index]; )
...@@ -2126,22 +2100,74 @@ static bool ocl_dft_C2C_row(InputArray _src, OutputArray _dst, int nonzero_rows, ...@@ -2126,22 +2100,74 @@ static bool ocl_dft_C2C_row(InputArray _src, OutputArray _dst, int nonzero_rows,
else if (4*n <= factors[0]) else if (4*n <= factors[0])
radix = 4; radix = 4;
radix_processing += format("fft_radix%d(smem,x,%d,%d);", radix, n, src.cols/radix); radixes.push_back(radix);
min_radix = min(radix, min_radix); min_radix = min(min_radix, radix);
n *= radix; n *= radix;
} }
factor_index++; factor_index++;
} }
// 2. all the other transforms // all the other transforms
for( ; factor_index < nf; factor_index++ ) for( ; factor_index < nf; factor_index++ )
{ {
int radix = factors[factor_index]; radixes.push_back(factors[factor_index]);
radix_processing += format("fft_radix%d(smem,x,%d,%d);", radix, n, src.cols/radix); min_radix = min(min_radix, factors[factor_index]);
min_radix = min(radix, min_radix); }
return radixes;
}
static bool ocl_dft_C2C_row(InputArray _src, OutputArray _dst, InputOutputArray _twiddles, int nonzero_rows, int flags)
{
int type = _src.type(), depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
UMat src = _src.getUMat();
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
if (depth == CV_64F && !doubleSupport)
return false;
int min_radix = INT_MAX;
std::vector<int> radixes = ocl_getRadixes(src.cols, min_radix);
// generate string with radix calls
String radix_processing;
int n = 1, twiddle_index = 0;
for (size_t i=0; i<radixes.size(); i++)
{
int radix = radixes[i];
radix_processing += format("fft_radix%d(smem,twiddles+%d,x,%d,%d);", radix, twiddle_index, n, src.cols/radix);
twiddle_index += (radix-1)*n;
n *= radix; n *= radix;
} }
UMat twiddles = _twiddles.getUMat();
if (twiddles.cols != twiddle_index)
{
// need to create/update tweedle table
int buffer_size = twiddle_index;
twiddles.create(1, buffer_size, CV_32FC2);
Mat tw = twiddles.getMat(ACCESS_WRITE);
float* ptr = tw.ptr<float>();
int ptr_index = 0;
int n = 1;
for (size_t i=0; i<radixes.size(); i++)
{
int radix = radixes[i];
n *= radix;
for (int k=0; k<(n/radix); k++)
{
double theta = -CV_TWO_PI*k/n;
for (int j=1; j<radix; j++)
{
ptr[ptr_index++] = cos(j*theta);
ptr[ptr_index++] = sin(j*theta);
}
}
}
}
//Mat buf = twiddles.getMat(ACCESS_READ);
UMat dst = _dst.getUMat(); UMat dst = _dst.getUMat();
int thread_count = src.cols / min_radix; int thread_count = src.cols / min_radix;
...@@ -2154,7 +2180,7 @@ static bool ocl_dft_C2C_row(InputArray _src, OutputArray _dst, int nonzero_rows, ...@@ -2154,7 +2180,7 @@ static bool ocl_dft_C2C_row(InputArray _src, OutputArray _dst, int nonzero_rows,
if (k.empty()) if (k.empty())
return false; return false;
k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), thread_count, nonzero_rows); k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), ocl::KernelArg::ReadOnlyNoSize(twiddles), thread_count, nonzero_rows);
return k.run(2, globalsize, localsize, false); return k.run(2, globalsize, localsize, false);
} }
...@@ -2232,25 +2258,26 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro ...@@ -2232,25 +2258,26 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags, int nonzero_ro
if( nonzero_rows <= 0 || nonzero_rows > _src.rows() ) if( nonzero_rows <= 0 || nonzero_rows > _src.rows() )
nonzero_rows = _src.rows(); nonzero_rows = _src.rows();
UMat buffer;
if (!ocl_dft_C2C_row(src, dst, nonzero_rows, flags)) if (!ocl_dft_C2C_row(src, dst, buffer, nonzero_rows, flags))
return false; return false;
if ((flags & DFT_ROWS) == 0 && nonzero_rows > 1) if ((flags & DFT_ROWS) == 0 && nonzero_rows > 1)
{ {
transpose(dst, dst); transpose(dst, dst);
if (!ocl_dft_C2C_row(dst, dst, dst.rows, flags)) if (!ocl_dft_C2C_row(dst, dst, buffer, dst.rows, flags))
return false; return false;
transpose(dst, dst); transpose(dst, dst);
} }
//if (complex_output) if (complex_output)
//{ {
// if (real_input && is1d) if (real_input && is1d)
// _dst.assign(buffer.colRange(0, buffer.cols/2+1)); _dst.assign(dst.colRange(0, dst.cols/2+1));
// else else
// _dst.assign(buffer); _dst.assign(dst);
//} }
//else //else
//{ //{
// if (!inv) // if (!inv)
......
This diff is collapsed.
...@@ -115,10 +115,10 @@ OCL_TEST_P(Dft, Mat) ...@@ -115,10 +115,10 @@ OCL_TEST_P(Dft, Mat)
OCL_OFF(cv::dft(src, dst, dft_flags)); OCL_OFF(cv::dft(src, dst, dft_flags));
OCL_ON(cv::dft(usrc, udst, dft_flags)); OCL_ON(cv::dft(usrc, udst, dft_flags));
Mat gpu = udst.getMat(ACCESS_READ); //Mat gpu = udst.getMat(ACCESS_READ);
std::cout << src << std::endl; //std::cout << src << std::endl;
std::cout << dst << std::endl; //std::cout << dst << std::endl;
std::cout << gpu << std::endl; //std::cout << gpu << std::endl;
//int cn = udst.channels(); //int cn = udst.channels();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment