Skip to content

Commit ffe99b2

Browse files
committed
Merge branch '4.x' into coordinate
2 parents 6348a05 + a886fa5 commit ffe99b2

File tree

3 files changed

+60
-57
lines changed

3 files changed

+60
-57
lines changed

modules/bgsegm/include/opencv2/bgsegm.hpp

+13
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,19 @@ CV_EXPORTS_W Ptr<BackgroundSubtractorMOG>
9999
class CV_EXPORTS_W BackgroundSubtractorGMG : public BackgroundSubtractor
100100
{
101101
public:
102+
// BackgroundSubtractor interface
103+
/** @brief Computes a foreground mask.
104+
105+
@param image Next video frame of type CV_8UC(n),CV_8SC(n),CV_16UC(n),CV_16SC(n),CV_32SC(n),CV_32FC(n),CV_64FC(n), where n is 1,2,3,4.
106+
@param fgmask The output foreground mask as an 8-bit binary image.
107+
@param learningRate The value between 0 and 1 that indicates how fast the background model is
108+
learnt. Negative parameter value makes the algorithm to use some automatically chosen learning
109+
rate. 0 means that the background model is not updated at all, 1 means that the background model
110+
is completely reinitialized from the last frame.
111+
*/
112+
CV_WRAP virtual void apply(InputArray image, OutputArray fgmask, double learningRate=-1) CV_OVERRIDE = 0;
113+
CV_WRAP virtual void getBackgroundImage(OutputArray backgroundImage) const CV_OVERRIDE = 0;
114+
102115
/** @brief Returns total number of distinct colors to maintain in histogram.
103116
*/
104117
CV_WRAP virtual int getMaxFeatures() const = 0;

modules/bgsegm/src/bgfg_gmg.cpp

+13-4
Original file line numberDiff line numberDiff line change
@@ -426,8 +426,13 @@ void BackgroundSubtractorGMGImpl::apply(InputArray _frame, OutputArray _fgmask,
426426
{
427427
Mat frame = _frame.getMat();
428428

429-
CV_Assert(frame.depth() == CV_8U || frame.depth() == CV_16U || frame.depth() == CV_32F);
430-
CV_Assert(frame.channels() == 1 || frame.channels() == 3 || frame.channels() == 4);
429+
const int depth = frame.depth();
430+
CV_CheckDepth(depth, (depth == CV_8U) || (depth == CV_8S) ||
431+
(depth == CV_16U) || (depth == CV_16S) ||
432+
(depth == CV_32S) ||
433+
(depth == CV_32F) || (depth == CV_64F), "Unsupported depth");
434+
CV_CheckGE(frame.channels(), 1, "Unsupported channels");
435+
CV_CheckLE(frame.channels(), 4, "Unsupported channels");
431436

432437
if (newLearningRate != -1.0)
433438
{
@@ -441,8 +446,12 @@ void BackgroundSubtractorGMGImpl::apply(InputArray _frame, OutputArray _fgmask,
441446
double maxval = maxVal_;
442447
if( minVal_ == 0 && maxVal_ == 0 )
443448
{
444-
minval = 0;
445-
maxval = frame.depth() == CV_8U ? 255.0 : frame.depth() == CV_16U ? std::numeric_limits<ushort>::max() : 1.0;
449+
if( depth == CV_8U ) { minval = std::numeric_limits<uint8_t>::min(); maxval = std::numeric_limits<uint8_t>::max(); }
450+
else if( depth == CV_8S ) { minval = std::numeric_limits<int8_t>::min(); maxval = std::numeric_limits<int8_t>::max(); }
451+
else if( depth == CV_16U ) { minval = std::numeric_limits<uint16_t>::min();maxval = std::numeric_limits<uint16_t>::max();}
452+
else if( depth == CV_16S ) { minval = std::numeric_limits<int16_t>::min(); maxval = std::numeric_limits<int16_t>::max(); }
453+
else if( depth == CV_32S ) { minval = std::numeric_limits<int32_t>::min(); maxval = std::numeric_limits<int32_t>::max(); }
454+
else /* CV_32F or CV_64F */ { minval = 0.0; maxval = 1.0; }
446455
}
447456
initialize(frame.size(), minval, maxval);
448457
}

modules/bgsegm/test/test_backgroundsubtractor_gbh.cpp

+34-53
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,24 @@
77

88
namespace opencv_test { namespace {
99

10-
class CV_BackgroundSubtractorTest : public cvtest::BaseTest
11-
{
12-
public:
13-
CV_BackgroundSubtractorTest();
14-
protected:
15-
void run(int);
16-
};
17-
18-
CV_BackgroundSubtractorTest::CV_BackgroundSubtractorTest()
19-
{
20-
}
21-
2210
/**
2311
* This test checks the following:
2412
* (i) BackgroundSubtractorGMG can operate with matrices of various types and sizes
2513
* (ii) Training mode returns empty fgmask
2614
* (iii) End of training mode, and anomalous frame yields every pixel detected as FG
2715
*/
28-
void CV_BackgroundSubtractorTest::run(int)
16+
typedef testing::TestWithParam<std::tuple<perf::MatDepth,int>> bgsubgmg_allTypes;
17+
TEST_P(bgsubgmg_allTypes, accuracy)
2918
{
30-
int code = cvtest::TS::OK;
31-
RNG& rng = ts->get_rng();
32-
int type = ((unsigned int)rng)%7; //!< pick a random type, 0 - 6, defined in types_c.h
33-
int channels = 1 + ((unsigned int)rng)%4; //!< random number of channels from 1 to 4.
34-
int channelsAndType = CV_MAKETYPE(type,channels);
35-
int width = 2 + ((unsigned int)rng)%98; //!< Mat will be 2 to 100 in width and height
36-
int height = 2 + ((unsigned int)rng)%98;
19+
const int depth = get<0>(GetParam());
20+
const int ncn = get<1>(GetParam());
21+
const int mtype = CV_MAKETYPE(depth, ncn);
22+
const int width = 64;
23+
const int height = 64;
24+
RNG& rng = TS::ptr()->get_rng();
3725

3826
Ptr<BackgroundSubtractorGMG> fgbg = createBackgroundSubtractorGMG();
39-
Mat fgmask;
40-
41-
if (!fgbg)
42-
CV_Error(Error::StsError,"Failed to create Algorithm\n");
27+
ASSERT_TRUE(fgbg != nullptr) << "Failed to call createBackgroundSubtractorGMG()";
4328

4429
/**
4530
* Set a few parameters
@@ -57,49 +42,51 @@ void CV_BackgroundSubtractorTest::run(int)
5742
* Max value for simulated images picked randomly in upper half of type range
5843
* Min value for simulated images picked randomly in lower half of type range
5944
*/
60-
if (type == CV_8U)
45+
if (depth == CV_8U)
6146
{
6247
uchar half = UCHAR_MAX/2;
6348
maxd = (unsigned char)rng.uniform(half+32, UCHAR_MAX);
6449
mind = (unsigned char)rng.uniform(0, half-32);
6550
}
66-
else if (type == CV_8S)
51+
else if (depth == CV_8S)
6752
{
6853
maxd = (char)rng.uniform(32, CHAR_MAX);
6954
mind = (char)rng.uniform(CHAR_MIN, -32);
7055
}
71-
else if (type == CV_16U)
56+
else if (depth == CV_16U)
7257
{
7358
ushort half = USHRT_MAX/2;
7459
maxd = (unsigned int)rng.uniform(half+32, USHRT_MAX);
7560
mind = (unsigned int)rng.uniform(0, half-32);
7661
}
77-
else if (type == CV_16S)
62+
else if (depth == CV_16S)
7863
{
7964
maxd = rng.uniform(32, SHRT_MAX);
8065
mind = rng.uniform(SHRT_MIN, -32);
8166
}
82-
else if (type == CV_32S)
67+
else if (depth == CV_32S)
8368
{
8469
maxd = rng.uniform(32, INT_MAX);
8570
mind = rng.uniform(INT_MIN, -32);
8671
}
87-
else if (type == CV_32F)
72+
else
8873
{
89-
maxd = rng.uniform(32.0f, FLT_MAX);
90-
mind = rng.uniform(-FLT_MAX, -32.0f);
91-
}
92-
else if (type == CV_64F)
93-
{
94-
maxd = rng.uniform(32.0, DBL_MAX);
95-
mind = rng.uniform(-DBL_MAX, -32.0);
74+
ASSERT_TRUE( (depth == CV_32F)||(depth == CV_64F) ) << "Unsupported depth";
75+
const double harf = 0.5;
76+
const double bias = 0.125; // = 32/256 (Like CV_8U)
77+
maxd = rng.uniform(harf + bias, 1.0);
78+
mind = rng.uniform(0.0, harf - bias );
9679
}
9780

9881
fgbg->setMinVal(mind);
9982
fgbg->setMaxVal(maxd);
10083

101-
Mat simImage = Mat::zeros(height, width, channelsAndType);
102-
int numLearningFrames = 120;
84+
Mat simImage(height, width, mtype);
85+
Mat fgmask;
86+
87+
const Mat fullbg(height, width, CV_8UC1, cv::Scalar(0)); // all background.
88+
89+
const int numLearningFrames = 120;
10390
for (int i = 0; i < numLearningFrames; ++i)
10491
{
10592
/**
@@ -111,27 +98,21 @@ void CV_BackgroundSubtractorTest::run(int)
11198
* Feed simulated images into background subtractor
11299
*/
113100
fgbg->apply(simImage,fgmask);
114-
Mat fullbg = Mat::zeros(simImage.rows, simImage.cols, CV_8U);
115101

116-
//! fgmask should be entirely background during training
117-
code = cvtest::cmpEps2( ts, fgmask, fullbg, 0, false, "The training foreground mask" );
118-
if (code < 0)
119-
ts->set_failed_test_info( code );
102+
EXPECT_EQ(cv::norm(fgmask, fullbg, NORM_INF), 0) << "foreground mask should be entirely background during training";
120103
}
121104
//! generate last image, distinct from training images
122105
rng.fill(simImage, RNG::UNIFORM, mind, maxd);
123-
124106
fgbg->apply(simImage,fgmask);
125-
//! now fgmask should be entirely foreground
126-
Mat fullfg = 255*Mat::ones(simImage.rows, simImage.cols, CV_8U);
127-
code = cvtest::cmpEps2( ts, fgmask, fullfg, 255, false, "The final foreground mask" );
128-
if (code < 0)
129-
{
130-
ts->set_failed_test_info( code );
131-
}
132107

108+
const Mat fullfg(height, width, CV_8UC1, cv::Scalar(255)); // all foreground.
109+
EXPECT_EQ(cv::norm(fgmask, fullfg, NORM_INF), 0) << "foreground mask should be entirely foreground finally";
133110
}
134111

135-
TEST(VIDEO_BGSUBGMG, accuracy) { CV_BackgroundSubtractorTest test; test.safe_run(); }
112+
INSTANTIATE_TEST_CASE_P(/**/,
113+
bgsubgmg_allTypes,
114+
testing::Combine(
115+
testing::Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F),
116+
testing::Values(1,2,3,4)));
136117

137118
}} // namespace

0 commit comments

Comments
 (0)