Merge remote-tracking branch 'origin/2.4' into merge-2.4
authorRoman Donchenko <roman.donchenko@itseez.com>
Mon, 7 Apr 2014 10:59:34 +0000 (14:59 +0400)
committerRoman Donchenko <roman.donchenko@itseez.com>
Mon, 7 Apr 2014 10:59:34 +0000 (14:59 +0400)
Conflicts:
modules/core/include/opencv2/core/version.hpp
modules/core/src/out.cpp
modules/cudaimgproc/test/test_hough.cpp
modules/gpu/doc/introduction.rst
modules/gpu/perf/perf_imgproc.cpp
modules/gpu/src/generalized_hough.cpp
modules/nonfree/perf/perf_main.cpp

1  2 
doc/tutorials/tutorials.rst
doc/tutorials/video/table_of_content_video/table_of_content_video.rst
modules/contrib/doc/facerec/facerec_api.rst
modules/core/src/out.cpp
modules/cuda/doc/introduction.rst
modules/cudabgsegm/test/test_bgsegm.cpp

Simple merge
index dcebcd7e24a098f2a78c65deaf60d4dc337d928a,ddcad0c7000ad6f98302164fc9ca217e605f5be7..8ec170f408d5b409aae1749a1dd54a448ac84e3d
@@@ -3,28 -3,9 +3,28 @@@
  *video* module. Video analysis
  -----------------------------------------------------------
  
- Look here in order to find use on your video stream algoritms like: motion extraction, feature tracking and foreground extractions.
+ Look here in order to find use on your video stream algorithms like: motion extraction, feature tracking and foreground extractions.
  
 -.. include:: ../../definitions/noContent.rst
 +.. include:: ../../definitions/tocDefinitions.rst
 +
 ++
 +  .. tabularcolumns:: m{100pt} m{300pt}
 +  .. cssclass:: toctableopencv
 +
 +  =============== ======================================================
 +   |BgSub|        **Title:** :ref:`Background_Subtraction`
 +
 +                  *Compatibility:* > OpenCV 2.4.6
 +
 +                  *Author:* |Author_DomenicoB|
 +
 +                  We will learn how to extract foreground masks from both videos and sequences of images and to show them.
 +
 +  =============== ======================================================
 +
 +  .. |BgSub| image:: images/Background_Subtraction_Tutorial_Cover.jpg
 +                   :height: 90pt
 +                   :width:  90pt
  
  .. raw:: latex
  
index 3ed454ebfa869931554917dc799d997e66edb004,a2894b7006a341f368e92b6f57e35c3319ed8ba8..d639ac2126aab5391893377f152174852b040685
  //M*/
  
  #include "precomp.hpp"
 -#include <iterator>
  
 -namespace cv
 -{
 -
 -static inline char getCloseBrace(char c)
 +namespace
  {
 -    return c == '[' ? ']' : c == '(' ? ')' : c == '{' ? '}' : '\0';
 -}
 -
 -
 -template<typename _Tp> static void writeElems(std::ostream& out, const _Tp* data,
 -                                              int nelems, int cn, char obrace, char cbrace)
 -{
 -    typedef typename DataType<_Tp>::work_type _WTp;
 -    nelems *= cn;
 -    for(int i = 0; i < nelems; i += cn)
 +    class FormattedImpl : public cv::Formatted
      {
 -        if(cn == 1)
 +        enum { STATE_PROLOGUE, STATE_EPILOGUE, STATE_ROW_OPEN, STATE_ROW_CLOSE, STATE_CN_OPEN, STATE_CN_CLOSE, STATE_VALUE, STATE_FINISHED,
 +               STATE_LINE_SEPARATOR, STATE_CN_SEPARATOR, STATE_VALUE_SEPARATOR };
 +        enum {BRACE_ROW_OPEN = 0, BRACE_ROW_CLOSE = 1, BRACE_ROW_SEP=2, BRACE_CN_OPEN=3, BRACE_CN_CLOSE=4 };
 +
 +        char floatFormat[8];
 +        char buf[32];   // enough for double with precision up to 20
 +
 +        cv::Mat mtx;
 +        int mcn; // == mtx.channels()
 +        bool singleLine;
 +
 +        int state;
 +        int row;
 +        int col;
 +        int cn;
 +
 +        cv::String prologue;
 +        cv::String epilogue;
 +        char braces[5];
 +
 +        void (FormattedImpl::*valueToStr)();
 +        void valueToStr8u()  { sprintf(buf, "%3d", (int)mtx.ptr<uchar>(row, col)[cn]); }
 +        void valueToStr8s()  { sprintf(buf, "%3d", (int)mtx.ptr<schar>(row, col)[cn]); }
 +        void valueToStr16u() { sprintf(buf, "%d", (int)mtx.ptr<ushort>(row, col)[cn]); }
 +        void valueToStr16s() { sprintf(buf, "%d", (int)mtx.ptr<short>(row, col)[cn]); }
 +        void valueToStr32s() { sprintf(buf, "%d", mtx.ptr<int>(row, col)[cn]); }
 +        void valueToStr32f() { sprintf(buf, floatFormat, mtx.ptr<float>(row, col)[cn]); }
 +        void valueToStr64f() { sprintf(buf, floatFormat, mtx.ptr<double>(row, col)[cn]); }
 +        void valueToStrOther() { buf[0] = 0; }
 +
 +    public:
 +
 +        FormattedImpl(cv::String pl, cv::String el, cv::Mat m, char br[5], bool sLine, int precision)
          {
 -            out << (_WTp)data[i] << (i+1 < nelems ? ", " : "");
 -            continue;
 +            prologue = pl;
 +            epilogue = el;
 +            mtx = m;
 +            mcn = m.channels();
 +            memcpy(braces, br, 5);
 +            state = STATE_PROLOGUE;
 +            singleLine = sLine;
 +
 +            if (precision < 0)
 +            {
 +                floatFormat[0] = '%';
 +                floatFormat[1] = 'a';
 +                floatFormat[2] = 0;
 +            }
 +            else
 +            {
 +                sprintf(floatFormat, "%%.%dg", std::min(precision, 20));
 +            }
 +
 +            switch(mtx.depth())
 +            {
 +                case CV_8U:  valueToStr = &FormattedImpl::valueToStr8u; break;
 +                case CV_8S:  valueToStr = &FormattedImpl::valueToStr8s; break;
 +                case CV_16U: valueToStr = &FormattedImpl::valueToStr16u; break;
 +                case CV_16S: valueToStr = &FormattedImpl::valueToStr16s; break;
 +                case CV_32S: valueToStr = &FormattedImpl::valueToStr32s; break;
 +                case CV_32F: valueToStr = &FormattedImpl::valueToStr32f; break;
 +                case CV_64F: valueToStr = &FormattedImpl::valueToStr64f; break;
 +                default:     valueToStr = &FormattedImpl::valueToStrOther; break;
 +            }
          }
 -        out << obrace;
 -        for(int j = 0; j < cn; j++)
 -            out << (_WTp)data[i + j] << (j+1 < cn ? ", " : "");
 -        out << cbrace << (i+cn < nelems ? ", " : "");
 -    }
 -}
  
 +        void reset()
 +        {
 +            state = STATE_PROLOGUE;
 +        }
  
 -static void writeElems(std::ostream& out, const void* data, int nelems, int type, char brace)
 -{
 -    int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
 -    char cbrace = ' ';
 -    if(!brace || isspace(brace))
 -    {
 -        nelems *= cn;
 -        cn = 1;
 -    }
 -    else
 -        cbrace = getCloseBrace(brace);
 -    if(depth == CV_8U)
 -        writeElems(out, (const uchar*)data, nelems, cn, brace, cbrace);
 -    else if(depth == CV_8S)
 -        writeElems(out, (const schar*)data, nelems, cn, brace, cbrace);
 -    else if(depth == CV_16U)
 -        writeElems(out, (const ushort*)data, nelems, cn, brace, cbrace);
 -    else if(depth == CV_16S)
 -        writeElems(out, (const short*)data, nelems, cn, brace, cbrace);
 -    else if(depth == CV_32S)
 -        writeElems(out, (const int*)data, nelems, cn, brace, cbrace);
 -    else if(depth == CV_32F)
 -    {
 -        std::streamsize pp = out.precision();
 -        out.precision(8);
 -        writeElems(out, (const float*)data, nelems, cn, brace, cbrace);
 -        out.precision(pp);
 -    }
 -    else if(depth == CV_64F)
 -    {
 -        std::streamsize pp = out.precision();
 -        out.precision(16);
 -        writeElems(out, (const double*)data, nelems, cn, brace, cbrace);
 -        out.precision(pp);
 -    }
 -    else
 -        CV_Error(CV_StsUnsupportedFormat, "");
 -}
 -
 +        const char* next()
 +        {
 +            switch(state)
 +            {
 +                case STATE_PROLOGUE:
 +                    row = 0;
 +                    if (mtx.empty())
 +                        state = STATE_EPILOGUE;
 +                    else
 +                        state = STATE_ROW_OPEN;
 +                    return prologue.c_str();
 +                case STATE_EPILOGUE:
 +                    state = STATE_FINISHED;
 +                    return epilogue.c_str();
 +                case STATE_ROW_OPEN:
 +                    col = 0;
 +                    state = STATE_CN_OPEN;
 +                    {
 +                        size_t pos = 0;
 +                        if (row > 0)
 +                            while(pos < prologue.size() && pos < sizeof(buf) - 2)
 +                                buf[pos++] = ' ';
 +                        if (braces[BRACE_ROW_OPEN])
 +                            buf[pos++] = braces[BRACE_ROW_OPEN];
 +                        if(!pos)
 +                            return next();
 +                        buf[pos] = 0;
 +                    }
 +                    return buf;
 +                case STATE_ROW_CLOSE:
 +                    state = STATE_LINE_SEPARATOR;
 +                    ++row;
 +                    if (braces[BRACE_ROW_CLOSE])
 +                    {
 +                        buf[0] = braces[BRACE_ROW_CLOSE];
 +                        buf[1] = row < mtx.rows ? ',' : '\0';
 +                        buf[2] = 0;
 +                        return buf;
 +                    }
 +                    else if(braces[BRACE_ROW_SEP] && row < mtx.rows)
 +                    {
 +                        buf[0] = braces[BRACE_ROW_SEP];
 +                        buf[1] = 0;
 +                        return buf;
 +                    }
 +                    return next();
 +                case STATE_CN_OPEN:
 +                    cn = 0;
 +                    state = STATE_VALUE;
 +                    if (mcn > 1 && braces[BRACE_CN_OPEN])
 +                    {
 +                        buf[0] = braces[BRACE_CN_OPEN];
 +                        buf[1] = 0;
 +                        return buf;
 +                    }
 +                    return next();
 +                case STATE_CN_CLOSE:
 +                    ++col;
 +                    if (col >= mtx.cols)
 +                        state = STATE_ROW_CLOSE;
 +                    else
 +                        state = STATE_CN_SEPARATOR;
 +                    if (mcn > 1 && braces[BRACE_CN_CLOSE])
 +                    {
 +                        buf[0] = braces[BRACE_CN_CLOSE];
 +                        buf[1] = 0;
 +                        return buf;
 +                    }
 +                    return next();
 +                case STATE_VALUE:
 +                    (this->*valueToStr)();
 +                    if (++cn >= mcn)
 +                        state = STATE_CN_CLOSE;
 +                    else
 +                        state = STATE_VALUE_SEPARATOR;
 +                    return buf;
 +                case STATE_FINISHED:
 +                    return 0;
 +                case STATE_LINE_SEPARATOR:
 +                    if (row >= mtx.rows)
 +                    {
 +                        state = STATE_EPILOGUE;
 +                        return next();
 +                    }
 +                    state = STATE_ROW_OPEN;
 +                    buf[0] = singleLine ? ' ' : '\n';
 +                    buf[1] = 0;
 +                    return buf;
 +                case STATE_CN_SEPARATOR:
 +                    state = STATE_CN_OPEN;
 +                    buf[0] = ',';
 +                    buf[1] = ' ';
 +                    buf[2] = 0;
 +                    return buf;
 +                case STATE_VALUE_SEPARATOR:
 +                    state = STATE_VALUE;
 +                    buf[0] = ',';
 +                    buf[1] = ' ';
 +                    buf[2] = 0;
 +                    return buf;
 +            }
 +            return 0;
 +        }
 +    };
  
 -static void writeMat(std::ostream& out, const Mat& m, char rowsep, char elembrace, bool singleLine)
 -{
 -    CV_Assert(m.dims <= 2);
 -    int type = m.type();
 +    class FormatterBase : public cv::Formatter
 +    {
 +    public:
 +        FormatterBase() : prec32f(8), prec64f(16), multiline(true) {}
  
 -    char crowbrace = getCloseBrace(rowsep);
 -    char orowbrace = crowbrace ? rowsep : '\0';
 +        void set32fPrecision(int p)
 +        {
 +            prec32f = p;
 +        }
  
 -    if( orowbrace || isspace(rowsep) )
 -        rowsep = '\0';
 +        void set64fPrecision(int p)
 +        {
 +            prec64f = p;
 +        }
  
 -    for( int i = 0; i < m.rows; i++ )
 -    {
 -        if(orowbrace)
 -            out << orowbrace;
 -        if( m.data )
 -            writeElems(out, m.ptr(i), m.cols, type, elembrace);
 -        if(orowbrace)
 -            out << crowbrace << (i+1 < m.rows ? ", " : "");
 -        if(i+1 < m.rows)
 +        void setMultiline(bool ml)
          {
 -            if(rowsep)
 -                out << rowsep << (singleLine ? " " : "");
 -            if(!singleLine)
 -                out << "\n  ";
 +            multiline = ml;
          }
 -    }
 -}
  
 -class MatlabFormatter : public Formatter
 -{
 -public:
 -    virtual ~MatlabFormatter() {}
 -    void write(std::ostream& out, const Mat& m, const int*, int) const
 -    {
 -        out << "[";
 -        writeMat(out, m, ';', ' ', m.rows == 1);
 -        out << "]";
 -    }
 +    protected:
 +        int prec32f;
 +        int prec64f;
 +        int multiline;
 +    };
  
 -    void write(std::ostream& out, const void* data, int nelems, int type, const int*, int) const
 +    class MatlabFormatter : public FormatterBase
      {
 -        writeElems(out, data, nelems, type, ' ');
 -    }
 -};
 +    public:
  
 -class PythonFormatter : public Formatter
 -{
 -public:
 -    virtual ~PythonFormatter() {}
 -    void write(std::ostream& out, const Mat& m, const int*, int) const
 -    {
 -        out << "[";
 -        writeMat(out, m, m.cols > 1 ? '[' : ' ', '[', m.rows*m.channels() == 1);
 -        out << "]";
 -    }
 +        cv::Ptr<cv::Formatted> format(const cv::Mat& mtx) const
 +        {
 +            char braces[5] = {'\0', '\0', ';', '\0', '\0'};
 +            return cv::makePtr<FormattedImpl>("[", "]", mtx, &*braces,
-                 mtx.cols == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f );
++                mtx.rows == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f );
 +        }
 +    };
  
 -    void write(std::ostream& out, const void* data, int nelems, int type, const int*, int) const
 +    class PythonFormatter : public FormatterBase
      {
 -        writeElems(out, data, nelems, type, '[');
 -    }
 -};
 +    public:
  
 -
 -class NumpyFormatter : public Formatter
 -{
 -public:
 -    virtual ~NumpyFormatter() {}
 -    void write(std::ostream& out, const Mat& m, const int*, int) const
 -    {
 -        static const char* numpyTypes[] =
 +        cv::Ptr<cv::Formatted> format(const cv::Mat& mtx) const
          {
 -            "uint8", "int8", "uint16", "int16", "int32", "float32", "float64", "uint64"
 -        };
 -        out << "array([";
 -        writeMat(out, m, m.cols > 1 ? '[' : ' ', '[', m.rows*m.channels() == 1);
 -        out << "], type='" << numpyTypes[m.depth()] << "')";
 -    }
 +            char braces[5] = {'[', ']', '\0', '[', ']'};
 +            if (mtx.cols == 1)
 +                braces[0] = braces[1] = '\0';
 +            return cv::makePtr<FormattedImpl>("[", "]", mtx, &*braces,
-                 mtx.cols*mtx.channels() == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f );
++                mtx.rows*mtx.channels() == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f );
 +        }
 +    };
  
 -    void write(std::ostream& out, const void* data, int nelems, int type, const int*, int) const
 +    class NumpyFormatter : public FormatterBase
      {
 -        writeElems(out, data, nelems, type, '[');
 -    }
 -};
 +    public:
  
-                 mtx.cols*mtx.channels() == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f );
 +        cv::Ptr<cv::Formatted> format(const cv::Mat& mtx) const
 +        {
 +            static const char* numpyTypes[] =
 +            {
 +                "uint8", "int8", "uint16", "int16", "int32", "float32", "float64", "uint64"
 +            };
 +            char braces[5] = {'[', ']', '\0', '[', ']'};
 +            if (mtx.cols == 1)
 +                braces[0] = braces[1] = '\0';
 +            return cv::makePtr<FormattedImpl>("array([",
 +                cv::format("], type='%s')", numpyTypes[mtx.depth()]), mtx, &*braces,
++                mtx.rows*mtx.channels() == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f );
 +        }
 +    };
  
 -class CSVFormatter : public Formatter
 -{
 -public:
 -    virtual ~CSVFormatter() {}
 -    void write(std::ostream& out, const Mat& m, const int*, int) const
 -    {
 -        writeMat(out, m, ' ', ' ', m.rows*m.channels() == 1);
 -        if(m.rows > 1)
 -            out << "\n";
 -    }
 -
 -    void write(std::ostream& out, const void* data, int nelems, int type, const int*, int) const
 +    class CSVFormatter : public FormatterBase
      {
 -        writeElems(out, data, nelems, type, ' ');
 -    }
 -};
 -
 +    public:
  
 -class CFormatter : public Formatter
 -{
 -public:
 -    virtual ~CFormatter() {}
 -    void write(std::ostream& out, const Mat& m, const int*, int) const
 -    {
 -        out << "{";
 -        writeMat(out, m, ',', ' ', m.rows==1);
 -        out << "}";
 -    }
 +        cv::Ptr<cv::Formatted> format(const cv::Mat& mtx) const
 +        {
 +            char braces[5] = {'\0', '\0', '\0', '\0', '\0'};
 +            return cv::makePtr<FormattedImpl>(cv::String(),
 +                mtx.rows > 1 ? cv::String("\n") : cv::String(), mtx, &*braces,
-                 mtx.cols*mtx.channels() == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f );
++                mtx.rows*mtx.channels() == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f );
 +        }
 +    };
  
 -    void write(std::ostream& out, const void* data, int nelems, int type, const int*, int) const
 +    class CFormatter : public FormatterBase
      {
 -        writeElems(out, data, nelems, type, ' ');
 -    }
 -};
 +    public:
  
-                 mtx.cols == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f );
 +        cv::Ptr<cv::Formatted> format(const cv::Mat& mtx) const
 +        {
 +            char braces[5] = {'\0', '\0', ',', '\0', '\0'};
 +            return cv::makePtr<FormattedImpl>("{", "}", mtx, &*braces,
++                mtx.rows == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f );
 +        }
 +    };
  
 -static MatlabFormatter matlabFormatter;
 -static PythonFormatter pythonFormatter;
 -static NumpyFormatter numpyFormatter;
 -static CSVFormatter csvFormatter;
 -static CFormatter cFormatter;
 +} // namespace
  
 -static const Formatter* g_defaultFormatter0 = &matlabFormatter;
 -static const Formatter* g_defaultFormatter = &matlabFormatter;
  
 -static bool my_streq(const char* a, const char* b)
 -{
 -    size_t i, alen = strlen(a), blen = strlen(b);
 -    if( alen != blen )
 -        return false;
 -    for( i = 0; i < alen; i++ )
 -        if( a[i] != b[i] && a[i] - 32 != b[i] )
 -            return false;
 -    return true;
 -}
 -
 -const Formatter* Formatter::get(const char* fmt)
 -{
 -    if(!fmt || my_streq(fmt, ""))
 -        return g_defaultFormatter;
 -    if( my_streq(fmt, "MATLAB"))
 -        return &matlabFormatter;
 -    if( my_streq(fmt, "CSV"))
 -        return &csvFormatter;
 -    if( my_streq(fmt, "PYTHON"))
 -        return &pythonFormatter;
 -    if( my_streq(fmt, "NUMPY"))
 -        return &numpyFormatter;
 -    if( my_streq(fmt, "C"))
 -        return &cFormatter;
 -    CV_Error(CV_StsBadArg, "Unknown formatter");
 -    return g_defaultFormatter;
 -}
 -
 -const Formatter* Formatter::setDefault(const Formatter* fmt)
 -{
 -    const Formatter* prevFmt = g_defaultFormatter;
 -    if(!fmt)
 -        fmt = g_defaultFormatter0;
 -    g_defaultFormatter = fmt;
 -    return prevFmt;
 -}
 -
 -Formatted::Formatted(const Mat& _m, const Formatter* _fmt,
 -                     const vector<int>& _params)
 -{
 -    mtx = _m;
 -    fmt = _fmt ? _fmt : Formatter::get();
 -    std::copy(_params.begin(), _params.end(), back_inserter(params));
 -}
 -
 -Formatted::Formatted(const Mat& _m, const Formatter* _fmt, const int* _params)
 +namespace cv
  {
 -    mtx = _m;
 -    fmt = _fmt ? _fmt : Formatter::get();
 +    Formatted::~Formatted() {}
 +    Formatter::~Formatter() {}
  
 -    if( _params )
 +    Ptr<Formatter> Formatter::get(int fmt)
      {
 -        int i, maxParams = 100;
 -        for(i = 0; i < maxParams && _params[i] != 0; i+=2)
 -            ;
 -        std::copy(_params, _params + i, back_inserter(params));
 +        switch(fmt)
 +        {
 +            case FMT_MATLAB:
 +                return makePtr<MatlabFormatter>();
 +            case FMT_CSV:
 +                return makePtr<CSVFormatter>();
 +            case FMT_PYTHON:
 +                return makePtr<PythonFormatter>();
 +            case FMT_NUMPY:
 +                return makePtr<NumpyFormatter>();
 +            case FMT_C:
 +                return makePtr<CFormatter>();
 +        }
 +        return makePtr<MatlabFormatter>();
      }
 -}
 -
 -}
 +} // cv
index 589a39fdc4d87c1a686705e37357434563d02091,0000000000000000000000000000000000000000..230a6f41e33d71b21f6bf0f86adcdabac6532f2f
mode 100644,000000..100644
--- /dev/null
@@@ -1,61 -1,0 +1,61 @@@
- Switching active devie can be done using :ocv:func:`cuda::setDevice()` function.  For more details please read Cuda C Programing Guide.
 +CUDA Module Introduction
 +========================
 +
 +.. highlight:: cpp
 +
 +
 +
 +General Information
 +-------------------
 +
 +The OpenCV CUDA module is a set of classes and functions to utilize CUDA computational capabilities. It is implemented using NVIDIA* CUDA* Runtime API and supports only NVIDIA GPUs. The OpenCV CUDA module includes utility functions, low-level vision primitives, and high-level algorithms. The utility functions and low-level primitives provide a powerful infrastructure for developing fast vision algorithms taking advantage of CUDA whereas the high-level functionality includes some state-of-the-art algorithms (such as stereo correspondence, face and people detectors, and others) ready to be used by the application developers.
 +
 +The CUDA module is designed as a host-level API. This means that if you have pre-compiled OpenCV CUDA binaries, you are not required to have the CUDA Toolkit installed or write any extra code to make use of the CUDA.
 +
 +The OpenCV CUDA module is designed for ease of use and does not require any knowledge of CUDA. Though, such a knowledge will certainly be useful to handle non-trivial cases or achieve the highest performance. It is helpful to understand the cost of various operations, what the GPU does, what the preferred data formats are, and so on. The CUDA module is an effective instrument for quick implementation of CUDA-accelerated computer vision algorithms. However, if your algorithm involves many simple operations, then, for the best possible performance, you may still need to write your own kernels to avoid extra write and read operations on the intermediate results.
 +
 +To enable CUDA support, configure OpenCV using ``CMake`` with ``WITH_CUDA=ON`` . When the flag is set and if CUDA is installed, the full-featured OpenCV CUDA module is built. Otherwise, the module is still built but at runtime all functions from the module throw
 +:ocv:class:`Exception` with ``CV_GpuNotSupported`` error code, except for
 +:ocv:func:`cuda::getCudaEnabledDeviceCount()`. The latter function returns zero GPU count in this case. Building OpenCV without CUDA support does not perform device code compilation, so it does not require the CUDA Toolkit installed. Therefore, using the
 +:ocv:func:`cuda::getCudaEnabledDeviceCount()` function, you can implement a high-level algorithm that will detect GPU presence at runtime and choose an appropriate implementation (CPU or GPU) accordingly.
 +
 +Compilation for Different NVIDIA* Platforms
 +-------------------------------------------
 +
 +NVIDIA* compiler enables generating binary code (cubin and fatbin) and intermediate code (PTX). Binary code often implies a specific GPU architecture and generation, so the compatibility with other GPUs is not guaranteed. PTX is targeted for a virtual platform that is defined entirely by the set of capabilities or features. Depending on the selected virtual platform, some of the instructions are emulated or disabled, even if the real hardware supports all the features.
 +
 +At the first call, the PTX code is compiled to binary code for the particular GPU using a JIT compiler. When the target GPU has a compute capability (CC) lower than the PTX code, JIT fails.
 +By default, the OpenCV CUDA module includes:
 +
 +*
 +    Binaries for compute capabilities 1.3 and 2.0 (controlled by ``CUDA_ARCH_BIN``     in ``CMake``)
 +
 +*
 +    PTX code for compute capabilities 1.1 and 1.3 (controlled by ``CUDA_ARCH_PTX``     in ``CMake``)
 +
 +This means that for devices with CC 1.3 and 2.0 binary images are ready to run. For all newer platforms, the PTX code for 1.3 is JIT'ed to a binary image. For devices with CC 1.1 and 1.2, the PTX for 1.1 is JIT'ed. For devices with CC 1.0, no code is available and the functions throw
 +:ocv:class:`Exception`. For platforms where JIT compilation is performed first, the run is slow.
 +
 +On a GPU with CC 1.0, you can still compile the CUDA module and most of the functions will run flawlessly. To achieve this, add "1.0" to the list of binaries, for example, ``CUDA_ARCH_BIN="1.0 1.3 2.0"`` . The functions that cannot be run on CC 1.0 GPUs throw an exception.
 +
 +You can always determine at runtime whether the OpenCV GPU-built binaries (or PTX code) are compatible with your GPU. The function
 +:ocv:func:`cuda::DeviceInfo::isCompatible` returns the compatibility status (true/false).
 +
 +Utilizing Multiple GPUs
 +-----------------------
 +
 +In the current version, each of the OpenCV CUDA algorithms can use only a single GPU. So, to utilize multiple GPUs, you have to manually distribute the work between GPUs.
++Switching active devie can be done using :ocv:func:`cuda::setDevice()` function.  For more details please read Cuda C Programming Guide.
 +
 +While developing algorithms for multiple GPUs, note a data passing overhead. For primitive functions and small images, it can be significant, which may eliminate all the advantages of having multiple GPUs. But for high-level algorithms, consider using multi-GPU acceleration. For example, the Stereo Block Matching algorithm has been successfully parallelized using the following algorithm:
 +
 +
 + 1.   Split each image of the stereo pair into two horizontal overlapping stripes.
 +
 +
 + 2.   Process each pair of stripes (from the left and right images) on a separate Fermi* GPU.
 +
 +
 + 3.   Merge the results into a single disparity map.
 +
 +With this algorithm, a dual GPU gave a 180% performance increase comparing to the single Fermi GPU. For a source code example, see https://github.com/Itseez/opencv/tree/master/samples/gpu/.
index 3597e2c10c84d598caaf6defd6e2291716aee2fa,0000000000000000000000000000000000000000..75d6d73a3f6bc0b29eac5ac5ef4f04692fb3c304
mode 100644,000000..100644
--- /dev/null
@@@ -1,391 -1,0 +1,391 @@@
-     ASSERT_MAT_NEAR(background_gold, background, 0);
 +/*M///////////////////////////////////////////////////////////////////////////////////////
 +//
 +//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
 +//
 +//  By downloading, copying, installing or using the software you agree to this license.
 +//  If you do not agree to this license, do not download, install,
 +//  copy or use the software.
 +//
 +//
 +//                           License Agreement
 +//                For Open Source Computer Vision Library
 +//
 +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
 +// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
 +// Third party copyrights are property of their respective owners.
 +//
 +// Redistribution and use in source and binary forms, with or without modification,
 +// are permitted provided that the following conditions are met:
 +//
 +//   * Redistribution's of source code must retain the above copyright notice,
 +//     this list of conditions and the following disclaimer.
 +//
 +//   * Redistribution's in binary form must reproduce the above copyright notice,
 +//     this list of conditions and the following disclaimer in the documentation
 +//     and/or other materials provided with the distribution.
 +//
 +//   * The name of the copyright holders may not be used to endorse or promote products
 +//     derived from this software without specific prior written permission.
 +//
 +// This software is provided by the copyright holders and contributors "as is" and
 +// any express or implied warranties, including, but not limited to, the implied
 +// warranties of merchantability and fitness for a particular purpose are disclaimed.
 +// In no event shall the Intel Corporation or contributors be liable for any direct,
 +// indirect, incidental, special, exemplary, or consequential damages
 +// (including, but not limited to, procurement of substitute goods or services;
 +// loss of use, data, or profits; or business interruption) however caused
 +// and on any theory of liability, whether in contract, strict liability,
 +// or tort (including negligence or otherwise) arising in any way out of
 +// the use of this software, even if advised of the possibility of such damage.
 +//
 +//M*/
 +
 +#include "test_precomp.hpp"
 +
 +#ifdef HAVE_OPENCV_LEGACY
 +#  include "opencv2/legacy.hpp"
 +#endif
 +
 +#ifdef HAVE_CUDA
 +
 +using namespace cvtest;
 +
 +#if defined(HAVE_XINE)         || \
 +    defined(HAVE_GSTREAMER)    || \
 +    defined(HAVE_QUICKTIME)    || \
 +    defined(HAVE_QTKIT)        || \
 +    defined(HAVE_AVFOUNDATION) || \
 +    defined(HAVE_FFMPEG)       || \
 +    defined(WIN32) /* assume that we have ffmpeg */
 +
 +#  define BUILD_WITH_VIDEO_INPUT_SUPPORT 1
 +#else
 +#  define BUILD_WITH_VIDEO_INPUT_SUPPORT 0
 +#endif
 +
 +//////////////////////////////////////////////////////
 +// FGDStatModel
 +
 +#if BUILD_WITH_VIDEO_INPUT_SUPPORT && defined(HAVE_OPENCV_LEGACY)
 +
 +namespace cv
 +{
 +    template<> void DefaultDeleter<CvBGStatModel>::operator ()(CvBGStatModel* obj) const
 +    {
 +        cvReleaseBGStatModel(&obj);
 +    }
 +}
 +
 +PARAM_TEST_CASE(FGDStatModel, cv::cuda::DeviceInfo, std::string)
 +{
 +    cv::cuda::DeviceInfo devInfo;
 +    std::string inputFile;
 +
 +    virtual void SetUp()
 +    {
 +        devInfo = GET_PARAM(0);
 +        cv::cuda::setDevice(devInfo.deviceID());
 +
 +        inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "video/" + GET_PARAM(1);
 +    }
 +};
 +
 +CUDA_TEST_P(FGDStatModel, Update)
 +{
 +    cv::VideoCapture cap(inputFile);
 +    ASSERT_TRUE(cap.isOpened());
 +
 +    cv::Mat frame;
 +    cap >> frame;
 +    ASSERT_FALSE(frame.empty());
 +
 +    IplImage ipl_frame = frame;
 +    cv::Ptr<CvBGStatModel> model(cvCreateFGDStatModel(&ipl_frame));
 +
 +    cv::cuda::GpuMat d_frame(frame);
 +    cv::Ptr<cv::cuda::BackgroundSubtractorFGD> d_fgd = cv::cuda::createBackgroundSubtractorFGD();
 +    cv::cuda::GpuMat d_foreground, d_background;
 +    std::vector< std::vector<cv::Point> > foreground_regions;
 +    d_fgd->apply(d_frame, d_foreground);
 +
 +    for (int i = 0; i < 5; ++i)
 +    {
 +        cap >> frame;
 +        ASSERT_FALSE(frame.empty());
 +
 +        ipl_frame = frame;
 +        int gold_count = cvUpdateBGStatModel(&ipl_frame, model);
 +
 +        d_frame.upload(frame);
 +        d_fgd->apply(d_frame, d_foreground);
 +        d_fgd->getBackgroundImage(d_background);
 +        d_fgd->getForegroundRegions(foreground_regions);
 +        int count = (int) foreground_regions.size();
 +
 +        cv::Mat gold_background = cv::cvarrToMat(model->background);
 +        cv::Mat gold_foreground = cv::cvarrToMat(model->foreground);
 +
 +        ASSERT_MAT_NEAR(gold_background, d_background, 1.0);
 +        ASSERT_MAT_NEAR(gold_foreground, d_foreground, 0.0);
 +        ASSERT_EQ(gold_count, count);
 +    }
 +}
 +
 +INSTANTIATE_TEST_CASE_P(CUDA_BgSegm, FGDStatModel, testing::Combine(
 +    ALL_DEVICES,
 +    testing::Values(std::string("768x576.avi"))));
 +
 +#endif
 +
 +//////////////////////////////////////////////////////
 +// MOG
 +
 +#if BUILD_WITH_VIDEO_INPUT_SUPPORT
 +
 +namespace
 +{
 +    IMPLEMENT_PARAM_CLASS(UseGray, bool)
 +    IMPLEMENT_PARAM_CLASS(LearningRate, double)
 +}
 +
 +PARAM_TEST_CASE(MOG, cv::cuda::DeviceInfo, std::string, UseGray, LearningRate, UseRoi)
 +{
 +    cv::cuda::DeviceInfo devInfo;
 +    std::string inputFile;
 +    bool useGray;
 +    double learningRate;
 +    bool useRoi;
 +
 +    virtual void SetUp()
 +    {
 +        devInfo = GET_PARAM(0);
 +        cv::cuda::setDevice(devInfo.deviceID());
 +
 +        inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "video/" + GET_PARAM(1);
 +
 +        useGray = GET_PARAM(2);
 +
 +        learningRate = GET_PARAM(3);
 +
 +        useRoi = GET_PARAM(4);
 +    }
 +};
 +
 +CUDA_TEST_P(MOG, Update)
 +{
 +    cv::VideoCapture cap(inputFile);
 +    ASSERT_TRUE(cap.isOpened());
 +
 +    cv::Mat frame;
 +    cap >> frame;
 +    ASSERT_FALSE(frame.empty());
 +
 +    cv::Ptr<cv::BackgroundSubtractorMOG> mog = cv::cuda::createBackgroundSubtractorMOG();
 +    cv::cuda::GpuMat foreground = createMat(frame.size(), CV_8UC1, useRoi);
 +
 +    cv::Ptr<cv::BackgroundSubtractorMOG> mog_gold = cv::createBackgroundSubtractorMOG();
 +    cv::Mat foreground_gold;
 +
 +    for (int i = 0; i < 10; ++i)
 +    {
 +        cap >> frame;
 +        ASSERT_FALSE(frame.empty());
 +
 +        if (useGray)
 +        {
 +            cv::Mat temp;
 +            cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY);
 +            cv::swap(temp, frame);
 +        }
 +
 +        mog->apply(loadMat(frame, useRoi), foreground, learningRate);
 +
 +        mog_gold->apply(frame, foreground_gold, learningRate);
 +
 +        ASSERT_MAT_NEAR(foreground_gold, foreground, 0.0);
 +    }
 +}
 +
 +INSTANTIATE_TEST_CASE_P(CUDA_BgSegm, MOG, testing::Combine(
 +    ALL_DEVICES,
 +    testing::Values(std::string("768x576.avi")),
 +    testing::Values(UseGray(true), UseGray(false)),
 +    testing::Values(LearningRate(0.0), LearningRate(0.01)),
 +    WHOLE_SUBMAT));
 +
 +#endif
 +
 +//////////////////////////////////////////////////////
 +// MOG2
 +
 +#if BUILD_WITH_VIDEO_INPUT_SUPPORT
 +
 +namespace
 +{
 +    IMPLEMENT_PARAM_CLASS(DetectShadow, bool)
 +}
 +
 +PARAM_TEST_CASE(MOG2, cv::cuda::DeviceInfo, std::string, UseGray, DetectShadow, UseRoi)
 +{
 +    cv::cuda::DeviceInfo devInfo;
 +    std::string inputFile;
 +    bool useGray;
 +    bool detectShadow;
 +    bool useRoi;
 +
 +    virtual void SetUp()
 +    {
 +        devInfo = GET_PARAM(0);
 +        cv::cuda::setDevice(devInfo.deviceID());
 +
 +        inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "video/" + GET_PARAM(1);
 +        useGray = GET_PARAM(2);
 +        detectShadow = GET_PARAM(3);
 +        useRoi = GET_PARAM(4);
 +    }
 +};
 +
 +CUDA_TEST_P(MOG2, Update)
 +{
 +    cv::VideoCapture cap(inputFile);
 +    ASSERT_TRUE(cap.isOpened());
 +
 +    cv::Mat frame;
 +    cap >> frame;
 +    ASSERT_FALSE(frame.empty());
 +
 +    cv::Ptr<cv::BackgroundSubtractorMOG2> mog2 = cv::cuda::createBackgroundSubtractorMOG2();
 +    mog2->setDetectShadows(detectShadow);
 +    cv::cuda::GpuMat foreground = createMat(frame.size(), CV_8UC1, useRoi);
 +
 +    cv::Ptr<cv::BackgroundSubtractorMOG2> mog2_gold = cv::createBackgroundSubtractorMOG2();
 +    mog2_gold->setDetectShadows(detectShadow);
 +    cv::Mat foreground_gold;
 +
 +    for (int i = 0; i < 10; ++i)
 +    {
 +        cap >> frame;
 +        ASSERT_FALSE(frame.empty());
 +
 +        if (useGray)
 +        {
 +            cv::Mat temp;
 +            cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY);
 +            cv::swap(temp, frame);
 +        }
 +
 +        mog2->apply(loadMat(frame, useRoi), foreground);
 +
 +        mog2_gold->apply(frame, foreground_gold);
 +
 +        if (detectShadow)
 +        {
 +            ASSERT_MAT_SIMILAR(foreground_gold, foreground, 1e-2);
 +        }
 +        else
 +        {
 +            ASSERT_MAT_NEAR(foreground_gold, foreground, 0);
 +        }
 +    }
 +}
 +
 +CUDA_TEST_P(MOG2, getBackgroundImage)
 +{
 +    if (useGray)
 +        return;
 +
 +    cv::VideoCapture cap(inputFile);
 +    ASSERT_TRUE(cap.isOpened());
 +
 +    cv::Mat frame;
 +
 +    cv::Ptr<cv::BackgroundSubtractorMOG2> mog2 = cv::cuda::createBackgroundSubtractorMOG2();
 +    mog2->setDetectShadows(detectShadow);
 +    cv::cuda::GpuMat foreground;
 +
 +    cv::Ptr<cv::BackgroundSubtractorMOG2> mog2_gold = cv::createBackgroundSubtractorMOG2();
 +    mog2_gold->setDetectShadows(detectShadow);
 +    cv::Mat foreground_gold;
 +
 +    for (int i = 0; i < 10; ++i)
 +    {
 +        cap >> frame;
 +        ASSERT_FALSE(frame.empty());
 +
 +        mog2->apply(loadMat(frame, useRoi), foreground);
 +
 +        mog2_gold->apply(frame, foreground_gold);
 +    }
 +
 +    cv::cuda::GpuMat background = createMat(frame.size(), frame.type(), useRoi);
 +    mog2->getBackgroundImage(background);
 +
 +    cv::Mat background_gold;
 +    mog2_gold->getBackgroundImage(background_gold);
 +
++    ASSERT_MAT_NEAR(background_gold, background, 1);
 +}
 +
 +INSTANTIATE_TEST_CASE_P(CUDA_BgSegm, MOG2, testing::Combine(
 +    ALL_DEVICES,
 +    testing::Values(std::string("768x576.avi")),
 +    testing::Values(UseGray(true), UseGray(false)),
 +    testing::Values(DetectShadow(true), DetectShadow(false)),
 +    WHOLE_SUBMAT));
 +
 +#endif
 +
 +//////////////////////////////////////////////////////
 +// GMG
 +
 +PARAM_TEST_CASE(GMG, cv::cuda::DeviceInfo, cv::Size, MatDepth, Channels, UseRoi)
 +{
 +};
 +
 +CUDA_TEST_P(GMG, Accuracy)
 +{
 +    const cv::cuda::DeviceInfo devInfo = GET_PARAM(0);
 +    cv::cuda::setDevice(devInfo.deviceID());
 +    const cv::Size size = GET_PARAM(1);
 +    const int depth = GET_PARAM(2);
 +    const int channels = GET_PARAM(3);
 +    const bool useRoi = GET_PARAM(4);
 +
 +    const int type = CV_MAKE_TYPE(depth, channels);
 +
 +    const cv::Mat zeros(size, CV_8UC1, cv::Scalar::all(0));
 +    const cv::Mat fullfg(size, CV_8UC1, cv::Scalar::all(255));
 +
 +    cv::Mat frame = randomMat(size, type, 0, 100);
 +    cv::cuda::GpuMat d_frame = loadMat(frame, useRoi);
 +
 +    cv::Ptr<cv::BackgroundSubtractorGMG> gmg = cv::cuda::createBackgroundSubtractorGMG();
 +    gmg->setNumFrames(5);
 +    gmg->setSmoothingRadius(0);
 +
 +    cv::cuda::GpuMat d_fgmask = createMat(size, CV_8UC1, useRoi);
 +
 +    for (int i = 0; i < gmg->getNumFrames(); ++i)
 +    {
 +        gmg->apply(d_frame, d_fgmask);
 +
 +        // fgmask should be entirely background during training
 +        ASSERT_MAT_NEAR(zeros, d_fgmask, 0);
 +    }
 +
 +    frame = randomMat(size, type, 160, 255);
 +    d_frame = loadMat(frame, useRoi);
 +    gmg->apply(d_frame, d_fgmask);
 +
 +    // now fgmask should be entirely foreground
 +    ASSERT_MAT_NEAR(fullfg, d_fgmask, 0);
 +}
 +
 +INSTANTIATE_TEST_CASE_P(CUDA_BgSegm, GMG, testing::Combine(
 +    ALL_DEVICES,
 +    DIFFERENT_SIZES,
 +    testing::Values(MatType(CV_8U), MatType(CV_16U), MatType(CV_32F)),
 +    testing::Values(Channels(1), Channels(3), Channels(4)),
 +    WHOLE_SUBMAT));
 +
 +#endif // HAVE_CUDA