Merge pull request #2677 from ilya-lavrenov:ipp_compilation
authorAlexander Alekhin <alexander.alekhin@itseez.com>
Tue, 29 Apr 2014 08:26:48 +0000 (12:26 +0400)
committerOpenCV Buildbot <buildbot@opencv.org>
Tue, 29 Apr 2014 08:26:49 +0000 (12:26 +0400)
12 files changed:
doc/tutorials/core/file_input_output_with_xml_yml/file_input_output_with_xml_yml.rst
doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.rst
modules/core/include/opencv2/core/private.hpp
modules/core/perf/perf_dft.cpp
modules/core/src/convert.cpp
modules/core/src/dxt.cpp
modules/highgui/doc/reading_and_writing_images_and_video.rst
modules/highgui/src/cap_vfw.cpp
modules/imgproc/src/morph.cpp
modules/imgproc/test/ocl/test_warp.cpp
modules/objdetect/perf/opencl/perf_hogdetect.cpp
modules/video/perf/perf_ecc.cpp

index 42f6a60..7e1674e 100644 (file)
@@ -31,15 +31,15 @@ Here's a sample code of how to achieve all the stuff enumerated at the goal list
 Explanation
 ===========
 
-Here we talk only about XML and YAML file inputs. Your output (and its respective input) file may have only one of these extensions and the structure coming from this. They are two kinds of data structures you may serialize: *mappings* (like the STL map) and *element sequence* (like the STL vector>. The difference between these is that in a map every element has a unique name through what you may access it. For sequences you need to go through them to query a specific item.
+Here we talk only about XML and YAML file inputs. Your output (and its respective input) file may have only one of these extensions and the structure coming from this. They are two kinds of data structures you may serialize: *mappings* (like the STL map) and *element sequence* (like the STL vector). The difference between these is that in a map every element has a unique name through what you may access it. For sequences you need to go through them to query a specific item.
 
-1. **XML\\YAML File Open and Close.** Before you write any content to such file you need to open it and at the end to close it. The XML\YAML data structure in OpenCV is :xmlymlpers:`FileStorage <filestorage>`. To specify that this structure to which file binds on your hard drive you can use either its constructor or the *open()* function of this:
+1. **XML/YAML File Open and Close.** Before you write any content to such file you need to open it and at the end to close it. The XML/YAML data structure in OpenCV is :xmlymlpers:`FileStorage <filestorage>`. To specify that this structure to which file binds on your hard drive you can use either its constructor or the *open()* function of this:
 
    .. code-block:: cpp
 
       string filename = "I.xml";
       FileStorage fs(filename, FileStorage::WRITE);
-      \\...
+      //...
       fs.open(filename, FileStorage::READ);
 
    Either one of this you use the second argument is a constant specifying the type of operations you'll be able to on them: WRITE, READ or APPEND. The extension specified in the file name also determinates the output format that will be used. The output may be even compressed if you specify an extension such as *.xml.gz*.
@@ -64,7 +64,7 @@ Here we talk only about XML and YAML file inputs. Your output (and its respectiv
       fs["iterationNr"] >> itNr;
       itNr = (int) fs["iterationNr"];
 
-#. **Input\\Output of OpenCV Data structures.** Well these behave exactly just as the basic C++ types:
+#. **Input/Output of OpenCV Data structures.** Well these behave exactly just as the basic C++ types:
 
    .. code-block:: cpp
 
@@ -77,7 +77,7 @@ Here we talk only about XML and YAML file inputs. Your output (and its respectiv
       fs["R"] >> R;                                      // Read cv::Mat
       fs["T"] >> T;
 
-#. **Input\\Output of vectors (arrays) and associative maps.** As I mentioned beforehand we can output maps and sequences (array, vector) too. Again we first print the name of the variable and then we have to specify if our output is either a sequence or map.
+#. **Input/Output of vectors (arrays) and associative maps.** As I mentioned beforehand, we can output maps and sequences (array, vector) too. Again we first print the name of the variable and then we have to specify if our output is either a sequence or map.
 
    For sequence before the first element print the "[" character and after the last one the "]" character:
 
index de38a85..736aceb 100644 (file)
@@ -113,7 +113,7 @@ Although *Mat* works really well as an image container, it is also a general mat
 
     For instance, *CV_8UC3* means we use unsigned char types that are 8 bit long and each pixel has three of these to form the three channels. This are predefined for up to four channel numbers. The :basicstructures:`Scalar <scalar>` is four element short vector. Specify this and you can initialize all matrix points with a custom value. If you need more you can create the type with the upper macro, setting the channel number in parenthesis as you can see below.
 
-   + Use C\\C++ arrays and initialize via constructor
+   + Use C/C++ arrays and initialize via constructor
 
      .. literalinclude:: ../../../../samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp
         :language: cpp
index a9210a1..eea2281 100644 (file)
@@ -218,6 +218,8 @@ CV_EXPORTS void scalarToRawData(const cv::Scalar& s, void* buf, int type, int un
 #  endif
 #  define IPP_VERSION_X100 (IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR)
 
+#define IPP_ALIGN 32 // required for AVX optimization
+
 #define setIppErrorStatus() cv::ipp::setIppStatus(-1, CV_Func, __FILE__, __LINE__)
 
 static inline IppiSize ippiSize(int width, int height)
index a33bcf5..a2d3d50 100644 (file)
@@ -6,21 +6,26 @@ using namespace perf;
 using std::tr1::make_tuple;
 using std::tr1::get;
 
-#define MAT_TYPES_DFT  CV_32FC1, CV_64FC1
-#define MAT_SIZES_DFT  sz1080p, sz2K
-#define TEST_MATS_DFT  testing::Combine(testing::Values(MAT_SIZES_DFT), testing::Values(MAT_TYPES_DFT))
+#define MAT_TYPES_DFT  CV_32FC1, CV_32FC2, CV_64FC1
+#define MAT_SIZES_DFT  cv::Size(320, 480), cv::Size(800, 600), cv::Size(1280, 1024), sz1080p, sz2K
+CV_ENUM(FlagsType, 0, DFT_INVERSE, DFT_SCALE, DFT_COMPLEX_OUTPUT, DFT_ROWS, DFT_INVERSE|DFT_COMPLEX_OUTPUT)
+#define TEST_MATS_DFT  testing::Combine(testing::Values(MAT_SIZES_DFT), testing::Values(MAT_TYPES_DFT), FlagsType::all())
 
-PERF_TEST_P(Size_MatType, dft, TEST_MATS_DFT)
+typedef std::tr1::tuple<Size, MatType, FlagsType> Size_MatType_FlagsType_t;
+typedef perf::TestBaseWithParam<Size_MatType_FlagsType_t> Size_MatType_FlagsType;
+
+PERF_TEST_P(Size_MatType_FlagsType, dft, TEST_MATS_DFT)
 {
     Size sz = get<0>(GetParam());
     int type = get<1>(GetParam());
+    int flags = get<2>(GetParam());
 
     Mat src(sz, type);
     Mat dst(sz, type);
 
     declare.in(src, WARMUP_RNG).time(60);
 
-    TEST_CYCLE() dft(src, dst);
+    TEST_CYCLE() dft(src, dst, flags);
 
     SANITY_CHECK(dst, 1e-5, ERROR_RELATIVE);
-}
+}
\ No newline at end of file
index e615443..6684ded 100644 (file)
@@ -1543,10 +1543,10 @@ static LUTFunc lutTab[] =
 
 static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst)
 {
-    int dtype = _dst.type(), lcn = _lut.channels(), dcn = CV_MAT_CN(dtype), ddepth = CV_MAT_DEPTH(dtype);
+    int lcn = _lut.channels(), dcn = _src.channels(), ddepth = _lut.depth();
 
     UMat src = _src.getUMat(), lut = _lut.getUMat();
-    _dst.create(src.size(), dtype);
+    _dst.create(src.size(), CV_MAKETYPE(ddepth, dcn));
     UMat dst = _dst.getUMat();
 
     ocl::Kernel k("LUT", ocl::core::lut_oclsrc,
@@ -1564,6 +1564,201 @@ static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst)
 
 #endif
 
+#if defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY)
+namespace ipp {
+
+#if 0 // there are no performance benefits (PR #2653)
+class IppLUTParallelBody_LUTC1 : public ParallelLoopBody
+{
+public:
+    bool* ok;
+    const Mat& src_;
+    const Mat& lut_;
+    Mat& dst_;
+
+    typedef IppStatus (*IppFn)(const Ipp8u* pSrc, int srcStep, void* pDst, int dstStep,
+                          IppiSize roiSize, const void* pTable, int nBitSize);
+    IppFn fn;
+
+    int width;
+
+    IppLUTParallelBody_LUTC1(const Mat& src, const Mat& lut, Mat& dst, bool* _ok)
+        : ok(_ok), src_(src), lut_(lut), dst_(dst)
+    {
+        width = dst.cols * dst.channels();
+
+        size_t elemSize1 = CV_ELEM_SIZE1(dst.depth());
+
+        fn =
+                elemSize1 == 1 ? (IppFn)ippiLUTPalette_8u_C1R :
+                elemSize1 == 4 ? (IppFn)ippiLUTPalette_8u32u_C1R :
+                NULL;
+
+        *ok = (fn != NULL);
+    }
+
+    void operator()( const cv::Range& range ) const
+    {
+        if (!*ok)
+            return;
+
+        const int row0 = range.start;
+        const int row1 = range.end;
+
+        Mat src = src_.rowRange(row0, row1);
+        Mat dst = dst_.rowRange(row0, row1);
+
+        IppiSize sz = { width, dst.rows };
+
+        CV_DbgAssert(fn != NULL);
+        if (fn(src.data, (int)src.step[0], dst.data, (int)dst.step[0], sz, lut_.data, 8) < 0)
+        {
+            setIppErrorStatus();
+            *ok = false;
+        }
+    }
+private:
+    IppLUTParallelBody_LUTC1(const IppLUTParallelBody_LUTC1&);
+    IppLUTParallelBody_LUTC1& operator=(const IppLUTParallelBody_LUTC1&);
+};
+#endif
+
+class IppLUTParallelBody_LUTCN : public ParallelLoopBody
+{
+public:
+    bool *ok;
+    const Mat& src_;
+    const Mat& lut_;
+    Mat& dst_;
+
+    int lutcn;
+
+    uchar* lutBuffer;
+    uchar* lutTable[4];
+
+    IppLUTParallelBody_LUTCN(const Mat& src, const Mat& lut, Mat& dst, bool* _ok)
+        : ok(_ok), src_(src), lut_(lut), dst_(dst), lutBuffer(NULL)
+    {
+        lutcn = lut.channels();
+        IppiSize sz256 = {256, 1};
+
+        size_t elemSize1 = dst.elemSize1();
+        CV_DbgAssert(elemSize1 == 1);
+        lutBuffer = (uchar*)ippMalloc(256 * (int)elemSize1 * 4);
+        lutTable[0] = lutBuffer + 0;
+        lutTable[1] = lutBuffer + 1 * 256 * elemSize1;
+        lutTable[2] = lutBuffer + 2 * 256 * elemSize1;
+        lutTable[3] = lutBuffer + 3 * 256 * elemSize1;
+
+        CV_DbgAssert(lutcn == 3 || lutcn == 4);
+        if (lutcn == 3)
+        {
+            IppStatus status = ippiCopy_8u_C3P3R(lut.data, (int)lut.step[0], lutTable, (int)lut.step[0], sz256);
+            if (status < 0)
+            {
+                setIppErrorStatus();
+                return;
+            }
+        }
+        else if (lutcn == 4)
+        {
+            IppStatus status = ippiCopy_8u_C4P4R(lut.data, (int)lut.step[0], lutTable, (int)lut.step[0], sz256);
+            if (status < 0)
+            {
+                setIppErrorStatus();
+                return;
+            }
+        }
+
+        *ok = true;
+    }
+
+    ~IppLUTParallelBody_LUTCN()
+    {
+        if (lutBuffer != NULL)
+            ippFree(lutBuffer);
+        lutBuffer = NULL;
+        lutTable[0] = NULL;
+    }
+
+    void operator()( const cv::Range& range ) const
+    {
+        if (!*ok)
+            return;
+
+        const int row0 = range.start;
+        const int row1 = range.end;
+
+        Mat src = src_.rowRange(row0, row1);
+        Mat dst = dst_.rowRange(row0, row1);
+
+        if (lutcn == 3)
+        {
+            if (ippiLUTPalette_8u_C3R(
+                    src.data, (int)src.step[0], dst.data, (int)dst.step[0],
+                    ippiSize(dst.size()), lutTable, 8) >= 0)
+                return;
+        }
+        else if (lutcn == 4)
+        {
+            if (ippiLUTPalette_8u_C4R(
+                    src.data, (int)src.step[0], dst.data, (int)dst.step[0],
+                    ippiSize(dst.size()), lutTable, 8) >= 0)
+                return;
+        }
+        setIppErrorStatus();
+        *ok = false;
+    }
+private:
+    IppLUTParallelBody_LUTCN(const IppLUTParallelBody_LUTCN&);
+    IppLUTParallelBody_LUTCN& operator=(const IppLUTParallelBody_LUTCN&);
+};
+} // namespace ipp
+#endif // IPP
+
+class LUTParallelBody : public ParallelLoopBody
+{
+public:
+    bool* ok;
+    const Mat& src_;
+    const Mat& lut_;
+    Mat& dst_;
+
+    LUTFunc func;
+
+    LUTParallelBody(const Mat& src, const Mat& lut, Mat& dst, bool* _ok)
+        : ok(_ok), src_(src), lut_(lut), dst_(dst)
+    {
+        func = lutTab[lut.depth()];
+        *ok = (func != NULL);
+    }
+
+    void operator()( const cv::Range& range ) const
+    {
+        CV_DbgAssert(*ok);
+
+        const int row0 = range.start;
+        const int row1 = range.end;
+
+        Mat src = src_.rowRange(row0, row1);
+        Mat dst = dst_.rowRange(row0, row1);
+
+        int cn = src.channels();
+        int lutcn = lut_.channels();
+
+        const Mat* arrays[] = {&src, &dst, 0};
+        uchar* ptrs[2];
+        NAryMatIterator it(arrays, ptrs);
+        int len = (int)it.size;
+
+        for( size_t i = 0; i < it.nplanes; i++, ++it )
+            func(ptrs[0], lut_.data, ptrs[1], len, cn, lutcn);
+    }
+private:
+    LUTParallelBody(const LUTParallelBody&);
+    LUTParallelBody& operator=(const LUTParallelBody&);
+};
+
 }
 
 void cv::LUT( InputArray _src, InputArray _lut, OutputArray _dst )
@@ -1582,6 +1777,44 @@ void cv::LUT( InputArray _src, InputArray _lut, OutputArray _dst )
     _dst.create(src.dims, src.size, CV_MAKETYPE(_lut.depth(), cn));
     Mat dst = _dst.getMat();
 
+    if (_src.dims() <= 2)
+    {
+        bool ok = false;
+        Ptr<ParallelLoopBody> body;
+#if defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY)
+        size_t elemSize1 = CV_ELEM_SIZE1(dst.depth());
+#if 0 // there are no performance benefits (PR #2653)
+        if (lutcn == 1)
+        {
+            ParallelLoopBody* p = new ipp::IppLUTParallelBody_LUTC1(src, lut, dst, &ok);
+            body.reset(p);
+        }
+        else
+#endif
+        if ((lutcn == 3 || lutcn == 4) && elemSize1 == 1)
+        {
+            ParallelLoopBody* p = new ipp::IppLUTParallelBody_LUTCN(src, lut, dst, &ok);
+            body.reset(p);
+        }
+#endif
+        if (body == NULL || ok == false)
+        {
+            ok = false;
+            ParallelLoopBody* p = new LUTParallelBody(src, lut, dst, &ok);
+            body.reset(p);
+        }
+        if (body != NULL && ok)
+        {
+            Range all(0, dst.rows);
+            if (dst.total()>>18)
+                parallel_for_(all, *body, (double)std::max((size_t)1, dst.total()>>16));
+            else
+                (*body)(all);
+            if (ok)
+                return;
+        }
+    }
+
     LUTFunc func = lutTab[lut.depth()];
     CV_Assert( func != 0 );
 
index c5a44e7..0c12e19 100644 (file)
@@ -1476,6 +1476,300 @@ typedef IppStatus (CV_STDCALL* IppDFTGetSizeFunc)(int, int, IppHintAlgorithm, in
 typedef IppStatus (CV_STDCALL* IppDFTInitFunc)(int, int, IppHintAlgorithm, void*, uchar*);
 #endif
 
+namespace cv
+{
+#if defined USE_IPP_DFT && !defined HAVE_IPP_ICV_ONLY
+
+typedef IppStatus (CV_STDCALL* ippiDFT_C_Func)(const Ipp32fc*, int, Ipp32fc*, int, const IppiDFTSpec_C_32fc*, Ipp8u*);
+typedef IppStatus (CV_STDCALL* ippiDFT_R_Func)(const Ipp32f* , int, Ipp32f* , int, const IppiDFTSpec_R_32f* , Ipp8u*);
+
+template <typename Dft>
+class Dft_C_IPPLoop_Invoker : public ParallelLoopBody
+{
+public:
+
+    Dft_C_IPPLoop_Invoker(const Mat& _src, Mat& _dst, const Dft& _ippidft, int _norm_flag, bool *_ok) :
+        ParallelLoopBody(), src(_src), dst(_dst), ippidft(_ippidft), norm_flag(_norm_flag), ok(_ok)
+    {
+        *ok = true;
+    }
+
+    virtual void operator()(const Range& range) const
+    {
+        IppStatus status;
+        Ipp8u* pBuffer = 0;
+        Ipp8u* pMemInit= 0;
+        int sizeBuffer=0;
+        int sizeSpec=0;
+        int sizeInit=0;
+
+        IppiSize srcRoiSize = {src.cols, 1};
+
+        status = ippiDFTGetSize_C_32fc(srcRoiSize, norm_flag, ippAlgHintNone, &sizeSpec, &sizeInit, &sizeBuffer );
+        if ( status < 0 )
+        {
+            *ok = false;
+            return;
+        }
+
+        IppiDFTSpec_C_32fc* pDFTSpec = (IppiDFTSpec_C_32fc*)ippMalloc( sizeSpec );
+
+        if ( sizeInit > 0 )
+            pMemInit = (Ipp8u*)ippMalloc( sizeInit );
+
+        if ( sizeBuffer > 0 )
+            pBuffer = (Ipp8u*)ippMalloc( sizeBuffer );
+
+        status = ippiDFTInit_C_32fc( srcRoiSize, norm_flag, ippAlgHintNone, pDFTSpec, pMemInit );
+
+        if ( sizeInit > 0 )
+            ippFree( pMemInit );
+
+        if ( status < 0 )
+        {
+            ippFree( pDFTSpec );
+            if ( sizeBuffer > 0 )
+                ippFree( pBuffer );
+            *ok = false;
+            return;
+        }
+
+        for( int i = range.start; i < range.end; ++i)
+            if(!ippidft((Ipp32fc*)(src.data+i*src.step), (int)src.step,(Ipp32fc*)(dst.data+i*dst.step), (int)dst.step, pDFTSpec, (Ipp8u*)pBuffer))
+            {
+                *ok = false;
+            }
+
+        if ( sizeBuffer > 0 )
+            ippFree( pBuffer );
+
+        ippFree( pDFTSpec );
+    }
+
+private:
+    const Mat& src;
+    Mat& dst;
+    const Dft& ippidft;
+    int norm_flag;
+    bool *ok;
+
+    const Dft_C_IPPLoop_Invoker& operator= (const Dft_C_IPPLoop_Invoker&);
+};
+
+template <typename Dft>
+class Dft_R_IPPLoop_Invoker : public ParallelLoopBody
+{
+public:
+
+    Dft_R_IPPLoop_Invoker(const Mat& _src, Mat& _dst, const Dft& _ippidft, int _norm_flag, bool *_ok) :
+        ParallelLoopBody(), src(_src), dst(_dst), ippidft(_ippidft), norm_flag(_norm_flag), ok(_ok)
+    {
+        *ok = true;
+    }
+
+    virtual void operator()(const Range& range) const
+    {
+        IppStatus status;
+        Ipp8u* pBuffer = 0;
+        Ipp8u* pMemInit= 0;
+        int sizeBuffer=0;
+        int sizeSpec=0;
+        int sizeInit=0;
+
+        IppiSize srcRoiSize = {src.cols, 1};
+
+        status = ippiDFTGetSize_R_32f(srcRoiSize, norm_flag, ippAlgHintNone, &sizeSpec, &sizeInit, &sizeBuffer );
+        if ( status < 0 )
+        {
+            *ok = false;
+            return;
+        }
+
+        IppiDFTSpec_R_32f* pDFTSpec = (IppiDFTSpec_R_32f*)ippMalloc( sizeSpec );
+
+        if ( sizeInit > 0 )
+            pMemInit = (Ipp8u*)ippMalloc( sizeInit );
+
+        if ( sizeBuffer > 0 )
+            pBuffer = (Ipp8u*)ippMalloc( sizeBuffer );
+
+        status = ippiDFTInit_R_32f( srcRoiSize, norm_flag, ippAlgHintNone, pDFTSpec, pMemInit );
+
+        if ( sizeInit > 0 )
+            ippFree( pMemInit );
+
+        if ( status < 0 )
+        {
+            ippFree( pDFTSpec );
+            if ( sizeBuffer > 0 )
+                ippFree( pBuffer );
+            *ok = false;
+            return;
+        }
+
+        for( int i = range.start; i < range.end; ++i)
+            if(!ippidft(src.ptr<float>(i), (int)src.step,dst.ptr<float>(i), (int)dst.step, pDFTSpec, (Ipp8u*)pBuffer))
+            {
+                *ok = false;
+            }
+
+        if ( sizeBuffer > 0 )
+            ippFree( pBuffer );
+
+        ippFree( pDFTSpec );
+    }
+
+private:
+    const Mat& src;
+    Mat& dst;
+    const Dft& ippidft;
+    int norm_flag;
+    bool *ok;
+
+    const Dft_R_IPPLoop_Invoker& operator= (const Dft_R_IPPLoop_Invoker&);
+};
+
+template <typename Dft>
+bool Dft_C_IPPLoop(const Mat& src, Mat& dst, const Dft& ippidft, int norm_flag)
+{
+    bool ok;
+    parallel_for_(Range(0, src.rows), Dft_C_IPPLoop_Invoker<Dft>(src, dst, ippidft, norm_flag, &ok), src.total()/(double)(1<<16) );
+    return ok;
+}
+
+template <typename Dft>
+bool Dft_R_IPPLoop(const Mat& src, Mat& dst, const Dft& ippidft, int norm_flag)
+{
+    bool ok;
+    parallel_for_(Range(0, src.rows), Dft_R_IPPLoop_Invoker<Dft>(src, dst, ippidft, norm_flag, &ok), src.total()/(double)(1<<16) );
+    return ok;
+}
+
+struct IPPDFT_C_Functor
+{
+    IPPDFT_C_Functor(ippiDFT_C_Func _func) : func(_func){}
+
+    bool operator()(const Ipp32fc* src, int srcStep, Ipp32fc* dst, int dstStep, const IppiDFTSpec_C_32fc* pDFTSpec, Ipp8u* pBuffer) const
+    {
+        return func ? func(src, srcStep, dst, dstStep, pDFTSpec, pBuffer) >= 0 : false;
+    }
+private:
+    ippiDFT_C_Func func;
+};
+
+struct IPPDFT_R_Functor
+{
+    IPPDFT_R_Functor(ippiDFT_R_Func _func) : func(_func){}
+
+    bool operator()(const Ipp32f* src, int srcStep, Ipp32f* dst, int dstStep, const IppiDFTSpec_R_32f* pDFTSpec, Ipp8u* pBuffer) const
+    {
+        return func ? func(src, srcStep, dst, dstStep, pDFTSpec, pBuffer) >= 0 : false;
+    }
+private:
+    ippiDFT_R_Func func;
+};
+
+static bool ippi_DFT_C_32F(const Mat& src, Mat& dst, bool inv, int norm_flag)
+{
+    IppStatus status;
+    Ipp8u* pBuffer = 0;
+    Ipp8u* pMemInit= 0;
+    int sizeBuffer=0;
+    int sizeSpec=0;
+    int sizeInit=0;
+
+    IppiSize srcRoiSize = {src.cols, src.rows};
+
+    status = ippiDFTGetSize_C_32fc(srcRoiSize, norm_flag, ippAlgHintNone, &sizeSpec, &sizeInit, &sizeBuffer );
+    if ( status < 0 )
+        return false;
+
+    IppiDFTSpec_C_32fc* pDFTSpec = (IppiDFTSpec_C_32fc*)ippMalloc( sizeSpec );
+
+    if ( sizeInit > 0 )
+        pMemInit = (Ipp8u*)ippMalloc( sizeInit );
+
+    if ( sizeBuffer > 0 )
+        pBuffer = (Ipp8u*)ippMalloc( sizeBuffer );
+
+    status = ippiDFTInit_C_32fc( srcRoiSize, norm_flag, ippAlgHintNone, pDFTSpec, pMemInit );
+
+    if ( sizeInit > 0 )
+        ippFree( pMemInit );
+
+    if ( status < 0 )
+    {
+        ippFree( pDFTSpec );
+        if ( sizeBuffer > 0 )
+            ippFree( pBuffer );
+        return false;
+    }
+
+    if (!inv)
+        status = ippiDFTFwd_CToC_32fc_C1R( (Ipp32fc*)src.data, (int)src.step, (Ipp32fc*)dst.data, (int)dst.step, pDFTSpec, pBuffer );
+    else
+        status = ippiDFTInv_CToC_32fc_C1R( (Ipp32fc*)src.data, (int)src.step, (Ipp32fc*)dst.data, (int)dst.step, pDFTSpec, pBuffer );
+
+    if ( sizeBuffer > 0 )
+        ippFree( pBuffer );
+
+    ippFree( pDFTSpec );
+
+    return status >= 0;
+    }
+
+static bool ippi_DFT_R_32F(const Mat& src, Mat& dst, bool inv, int norm_flag)
+{
+    IppStatus status;
+    Ipp8u* pBuffer = 0;
+    Ipp8u* pMemInit= 0;
+    int sizeBuffer=0;
+    int sizeSpec=0;
+    int sizeInit=0;
+
+    IppiSize srcRoiSize = {src.cols, src.rows};
+
+    status = ippiDFTGetSize_R_32f(srcRoiSize, norm_flag, ippAlgHintNone, &sizeSpec, &sizeInit, &sizeBuffer );
+    if ( status < 0 )
+        return false;
+
+    IppiDFTSpec_R_32f* pDFTSpec = (IppiDFTSpec_R_32f*)ippMalloc( sizeSpec );
+
+    if ( sizeInit > 0 )
+        pMemInit = (Ipp8u*)ippMalloc( sizeInit );
+
+    if ( sizeBuffer > 0 )
+        pBuffer = (Ipp8u*)ippMalloc( sizeBuffer );
+
+    status = ippiDFTInit_R_32f( srcRoiSize, norm_flag, ippAlgHintNone, pDFTSpec, pMemInit );
+
+    if ( sizeInit > 0 )
+        ippFree( pMemInit );
+
+    if ( status < 0 )
+    {
+        ippFree( pDFTSpec );
+        if ( sizeBuffer > 0 )
+            ippFree( pBuffer );
+        return false;
+    }
+
+    if (!inv)
+        status = ippiDFTFwd_RToPack_32f_C1R( src.ptr<float>(), (int)(src.step), dst.ptr<float>(), (int)dst.step, pDFTSpec, pBuffer );
+    else
+        status = ippiDFTInv_PackToR_32f_C1R( src.ptr<float>(), (int)src.step, dst.ptr<float>(), (int)dst.step, pDFTSpec, pBuffer );
+
+    if ( sizeBuffer > 0 )
+        ippFree( pBuffer );
+
+    ippFree( pDFTSpec );
+
+    return status >= 0;
+}
+
+#endif
+}
+
 #ifdef HAVE_CLAMDFFT
 
 namespace cv {
@@ -1769,6 +2063,43 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows )
 
     Mat dst = _dst.getMat();
 
+#if defined USE_IPP_DFT && !defined HAVE_IPP_ICV_ONLY
+
+    if ((src.depth() == CV_32F) && (src.total()>(int)(1<<6)))
+        if ((flags & DFT_ROWS) == 0)
+        {
+            if (!real_transform)
+            {
+                if (ippi_DFT_C_32F(src,dst, inv, ipp_norm_flag))
+                    return;
+                setIppErrorStatus();
+            }
+            else if (inv || !(flags & DFT_COMPLEX_OUTPUT))
+            {
+                if (ippi_DFT_R_32F(src,dst, inv, ipp_norm_flag))
+                    return;
+                setIppErrorStatus();
+            }
+        }
+        else
+        {
+            if (!real_transform)
+            {
+                ippiDFT_C_Func ippiFunc = inv ? (ippiDFT_C_Func)ippiDFTInv_CToC_32fc_C1R : (ippiDFT_C_Func)ippiDFTFwd_CToC_32fc_C1R;
+                if (Dft_C_IPPLoop(src,dst, IPPDFT_C_Functor(ippiFunc),ipp_norm_flag))
+                    return;
+                setIppErrorStatus();
+            }
+            else if (inv || !(flags & DFT_COMPLEX_OUTPUT))
+            {
+                ippiDFT_R_Func ippiFunc = inv ? (ippiDFT_R_Func)ippiDFTInv_PackToR_32f_C1R : (ippiDFT_R_Func)ippiDFTFwd_RToPack_32f_C1R;
+                if (Dft_R_IPPLoop(src,dst, IPPDFT_R_Functor(ippiFunc),ipp_norm_flag))
+                    return;
+                setIppErrorStatus();
+            }
+        }
+#endif
+
     if( !real_transform )
         elem_size = complex_elem_size;
 
index 2461394..c094ef7 100644 (file)
@@ -140,7 +140,7 @@ Saves an image to a specified file.
 The function ``imwrite`` saves the image to the specified file. The image format is chosen based on the ``filename`` extension (see
 :ocv:func:`imread` for the list of extensions). Only 8-bit (or 16-bit unsigned (``CV_16U``) in case of PNG, JPEG 2000, and TIFF) single-channel or 3-channel (with 'BGR' channel order) images can be saved using this function. If the format, depth or channel order is different, use
 :ocv:func:`Mat::convertTo` , and
-:ocv:func:`cvtColor` to convert it before saving. Or, use the universal XML I/O functions to save the image to XML or YAML format.
+:ocv:func:`cvtColor` to convert it before saving. Or, use the universal :ocv:class:`FileStorage` I/O functions to save the image to XML or YAML format.
 
 It is possible to store PNG images with an alpha channel using this function. To do this, create 8-bit (or 16-bit) 4-channel image BGRA, where the alpha channel goes last. Fully transparent pixels should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535. The sample below shows how to create such a BGRA image and store to PNG file. It also demonstrates how to set custom compression parameters ::
 
index d845953..46e070a 100644 (file)
@@ -318,7 +318,7 @@ public:
     virtual bool open( int index );
     virtual void close();
     virtual double getProperty(int);
-    virtual bool setProperty(int, double) { return false; }
+    virtual bool setProperty(int, double);
     virtual bool grabFrame();
     virtual IplImage* retrieveFrame(int);
     virtual int getCaptureDomain() { return CV_CAP_VFW; } // Return the type of the capture object: CV_CAP_VFW, etc...
@@ -332,6 +332,8 @@ protected:
     HWND   capWnd;
     VIDEOHDR* hdr;
     DWORD  fourcc;
+    int width, height;
+    int widthSet, heightSet;
     HIC    hic;
     IplImage* frame;
 };
@@ -345,6 +347,8 @@ void CvCaptureCAM_VFW::init()
     fourcc = 0;
     hic = 0;
     frame = 0;
+    width = height = -1;
+    widthSet = heightSet = 0;
 }
 
 void CvCaptureCAM_VFW::closeHIC()
@@ -407,16 +411,43 @@ bool CvCaptureCAM_VFW::open( int wIndex )
 
         memset( &caps, 0, sizeof(caps));
         capDriverGetCaps( hWndC, &caps, sizeof(caps));
-        ::MoveWindow( hWndC, 0, 0, 320, 240, TRUE );
+        CAPSTATUS status = {};
+        capGetStatus(hWndC, &status, sizeof(status));
+        ::SetWindowPos(hWndC, NULL, 0, 0, status.uiImageWidth, status.uiImageHeight, SWP_NOZORDER|SWP_NOMOVE);
         capSetUserData( hWndC, (size_t)this );
         capSetCallbackOnFrame( hWndC, frameCallback );
         CAPTUREPARMS p;
         capCaptureGetSetup(hWndC,&p,sizeof(CAPTUREPARMS));
-        p.dwRequestMicroSecPerFrame = 66667/2;
+        p.dwRequestMicroSecPerFrame = 66667/2; // 30 FPS
         capCaptureSetSetup(hWndC,&p,sizeof(CAPTUREPARMS));
         //capPreview( hWndC, 1 );
         capPreviewScale(hWndC,FALSE);
         capPreviewRate(hWndC,1);
+
+        // Get frame initial parameters.
+        const DWORD size = capGetVideoFormatSize(capWnd);
+        if( size > 0 )
+        {
+            unsigned char *pbi = new unsigned char[size];
+            if( pbi )
+            {
+                if( capGetVideoFormat(capWnd, pbi, size) == size )
+                {
+                    BITMAPINFOHEADER& vfmt = ((BITMAPINFO*)pbi)->bmiHeader;
+                    widthSet = vfmt.biWidth;
+                    heightSet = vfmt.biHeight;
+                    fourcc = vfmt.biCompression;
+                }
+                delete []pbi;
+            }
+        }
+        // And alternative way in case of failure.
+        if( widthSet == 0 || heightSet == 0 )
+        {
+            widthSet = status.uiImageWidth;
+            heightSet = status.uiImageHeight;
+        }
+
     }
     return capWnd != 0;
 }
@@ -439,10 +470,8 @@ void CvCaptureCAM_VFW::close()
 bool CvCaptureCAM_VFW::grabFrame()
 {
     if( capWnd )
-    {
-        SendMessage( capWnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0 );
-        return true;
-    }
+        return capGrabFrameNoStop(capWnd) == TRUE;
+
     return false;
 }
 
@@ -452,14 +481,13 @@ IplImage* CvCaptureCAM_VFW::retrieveFrame(int)
     BITMAPINFO vfmt;
     memset( &vfmt, 0, sizeof(vfmt));
     BITMAPINFOHEADER& vfmt0 = vfmt.bmiHeader;
-    int sz, prevWidth, prevHeight;
 
     if( !capWnd )
         return 0;
 
-    sz = capGetVideoFormat( capWnd, &vfmt, sizeof(vfmt));
-    prevWidth = frame ? frame->width : 0;
-    prevHeight = frame ? frame->height : 0;
+    const DWORD sz = capGetVideoFormat( capWnd, &vfmt, sizeof(vfmt));
+    const int prevWidth = frame ? frame->width : 0;
+    const int prevHeight = frame ? frame->height : 0;
 
     if( !hdr || hdr->lpData == 0 || sz == 0 )
         return 0;
@@ -470,8 +498,8 @@ IplImage* CvCaptureCAM_VFW::retrieveFrame(int)
         frame = cvCreateImage( cvSize( vfmt0.biWidth, vfmt0.biHeight ), 8, 3 );
     }
 
-    if( vfmt.bmiHeader.biCompression != BI_RGB ||
-        vfmt.bmiHeader.biBitCount != 24 )
+    if( vfmt0.biCompression != BI_RGB ||
+        vfmt0.biBitCount != 24 )
     {
         BITMAPINFOHEADER vfmt1 = icvBitmapHeader( vfmt0.biWidth, vfmt0.biHeight, 24 );
 
@@ -518,15 +546,106 @@ double CvCaptureCAM_VFW::getProperty( int property_id )
     switch( property_id )
     {
     case CV_CAP_PROP_FRAME_WIDTH:
-        return frame ? frame->width : 0;
+        return widthSet;
     case CV_CAP_PROP_FRAME_HEIGHT:
-        return frame ? frame->height : 0;
+        return heightSet;
     case CV_CAP_PROP_FOURCC:
         return fourcc;
+    case CV_CAP_PROP_FPS:
+        {
+            CAPTUREPARMS params = {};
+            if( capCaptureGetSetup(capWnd, &params, sizeof(params)) )
+                return 1e6 / params.dwRequestMicroSecPerFrame;
+        }
+        break;
+    default:
+        break;
     }
     return 0;
 }
 
+bool CvCaptureCAM_VFW::setProperty(int property_id, double value)
+{
+    bool handledSize = false;
+
+    switch( property_id )
+    {
+    case CV_CAP_PROP_FRAME_WIDTH:
+        width = cvRound(value);
+        handledSize = true;
+        break;
+    case CV_CAP_PROP_FRAME_HEIGHT:
+        height = cvRound(value);
+        handledSize = true;
+        break;
+    case CV_CAP_PROP_FOURCC:
+        break;
+    case CV_CAP_PROP_FPS:
+        if( value > 0 )
+        {
+            CAPTUREPARMS params;
+            if( capCaptureGetSetup(capWnd, &params, sizeof(params)) )
+            {
+                params.dwRequestMicroSecPerFrame = cvRound(1e6/value);
+                return capCaptureSetSetup(capWnd, &params, sizeof(params)) == TRUE;
+            }
+        }
+        break;
+    default:
+        break;
+    }
+
+    if ( handledSize )
+    {
+        // If both width and height are set then change frame size.
+        if( width > 0 && height > 0 )
+        {
+            const DWORD size = capGetVideoFormatSize(capWnd);
+            if( size == 0 )
+                return false;
+
+            unsigned char *pbi = new unsigned char[size];
+            if( !pbi )
+                return false;
+
+            if( capGetVideoFormat(capWnd, pbi, size) != size )
+            {
+                delete []pbi;
+                return false;
+            }
+
+            BITMAPINFOHEADER& vfmt = ((BITMAPINFO*)pbi)->bmiHeader;
+            bool success = true;
+            if( width != vfmt.biWidth || height != vfmt.biHeight )
+            {
+                // Change frame size.
+                vfmt.biWidth = width;
+                vfmt.biHeight = height;
+                vfmt.biSizeImage = height * ((width * vfmt.biBitCount + 31) / 32) * 4;
+                vfmt.biCompression = BI_RGB;
+                success = capSetVideoFormat(capWnd, pbi, size) == TRUE;
+            }
+            if( success )
+            {
+                // Adjust capture window size.
+                CAPSTATUS status = {};
+                capGetStatus(capWnd, &status, sizeof(status));
+                ::SetWindowPos(capWnd, NULL, 0, 0, status.uiImageWidth, status.uiImageHeight, SWP_NOZORDER|SWP_NOMOVE);
+                // Store frame size.
+                widthSet = width;
+                heightSet = height;
+            }
+            delete []pbi;
+            width = height = -1;
+
+            return success;
+        }
+
+        return true;
+    }
+
+    return false;
+}
 
 CvCapture* cvCreateCameraCapture_VFW( int index )
 {
index e76f8ab..4747c60 100644 (file)
@@ -1258,8 +1258,11 @@ static bool IPPMorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kerne
         default:
             return false;
         }
-
         #undef IPP_MORPH_CASE
+
+#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8
+        return false; /// It disables false positive warning in GCC 4.8.2
+#endif
 #endif
     }
 }
index d59cf75..416bd52 100644 (file)
@@ -184,8 +184,7 @@ PARAM_TEST_CASE(Resize, MatType, double, double, Interpolation, bool, int)
 
         Size srcRoiSize = randomSize(1, MAX_VALUE), dstRoiSize;
         // Make sure the width is a multiple of the requested value, and no more
-        srcRoiSize.width &= ~((widthMultiple * 2) - 1);
-        srcRoiSize.width += widthMultiple;
+        srcRoiSize.width += widthMultiple - 1 - (srcRoiSize.width - 1) % widthMultiple;
         dstRoiSize.width = cvRound(srcRoiSize.width * fx);
         dstRoiSize.height = cvRound(srcRoiSize.height * fy);
 
index 1d10715..36ab857 100644 (file)
@@ -85,7 +85,7 @@ OCL_PERF_TEST(HOGFixture, HOG)
     OCL_TEST_CYCLE() hog.detectMultiScale(src, found_locations);
 
     std::sort(found_locations.begin(), found_locations.end(), RectLess());
-    SANITY_CHECK(found_locations, 1 + DBL_EPSILON);
+    SANITY_CHECK(found_locations, 3);
 }
 
 }
index 4f0709b..72410cf 100644 (file)
@@ -17,10 +17,7 @@ PERF_TEST_P(TransformationType, findTransformECC, /*testing::ValuesIn(MotionType
             (int) MOTION_AFFINE, (int) MOTION_HOMOGRAPHY)
             )
 {
-
-    Mat inputImage = imread(getDataPath("cv/shared/fruits.png"),0);
-    Mat img;
-    resize(inputImage, img, Size(216,216));
+    Mat img = imread(getDataPath("cv/shared/fruits_ecc.png"),0);
     Mat templateImage;
 
     int transform_type = get<0>(GetParam());