//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
--- /dev/null
- 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