Skip to content

Commit 496968c

Browse files
committed
Merge branch 4.x
2 parents 9a3ab80 + 438e67f commit 496968c

File tree

4 files changed

+62
-61
lines changed

4 files changed

+62
-61
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request
44

5-
- [ ] I agree to contribute to the project under Apache 2 License.
6-
- [ ] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
5+
- [x] I agree to contribute to the project under Apache 2 License.
6+
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
77
- [ ] The PR is proposed to the proper branch
88
- [ ] There is a reference to the original bug report and related work
99
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable

modules/bgsegm/include/opencv2/bgsegm.hpp

Lines changed: 13 additions & 0 deletions
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

Lines changed: 13 additions & 4 deletions
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

Lines changed: 34 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7,41 +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) % 3;
33-
type = (type == 0) ? CV_8U : (type == 1) ? CV_16U : CV_32F; // 8U, 16U, 32F
34-
int channels = ((unsigned int)rng)%3;
35-
channels = (channels == 2) ? 4 : channels; // 1, 3, 4
36-
int channelsAndType = CV_MAKETYPE(type,channels);
37-
int width = 2 + ((unsigned int)rng)%98; //!< Mat will be 2 to 100 in width and height
38-
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();
3925

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

4629
/**
4730
* Set a few parameters
@@ -59,49 +42,51 @@ void CV_BackgroundSubtractorTest::run(int)
5942
* Max value for simulated images picked randomly in upper half of type range
6043
* Min value for simulated images picked randomly in lower half of type range
6144
*/
62-
if (type == CV_8U)
45+
if (depth == CV_8U)
6346
{
6447
uchar half = UCHAR_MAX/2;
6548
maxd = (unsigned char)rng.uniform(half+32, UCHAR_MAX);
6649
mind = (unsigned char)rng.uniform(0, half-32);
6750
}
68-
else if (type == CV_8S)
51+
else if (depth == CV_8S)
6952
{
7053
maxd = (char)rng.uniform(32, CHAR_MAX);
7154
mind = (char)rng.uniform(CHAR_MIN, -32);
7255
}
73-
else if (type == CV_16U)
56+
else if (depth == CV_16U)
7457
{
7558
ushort half = USHRT_MAX/2;
7659
maxd = (unsigned int)rng.uniform(half+32, USHRT_MAX);
7760
mind = (unsigned int)rng.uniform(0, half-32);
7861
}
79-
else if (type == CV_16S)
62+
else if (depth == CV_16S)
8063
{
8164
maxd = rng.uniform(32, SHRT_MAX);
8265
mind = rng.uniform(SHRT_MIN, -32);
8366
}
84-
else if (type == CV_32S)
67+
else if (depth == CV_32S)
8568
{
8669
maxd = rng.uniform(32, INT_MAX);
8770
mind = rng.uniform(INT_MIN, -32);
8871
}
89-
else if (type == CV_32F)
72+
else
9073
{
91-
maxd = rng.uniform(32.0f, FLT_MAX);
92-
mind = rng.uniform(-FLT_MAX, -32.0f);
93-
}
94-
else if (type == CV_64F)
95-
{
96-
maxd = rng.uniform(32.0, DBL_MAX);
97-
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 );
9879
}
9980

10081
fgbg->setMinVal(mind);
10182
fgbg->setMaxVal(maxd);
10283

103-
Mat simImage = Mat::zeros(height, width, channelsAndType);
104-
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;
10590
for (int i = 0; i < numLearningFrames; ++i)
10691
{
10792
/**
@@ -113,27 +98,21 @@ void CV_BackgroundSubtractorTest::run(int)
11398
* Feed simulated images into background subtractor
11499
*/
115100
fgbg->apply(simImage,fgmask);
116-
Mat fullbg = Mat::zeros(simImage.rows, simImage.cols, CV_8U);
117101

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

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";
135110
}
136111

137-
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)));
138117

139118
}} // namespace

0 commit comments

Comments
 (0)