Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
42c1d4f4
Commit
42c1d4f4
authored
Aug 08, 2012
by
Vladislav Vinogradov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
new optimized version of BackgroundSubtractorGMG
parent
1995b1a0
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
87 additions
and
224 deletions
+87
-224
background_segm.hpp
modules/video/include/opencv2/video/background_segm.hpp
+22
-143
bgfg_gmg.cpp
modules/video/src/bgfg_gmg.cpp
+0
-0
test_backgroundsubtractor_gbh.cpp
modules/video/test/test_backgroundsubtractor_gbh.cpp
+7
-8
bgfg_gmg.cpp
samples/cpp/bgfg_gmg.cpp
+58
-73
No files found.
modules/video/include/opencv2/video/background_segm.hpp
View file @
42c1d4f4
...
@@ -199,111 +199,20 @@ protected:
...
@@ -199,111 +199,20 @@ protected:
*/
*/
class
CV_EXPORTS
BackgroundSubtractorGMG
:
public
cv
::
BackgroundSubtractor
class
CV_EXPORTS
BackgroundSubtractorGMG
:
public
cv
::
BackgroundSubtractor
{
{
protected
:
/**
* Used internally to represent a single feature in a histogram.
* Feature is a color and an associated likelihood (weight in the histogram).
*/
struct
CV_EXPORTS
HistogramFeatureGMG
{
/**
* Default constructor.
* Initializes likelihood of feature to 0, color remains uninitialized.
*/
HistogramFeatureGMG
(){
likelihood
=
0.0
;}
/**
* Copy constructor.
* Required to use HistogramFeatureGMG in a std::vector
* @see operator =()
*/
HistogramFeatureGMG
(
const
HistogramFeatureGMG
&
orig
){
color
=
orig
.
color
;
likelihood
=
orig
.
likelihood
;
}
/**
* Assignment operator.
* Required to use HistogramFeatureGMG in a std::vector
*/
HistogramFeatureGMG
&
operator
=
(
const
HistogramFeatureGMG
&
orig
){
color
=
orig
.
color
;
likelihood
=
orig
.
likelihood
;
return
*
this
;
}
/**
* Tests equality of histogram features.
* Equality is tested only by matching the color (feature), not the likelihood.
* This operator is used to look up an observed feature in a histogram.
*/
bool
operator
==
(
HistogramFeatureGMG
&
rhs
);
//! Regardless of the image datatype, it is quantized and mapped to an integer and represented as a vector.
vector
<
size_t
>
color
;
//! Represents the weight of feature in the histogram.
float
likelihood
;
friend
class
PixelModelGMG
;
};
/**
* Representation of the statistical model of a single pixel for use in the background subtraction
* algorithm.
*/
class
CV_EXPORTS
PixelModelGMG
{
public
:
PixelModelGMG
();
~
PixelModelGMG
();
/**
* Incorporate the last observed feature into the statistical model.
*
* @param learningRate The adaptation parameter for the histogram. -1.0 to use default. Value
* should be between 0.0 and 1.0, the higher the value, the faster the
* adaptation. 1.0 is limiting case where fast adaptation means no memory.
*/
void
insertFeature
(
double
learningRate
=
-
1.0
);
/**
* Set the feature last observed, to save before incorporating it into the statistical
* model with insertFeature().
*
* @param feature The feature (color) just observed.
*/
void
setLastObservedFeature
(
BackgroundSubtractorGMG
::
HistogramFeatureGMG
feature
);
/**
* Set the upper limit for the number of features to store in the histogram. Use to adjust
* memory requirements.
*
* @param max size_t representing the max number of features.
*/
void
setMaxFeatures
(
size_t
max
)
{
maxFeatures
=
max
;
histogram
.
resize
(
max
);
histogram
.
clear
();
}
/**
* Normalize the histogram, so sum of weights of all features = 1.0
*/
void
normalizeHistogram
();
/**
* Return the weight of a feature in the histogram. If the feature is not represented in the
* histogram, the weight returned is 0.0.
*/
double
getLikelihood
(
HistogramFeatureGMG
f
);
PixelModelGMG
&
operator
*=
(
const
float
&
rhs
);
//friend class BackgroundSubtractorGMG;
//friend class HistogramFeatureGMG;
private
:
size_t
numFeatures
;
//!< number of features in histogram
size_t
maxFeatures
;
//!< max allowable features in histogram
std
::
list
<
HistogramFeatureGMG
>
histogram
;
//!< represents the histogram as a list of features
HistogramFeatureGMG
lastObservedFeature
;
//!< store last observed feature in case we need to add it to histogram
};
public
:
public
:
BackgroundSubtractorGMG
();
BackgroundSubtractorGMG
();
virtual
~
BackgroundSubtractorGMG
();
virtual
~
BackgroundSubtractorGMG
();
virtual
AlgorithmInfo
*
info
()
const
;
virtual
AlgorithmInfo
*
info
()
const
;
/**
* Validate parameters and set up data structures for appropriate image size.
* Must call before running on data.
* @param frameSize input frame size
* @param min minimum value taken on by pixels in image sequence. Usually 0
* @param max maximum value taken on by pixels in image sequence. e.g. 1.0 or 255
*/
void
initialize
(
cv
::
Size
frameSize
,
double
min
,
double
max
);
/**
/**
* Performs single-frame background subtraction and builds up a statistical background image
* Performs single-frame background subtraction and builds up a statistical background image
* model.
* model.
...
@@ -312,28 +221,6 @@ public:
...
@@ -312,28 +221,6 @@ public:
*/
*/
virtual
void
operator
()(
InputArray
image
,
OutputArray
fgmask
,
double
learningRate
=-
1.0
);
virtual
void
operator
()(
InputArray
image
,
OutputArray
fgmask
,
double
learningRate
=-
1.0
);
/**
* Validate parameters and set up data structures for appropriate image type. Must call before
* running on data.
* @param image One sample image from dataset
* @param min minimum value taken on by pixels in image sequence. Usually 0
* @param max maximum value taken on by pixels in image sequence. e.g. 1.0 or 255
*/
void
initializeType
(
InputArray
image
,
double
min
,
double
max
);
/**
* Selectively update the background model. Only update background model for pixels identified
* as background.
* @param mask Mask image same size as images in sequence. Must be 8UC1 matrix, 255 for foreground
* and 0 for background.
*/
void
updateBackgroundModel
(
InputArray
mask
);
/**
* Retrieve the greyscale image representing the probability that each pixel is foreground given
* the current estimated background model. Values are 0.0 (black) to 1.0 (white).
* @param img The 32FC1 image representing per-pixel probabilities that the pixel is foreground.
*/
void
getPosteriorImage
(
OutputArray
img
);
protected
:
protected
:
//! Total number of distinct colors to maintain in histogram.
//! Total number of distinct colors to maintain in histogram.
int
maxFeatures
;
int
maxFeatures
;
...
@@ -345,31 +232,23 @@ protected:
...
@@ -345,31 +232,23 @@ protected:
int
quantizationLevels
;
int
quantizationLevels
;
//! Prior probability that any given pixel is a background pixel. A sensitivity parameter.
//! Prior probability that any given pixel is a background pixel. A sensitivity parameter.
double
backgroundPrior
;
double
backgroundPrior
;
//! value above which pixel is determined to be FG.
double
decisionThreshold
;
//! smoothing radius, in pixels, for cleaning up FG image.
int
smoothingRadius
;
double
decisionThreshold
;
//!< value above which pixel is determined to be FG.
private
:
int
smoothingRadius
;
//!< smoothing radius, in pixels, for cleaning up FG image.
double
maxVal_
;
double
minVal_
;
double
maxVal
,
minVal
;
cv
::
Size
frameSize_
;
size_t
frameNum_
;
/*
cv
::
Mat_
<
int
>
nfeatures_
;
* General Parameters
cv
::
Mat_
<
int
>
colors_
;
*/
cv
::
Mat_
<
float
>
weights_
;
int
imWidth
;
//!< width of image.
int
imHeight
;
//!< height of image.
size_t
numPixels
;
unsigned
int
numChannels
;
//!< Number of channels in image.
cv
::
Mat
buf_
;
bool
isDataInitialized
;
//!< After general parameters are set, data structures must be initialized.
/*
* Data Structures
*/
vector
<
PixelModelGMG
>
pixels
;
//!< Probabilistic background models for each pixel in image.
int
frameNum
;
//!< Frame number counter, used to count frames in training mode.
Mat
posteriorImage
;
//!< Posterior probability image.
Mat
fgMaskImage
;
//!< Foreground mask image.
};
};
}
}
...
...
modules/video/src/bgfg_gmg.cpp
View file @
42c1d4f4
This diff is collapsed.
Click to expand it.
modules/video/test/test_backgroundsubtractor_gbh.cpp
View file @
42c1d4f4
...
@@ -115,43 +115,43 @@ void CV_BackgroundSubtractorTest::run(int)
...
@@ -115,43 +115,43 @@ void CV_BackgroundSubtractorTest::run(int)
{
{
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
unsigned
char
)(
minuc
/
2
+
maxuc
/
2
),
maxuc
);
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
unsigned
char
)(
minuc
/
2
+
maxuc
/
2
),
maxuc
);
if
(
i
==
0
)
if
(
i
==
0
)
fgbg
->
initialize
Type
(
simImage
,
minuc
,
maxuc
);
fgbg
->
initialize
(
simImage
.
size
()
,
minuc
,
maxuc
);
}
}
else
if
(
type
==
CV_8S
)
else
if
(
type
==
CV_8S
)
{
{
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
char
)(
minc
/
2
+
maxc
/
2
),
maxc
);
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
char
)(
minc
/
2
+
maxc
/
2
),
maxc
);
if
(
i
==
0
)
if
(
i
==
0
)
fgbg
->
initialize
Type
(
simImage
,
minc
,
maxc
);
fgbg
->
initialize
(
simImage
.
size
()
,
minc
,
maxc
);
}
}
else
if
(
type
==
CV_16U
)
else
if
(
type
==
CV_16U
)
{
{
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
unsigned
int
)(
minui
/
2
+
maxui
/
2
),
maxui
);
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
unsigned
int
)(
minui
/
2
+
maxui
/
2
),
maxui
);
if
(
i
==
0
)
if
(
i
==
0
)
fgbg
->
initialize
Type
(
simImage
,
minui
,
maxui
);
fgbg
->
initialize
(
simImage
.
size
()
,
minui
,
maxui
);
}
}
else
if
(
type
==
CV_16S
)
else
if
(
type
==
CV_16S
)
{
{
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
int
)(
mini
/
2
+
maxi
/
2
),
maxi
);
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
int
)(
mini
/
2
+
maxi
/
2
),
maxi
);
if
(
i
==
0
)
if
(
i
==
0
)
fgbg
->
initialize
Type
(
simImage
,
mini
,
maxi
);
fgbg
->
initialize
(
simImage
.
size
()
,
mini
,
maxi
);
}
}
else
if
(
type
==
CV_32F
)
else
if
(
type
==
CV_32F
)
{
{
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
float
)(
minf
/
2.0
+
maxf
/
2.0
),
maxf
);
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
float
)(
minf
/
2.0
+
maxf
/
2.0
),
maxf
);
if
(
i
==
0
)
if
(
i
==
0
)
fgbg
->
initialize
Type
(
simImage
,
minf
,
maxf
);
fgbg
->
initialize
(
simImage
.
size
()
,
minf
,
maxf
);
}
}
else
if
(
type
==
CV_32S
)
else
if
(
type
==
CV_32S
)
{
{
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
long
int
)(
minli
/
2
+
maxli
/
2
),
maxli
);
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
long
int
)(
minli
/
2
+
maxli
/
2
),
maxli
);
if
(
i
==
0
)
if
(
i
==
0
)
fgbg
->
initialize
Type
(
simImage
,
minli
,
maxli
);
fgbg
->
initialize
(
simImage
.
size
()
,
minli
,
maxli
);
}
}
else
if
(
type
==
CV_64F
)
else
if
(
type
==
CV_64F
)
{
{
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
double
)(
mind
/
2.0
+
maxd
/
2.0
),
maxd
);
rng
.
fill
(
simImage
,
RNG
::
UNIFORM
,(
double
)(
mind
/
2.0
+
maxd
/
2.0
),
maxd
);
if
(
i
==
0
)
if
(
i
==
0
)
fgbg
->
initialize
Type
(
simImage
,
mind
,
maxd
);
fgbg
->
initialize
(
simImage
.
size
()
,
mind
,
maxd
);
}
}
/**
/**
...
@@ -159,7 +159,6 @@ void CV_BackgroundSubtractorTest::run(int)
...
@@ -159,7 +159,6 @@ void CV_BackgroundSubtractorTest::run(int)
*/
*/
(
*
fgbg
)(
simImage
,
fgmask
);
(
*
fgbg
)(
simImage
,
fgmask
);
Mat
fullbg
=
Mat
::
zeros
(
simImage
.
rows
,
simImage
.
cols
,
CV_8U
);
Mat
fullbg
=
Mat
::
zeros
(
simImage
.
rows
,
simImage
.
cols
,
CV_8U
);
fgbg
->
updateBackgroundModel
(
fullbg
);
//! fgmask should be entirely background during training
//! fgmask should be entirely background during training
code
=
cvtest
::
cmpEps2
(
ts
,
fgmask
,
fullbg
,
0
,
false
,
"The training foreground mask"
);
code
=
cvtest
::
cmpEps2
(
ts
,
fgmask
,
fullbg
,
0
,
false
,
"The training foreground mask"
);
...
...
samples/cpp/bgfg_gmg.cpp
View file @
42c1d4f4
...
@@ -7,91 +7,76 @@
...
@@ -7,91 +7,76 @@
#include <opencv2/opencv.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <iostream>
#include <sstream>
using
namespace
cv
;
using
namespace
cv
;
static
void
help
()
static
void
help
()
{
{
std
::
cout
<<
std
::
cout
<<
"
\n
A program demonstrating the use and capabilities of a particular BackgroundSubtraction
\n
"
"
\n
A program demonstrating the use and capabilities of a particular BackgroundSubtraction
\n
"
"algorithm described in A. Godbehere, A. Matsukawa, K. Goldberg,
\n
"
"algorithm described in A. Godbehere, A. Matsukawa, K. Goldberg,
\n
"
"
\"
Visual Tracking of Human Visitors under Variable-Lighting Conditions for a Responsive
\n
"
"
\"
Visual Tracking of Human Visitors under Variable-Lighting Conditions for a Responsive
\n
"
"Audio Art Installation
\"
, American Control Conference, 2012, used in an interactive
\n
"
"Audio Art Installation
\"
, American Control Conference, 2012, used in an interactive
\n
"
"installation at the Contemporary Jewish Museum in San Francisco, CA from March 31 through
\n
"
"installation at the Contemporary Jewish Museum in San Francisco, CA from March 31 through
\n
"
"July 31, 2011.
\n
"
"July 31, 2011.
\n
"
"Call:
\n
"
"Call:
\n
"
"./BackgroundSubtractorGMG_sample
\n
"
"./BackgroundSubtractorGMG_sample
\n
"
"Using OpenCV version "
<<
CV_VERSION
<<
"
\n
"
<<
std
::
endl
;
"Using OpenCV version "
<<
CV_VERSION
<<
"
\n
"
<<
std
::
endl
;
}
}
int
main
(
int
argc
,
char
**
argv
)
int
main
(
int
argc
,
char
**
argv
)
{
{
help
();
help
();
setUseOptimized
(
true
);
setNumThreads
(
8
);
initModule_video
();
setUseOptimized
(
true
);
Ptr
<
BackgroundSubtractorGMG
>
fgbg
=
Algorithm
::
create
<
BackgroundSubtractorGMG
>
(
"BackgroundSubtractor.GMG"
);
setNumThreads
(
8
);
if
(
fgbg
==
NULL
)
{
Ptr
<
BackgroundSubtractorGMG
>
fgbg
=
Algorithm
::
create
<
BackgroundSubtractorGMG
>
(
"BackgroundSubtractor.GMG"
);
CV_Error
(
CV_StsError
,
"Failed to create Algorithm
\n
"
);
if
(
fgbg
.
empty
())
}
{
fgbg
->
set
(
"smoothingRadius"
,
7
);
std
::
cerr
<<
"Failed to create BackgroundSubtractor.GMG Algorithm."
<<
std
::
endl
;
fgbg
->
set
(
"decisionThreshold"
,
0.7
);
return
-
1
;
}
VideoCapture
cap
;
if
(
argc
>
1
)
fgbg
->
set
(
"initializationFrames"
,
20
);
fgbg
->
set
(
"decisionThreshold"
,
0.7
);
VideoCapture
cap
;
if
(
argc
>
1
)
cap
.
open
(
argv
[
1
]);
cap
.
open
(
argv
[
1
]);
else
else
cap
.
open
(
0
);
cap
.
open
(
0
);
if
(
!
cap
.
isOpened
())
if
(
!
cap
.
isOpened
())
{
{
std
::
cout
<<
"error: cannot read video. Try moving video file to sample directory.
\n
"
;
std
::
cerr
<<
"Cannot read video. Try moving video file to sample directory."
<<
std
::
endl
;
return
-
1
;
return
-
1
;
}
}
Mat
img
,
downimg
,
downimg2
,
fgmask
,
upfgmask
,
posterior
,
upposterior
;
Mat
frame
,
fgmask
,
segm
;
bool
first
=
true
;
namedWindow
(
"FG Segmentation"
,
WINDOW_NORMAL
);
namedWindow
(
"posterior"
);
namedWindow
(
"fgmask"
);
for
(;;)
namedWindow
(
"FG Segmentation"
);
{
int
i
=
0
;
cap
>>
frame
;
for
(;;)
{
if
(
frame
.
empty
())
std
::
stringstream
txt
;
break
;
txt
<<
"frame: "
;
txt
<<
i
++
;
(
*
fgbg
)(
frame
,
fgmask
);
cap
>>
img
;
frame
.
copyTo
(
segm
);
putText
(
img
,
txt
.
str
(),
Point
(
20
,
40
),
FONT_HERSHEY_SIMPLEX
,
0.8
,
Scalar
(
1.0
,
0.0
,
0.0
));
add
(
frame
,
Scalar
(
100
,
100
,
0
),
segm
,
fgmask
);
resize
(
img
,
downimg
,
Size
(
160
,
120
),
0
,
0
,
INTER_NEAREST
);
// Size(cols, rows) or Size(width,height)
imshow
(
"FG Segmentation"
,
segm
);
if
(
first
)
{
fgbg
->
initializeType
(
downimg
,
0
,
255
);
first
=
false
;
}
if
(
img
.
empty
())
{
return
0
;
}
(
*
fgbg
)(
downimg
,
fgmask
);
fgbg
->
updateBackgroundModel
(
Mat
::
zeros
(
120
,
160
,
CV_8U
));
fgbg
->
getPosteriorImage
(
posterior
);
resize
(
fgmask
,
upfgmask
,
Size
(
640
,
480
),
0
,
0
,
INTER_NEAREST
);
Mat
coloredFG
=
Mat
::
zeros
(
480
,
640
,
CV_8UC3
);
coloredFG
.
setTo
(
Scalar
(
100
,
100
,
0
),
upfgmask
);
resize
(
posterior
,
upposterior
,
Size
(
640
,
480
),
0
,
0
,
INTER_NEAREST
);
imshow
(
"posterior"
,
upposterior
);
imshow
(
"fgmask"
,
upfgmask
);
resize
(
img
,
downimg2
,
Size
(
640
,
480
),
0
,
0
,
INTER_LINEAR
);
imshow
(
"FG Segmentation"
,
downimg2
+
coloredFG
);
int
c
=
waitKey
(
30
);
int
c
=
waitKey
(
30
);
if
(
c
==
'q'
||
c
==
'Q'
||
(
c
&
255
)
==
27
)
if
(
c
==
'q'
||
c
==
'Q'
||
(
c
&
255
)
==
27
)
break
;
break
;
}
}
return
0
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment