# pragma warning(disable: 4748)
#endif
+#if defined HAVE_IPP && IPP_VERSION_MAJOR >= 7
+#define USE_IPP_DFT 1
+#else
+#undef USE_IPP_DFT
+#endif
+
+
/****************************************************************************************\
Discrete Fourier Transform
\****************************************************************************************/
#endif
-#ifdef HAVE_IPP
+#ifdef USE_IPP_DFT
static void ippsDFTFwd_CToC( const Complex<float>* src, Complex<float>* dst,
const void* spec, uchar* buf)
{
int nf, const int* factors, const int* itab,
const Complex<T>* wave, int tab_size,
const void*
-#ifdef HAVE_IPP
+#ifdef USE_IPP_DFT
spec
#endif
, Complex<T>* buf,
T scale = (T)_scale;
int tab_step;
-#ifdef HAVE_IPP
+#ifdef USE_IPP_DFT
if( spec )
{
if( !inv )
template<typename T> static void
RealDFT( const T* src, T* dst, int n, int nf, int* factors, const int* itab,
const Complex<T>* wave, int tab_size, const void*
-#ifdef HAVE_IPP
+#ifdef USE_IPP_DFT
spec
#endif
,
int j, n2 = n >> 1;
dst += complex_output;
-#ifdef HAVE_IPP
+#ifdef USE_IPP_DFT
if( spec )
{
ippsDFTFwd_RToPack( src, dst, spec, (uchar*)buf );
- goto finalize;
+ if( complex_output )
+ {
+ dst[-1] = dst[0];
+ dst[0] = 0;
+ if( (n & 1) == 0 )
+ dst[n] = 0;
+ }
+ return;
}
#endif
assert( tab_size == n );
}
}
-#ifdef HAVE_IPP
-finalize:
-#endif
if( complex_output && (n & 1) == 0 )
{
dst[-1] = dst[0];
dst[0] = 0;
- if( (n & 1) == 0 )
- dst[n] = 0;
+ dst[n] = 0;
}
}
CCSIDFT( const T* src, T* dst, int n, int nf, int* factors, const int* itab,
const Complex<T>* wave, int tab_size,
const void*
-#ifdef HAVE_IPP
+#ifdef USE_IPP_DFT
spec
#endif
, Complex<T>* buf,
((T*)src)[1] = src[0];
src++;
}
-#ifdef HAVE_IPP
+#ifdef USE_IPP_DFT
if( spec )
{
ippsDFTInv_PackToR( src, dst, spec, (uchar*)buf );
}
}
-#ifdef HAVE_IPP
+#ifdef USE_IPP_DFT
finalize:
#endif
if( complex_input )
}
-#ifdef HAVE_IPP
+#ifdef USE_IPP_DFT
typedef IppStatus (CV_STDCALL* IppDFTGetSizeFunc)(int, int, IppHintAlgorithm, int*, int*, int*);
typedef IppStatus (CV_STDCALL* IppDFTInitFunc)(int, int, IppHintAlgorithm, void*, uchar*);
#endif
int elem_size = (int)src.elemSize1(), complex_elem_size = elem_size*2;
int factors[34];
bool inplace_transform = false;
-#ifdef HAVE_IPP
+#ifdef USE_IPP_DFT
AutoBuffer<uchar> ippbuf;
int ipp_norm_flag = !(flags & DFT_SCALE) ? 8 : inv ? 2 : 1;
#endif
}
spec = 0;
-#ifdef HAVE_IPP
- if(
-#if IPP_VERSION_MAJOR >= 7
- depth == CV_32F && // IPP 7.x and 8.0 have bug somewhere in double-precision DFT
-#endif
- len*count >= 64 ) // use IPP DFT if available
+#ifdef USE_IPP_DFT
+ if( len*count >= 64 ) // use IPP DFT if available
{
int specsize=0, initsize=0, worksize=0;
IppDFTGetSizeFunc getSizeFunc = 0;
#include "precomp.hpp"
+#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
+#define USE_IPP_CANNY 1
+#else
+#undef USE_IPP_CANNY
+#endif
+
+#ifdef USE_IPP_CANNY
+namespace cv
+{
+static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high)
+{
+ int size = 0, size1 = 0;
+ IppiSize roi = { _src.cols, _src.rows };
+
+ ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size);
+ ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size1);
+ size = std::max(size, size1);
+ ippiCannyGetSize(roi, &size1);
+ size = std::max(size, size1);
+
+ AutoBuffer<uchar> buf(size + 64);
+ uchar* buffer = alignPtr((uchar*)buf, 32);
+
+ Mat _dx(_src.rows, _src.cols, CV_16S);
+ if( ippiFilterSobelNegVertBorder_8u16s_C1R(_src.data, (int)_src.step,
+ _dx.ptr<short>(), (int)_dx.step, roi,
+ ippMskSize3x3, ippBorderRepl, 0, buffer) < 0 )
+ return false;
+
+ Mat _dy(_src.rows, _src.cols, CV_16S);
+ if( ippiFilterSobelHorizBorder_8u16s_C1R(_src.data, (int)_src.step,
+ _dy.ptr<short>(), (int)_dy.step, roi,
+ ippMskSize3x3, ippBorderRepl, 0, buffer) < 0 )
+ return false;
+
+ if( ippiCanny_16s8u_C1R(_dx.ptr<short>(), (int)_dx.step,
+ _dy.ptr<short>(), (int)_dy.step,
+ _dst.data, (int)_dst.step, roi, low, high, buffer) < 0 )
+ return false;
+ return true;
+}
+}
+#endif
+
void cv::Canny( InputArray _src, OutputArray _dst,
double low_thresh, double high_thresh,
int aperture_size, bool L2gradient )
if ((aperture_size & 1) == 0 || (aperture_size != -1 && (aperture_size < 3 || aperture_size > 7)))
CV_Error(CV_StsBadFlag, "");
+ if (low_thresh > high_thresh)
+ std::swap(low_thresh, high_thresh);
+
#ifdef HAVE_TEGRA_OPTIMIZATION
if (tegra::canny(src, dst, low_thresh, high_thresh, aperture_size, L2gradient))
return;
#endif
- const int cn = src.channels();
- cv::Mat dx(src.rows, src.cols, CV_16SC(cn));
- cv::Mat dy(src.rows, src.cols, CV_16SC(cn));
+#ifdef USE_IPP_CANNY
+ if( aperture_size == 3 && !L2gradient &&
+ ippCanny(src, dst, low_thresh, high_thresh) >= 0 )
+ return;
+#endif
- cv::Sobel(src, dx, CV_16S, 1, 0, aperture_size, 1, 0, cv::BORDER_REPLICATE);
- cv::Sobel(src, dy, CV_16S, 0, 1, aperture_size, 1, 0, cv::BORDER_REPLICATE);
+ const int cn = src.channels();
+ Mat dx(src.rows, src.cols, CV_16SC(cn));
+ Mat dy(src.rows, src.cols, CV_16SC(cn));
- if (low_thresh > high_thresh)
- std::swap(low_thresh, high_thresh);
+ Sobel(src, dx, CV_16S, 1, 0, aperture_size, 1, 0, cv::BORDER_REPLICATE);
+ Sobel(src, dy, CV_16S, 0, 1, aperture_size, 1, 0, cv::BORDER_REPLICATE);
if (L2gradient)
{
int high = cvFloor(high_thresh);
ptrdiff_t mapstep = src.cols + 2;
- cv::AutoBuffer<uchar> buffer((src.cols+2)*(src.rows+2) + cn * mapstep * 3 * sizeof(int));
+ AutoBuffer<uchar> buffer((src.cols+2)*(src.rows+2) + cn * mapstep * 3 * sizeof(int));
int* mag_buf[3];
mag_buf[0] = (int*)(uchar*)buffer;
};
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
-static bool IPPMorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kernel, const Point &anchor)
+static bool IPPMorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kernel,
+ const Size& ksize, const Point &anchor, bool rectKernel)
{
int type = src.type();
const Mat* _src = &src;
}
//DEPRECATED. Allocates and initializes morphology state structure for erosion or dilation operation.
typedef IppStatus (CV_STDCALL* ippiMorphologyInitAllocFunc)(int, const void*, IppiSize, IppiPoint, IppiMorphState **);
- ippiMorphologyInitAllocFunc ippInitAllocFunc =
- type == CV_8UC1 ? (ippiMorphologyInitAllocFunc)ippiMorphologyInitAlloc_8u_C1R :
- type == CV_8UC3 ? (ippiMorphologyInitAllocFunc)ippiMorphologyInitAlloc_8u_C3R :
- type == CV_8UC4 ? (ippiMorphologyInitAllocFunc)ippiMorphologyInitAlloc_8u_C4R :
- type == CV_32FC1 ? (ippiMorphologyInitAllocFunc)ippiMorphologyInitAlloc_32f_C1R :
- type == CV_32FC3 ? (ippiMorphologyInitAllocFunc)ippiMorphologyInitAlloc_32f_C3R :
- type == CV_32FC4 ? (ippiMorphologyInitAllocFunc)ippiMorphologyInitAlloc_32f_C4R :
- 0;
- typedef IppStatus (CV_STDCALL* ippiMorphologyBorderReplicateFunc)(const void*, int, void *, int, IppiSize, IppiBorderType, IppiMorphState *);
- ippiMorphologyBorderReplicateFunc ippFunc = 0;
- switch( op )
+ typedef IppStatus (CV_STDCALL* ippiMorphologyBorderReplicateFunc)(const void*, int, void *, int,
+ IppiSize, IppiBorderType, IppiMorphState *);
+ typedef IppStatus (CV_STDCALL* ippiFilterMinMaxGetBufferSizeFunc)(int, IppiSize, int*);
+ typedef IppStatus (CV_STDCALL* ippiFilterMinMaxBorderReplicateFunc)(const void*, int, void*, int,
+ IppiSize, IppiSize, IppiPoint, void*);
+
+ ippiMorphologyInitAllocFunc initAllocFunc = 0;
+ ippiMorphologyBorderReplicateFunc morphFunc = 0;
+ ippiFilterMinMaxGetBufferSizeFunc getBufSizeFunc = 0;
+ ippiFilterMinMaxBorderReplicateFunc morphRectFunc = 0;
+
+ #define IPP_MORPH_CASE(type, flavor) \
+ case type: \
+ initAllocFunc = (ippiMorphologyInitAllocFunc)ippiMorphologyInitAlloc_##flavor; \
+ morphFunc = op == MORPH_ERODE ? (ippiMorphologyBorderReplicateFunc)ippiErodeBorderReplicate_##flavor : \
+ (ippiMorphologyBorderReplicateFunc)ippiDilateBorderReplicate_##flavor; \
+ getBufSizeFunc = (ippiFilterMinMaxGetBufferSizeFunc)ippiFilterMinGetBufferSize_##flavor; \
+ morphRectFunc = op == MORPH_ERODE ? (ippiFilterMinMaxBorderReplicateFunc)ippiFilterMinBorderReplicate_##flavor : \
+ (ippiFilterMinMaxBorderReplicateFunc)ippiFilterMaxBorderReplicate_##flavor; \
+ break
+
+ switch( type )
{
- case MORPH_DILATE:
- {
- ippFunc =
- type == CV_8UC1 ? (ippiMorphologyBorderReplicateFunc)ippiDilateBorderReplicate_8u_C1R :
- type == CV_8UC3 ? (ippiMorphologyBorderReplicateFunc)ippiDilateBorderReplicate_8u_C3R :
- type == CV_8UC4 ? (ippiMorphologyBorderReplicateFunc)ippiDilateBorderReplicate_8u_C4R :
- type == CV_32FC1 ? (ippiMorphologyBorderReplicateFunc)ippiDilateBorderReplicate_32f_C1R :
- type == CV_32FC3 ? (ippiMorphologyBorderReplicateFunc)ippiDilateBorderReplicate_32f_C3R :
- type == CV_32FC4 ? (ippiMorphologyBorderReplicateFunc)ippiDilateBorderReplicate_32f_C4R :
- 0;
- break;
- }
- case MORPH_ERODE:
- {
- ippFunc =
- type == CV_8UC1 ? (ippiMorphologyBorderReplicateFunc)ippiErodeBorderReplicate_8u_C1R :
- type == CV_8UC3 ? (ippiMorphologyBorderReplicateFunc)ippiErodeBorderReplicate_8u_C3R :
- type == CV_8UC4 ? (ippiMorphologyBorderReplicateFunc)ippiErodeBorderReplicate_8u_C4R :
- type == CV_32FC1 ? (ippiMorphologyBorderReplicateFunc)ippiErodeBorderReplicate_32f_C1R :
- type == CV_32FC3 ? (ippiMorphologyBorderReplicateFunc)ippiErodeBorderReplicate_32f_C3R :
- type == CV_32FC4 ? (ippiMorphologyBorderReplicateFunc)ippiErodeBorderReplicate_32f_C4R :
- 0;
- break;
- }
+ IPP_MORPH_CASE(CV_8UC1, 8u_C1R);
+ IPP_MORPH_CASE(CV_8UC3, 8u_C3R);
+ IPP_MORPH_CASE(CV_8UC4, 8u_C4R);
+ IPP_MORPH_CASE(CV_32FC1, 32f_C1R);
+ IPP_MORPH_CASE(CV_32FC3, 32f_C3R);
+ IPP_MORPH_CASE(CV_32FC4, 32f_C4R);
+ default:
+ return false;
}
- if( ippFunc && ippInitAllocFunc)
+
+ IppiSize roiSize = {src.cols, src.rows};
+ IppiSize kernelSize = {ksize.width, ksize.height};
+ IppiPoint point = {anchor.x, anchor.y};
+
+ if( !rectKernel && morphFunc && initAllocFunc )
{
IppiMorphState* pState;
- IppiSize roiSize = {src.cols, src.rows};
- IppiSize kernelSize = {kernel.cols, kernel.rows};
- IppiPoint point = {anchor.x, anchor.y};
- if( ippInitAllocFunc( roiSize.width, kernel.data, kernelSize, point, &pState ) < 0 )
+ if( initAllocFunc( roiSize.width, kernel.data, kernelSize, point, &pState ) < 0 )
return false;
- bool is_ok = ippFunc( _src->data, _src->step[0], dst.data, dst.step[0], roiSize, ippBorderRepl, pState ) >= 0;
+ bool is_ok = morphFunc( _src->data, (int)_src->step[0],
+ dst.data, (int)dst.step[0],
+ roiSize, ippBorderRepl, pState ) >= 0;
ippiMorphologyFree(pState);
return is_ok;
}
+ else if( rectKernel && morphRectFunc && getBufSizeFunc )
+ {
+ int bufSize = 0;
+ if( getBufSizeFunc( src.cols, kernelSize, &bufSize) < 0 )
+ return false;
+ AutoBuffer<uchar> buf(bufSize + 64);
+ uchar* buffer = alignPtr((uchar*)buf, 32);
+ return morphRectFunc(_src->data, (int)_src->step[0], dst.data, (int)dst.step[0],
+ roiSize, kernelSize, point, buffer);
+ }
return false;
}
!( borderType == cv::BORDER_REPLICATE || (borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue()) )
|| !( op == MORPH_DILATE || op == MORPH_ERODE) )
return false;
- if( borderType == cv::BORDER_CONSTANT )
+ if( borderType == cv::BORDER_CONSTANT && kernel.data )
{
int x, y;
for( y = 0; y < kernel.rows; y++ )
return true;
}
+ bool rectKernel = false;
if( !kernel.data )
{
- kernel = getStructuringElement(MORPH_RECT, Size(1+iterations*2,1+iterations*2));
+ ksize = Size(1+iterations*2,1+iterations*2);
normanchor = Point(iterations, iterations);
+ rectKernel = true;
iterations = 1;
}
else if( iterations > 1 && countNonZero(kernel) == kernel.rows*kernel.cols )
{
+ ksize = Size(ksize.width + (iterations-1)*(ksize.width-1),
+ ksize.height + (iterations-1)*(ksize.height-1)),
normanchor = Point(normanchor.x*iterations, normanchor.y*iterations);
- kernel = getStructuringElement(MORPH_RECT,
- Size(ksize.width + (iterations-1)*(ksize.width-1),
- ksize.height + (iterations-1)*(ksize.height-1)),
- normanchor);
+ kernel = Mat();
+ rectKernel = true;
iterations = 1;
}
- return IPPMorphReplicate( op, src, dst, kernel, normanchor );
+ // TODO: implement the case of iterations > 1.
+ if( iterations > 1 )
+ return false;
+
+ return IPPMorphReplicate( op, src, dst, kernel, ksize, normanchor, rectKernel );
}
#endif