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
60456083
Commit
60456083
authored
Dec 25, 2017
by
Glue Crow
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Parallelization of BackgroundSubtractorKNN
parent
047764f4
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
179 additions
and
166 deletions
+179
-166
bgfg_KNN.cpp
modules/video/src/bgfg_KNN.cpp
+179
-166
No files found.
modules/video/src/bgfg_KNN.cpp
View file @
60456083
...
@@ -259,10 +259,8 @@ protected:
...
@@ -259,10 +259,8 @@ protected:
String
name_
;
String
name_
;
};
};
//{ to do - paralelization ...
//struct KNNInvoker....
CV_INLINE
void
CV_INLINE
void
_cvUpdatePixelBackgroundNP
(
long
pixel
,
const
uchar
*
data
,
int
nchannels
,
int
m_nN
,
_cvUpdatePixelBackgroundNP
(
int
x_idx
,
const
uchar
*
data
,
int
nchannels
,
int
m_nN
,
uchar
*
m_aModel
,
uchar
*
m_aModel
,
uchar
*
m_nNextLongUpdate
,
uchar
*
m_nNextLongUpdate
,
uchar
*
m_nNextMidUpdate
,
uchar
*
m_nNextMidUpdate
,
...
@@ -273,70 +271,53 @@ CV_INLINE void
...
@@ -273,70 +271,53 @@ CV_INLINE void
int
m_nLongCounter
,
int
m_nLongCounter
,
int
m_nMidCounter
,
int
m_nMidCounter
,
int
m_nShortCounter
,
int
m_nShortCounter
,
int
m_nLongUpdate
,
int
m_nMidUpdate
,
int
m_nShortUpdate
,
uchar
include
uchar
include
)
)
{
{
// hold the offset
// hold the offset
int
ndata
=
1
+
nchannels
;
int
ndata
=
1
+
nchannels
;
long
offsetLong
=
ndata
*
(
pixel
*
m_nN
*
3
+
m_aModelIndexLong
[
pixel
]
+
m_nN
*
2
);
long
offsetLong
=
ndata
*
(
m_aModelIndexLong
[
x_idx
]
+
m_nN
*
2
);
long
offsetMid
=
ndata
*
(
pixel
*
m_nN
*
3
+
m_aModelIndexMid
[
pixel
]
+
m_nN
*
1
);
long
offsetMid
=
ndata
*
(
m_aModelIndexMid
[
x_idx
]
+
m_nN
*
1
);
long
offsetShort
=
ndata
*
(
pixel
*
m_nN
*
3
+
m_aModelIndexShort
[
pixel
]);
long
offsetShort
=
ndata
*
(
m_aModelIndexShort
[
x_idx
]);
// Long update?
// Long update?
if
(
m_nNextLongUpdate
[
pixel
]
==
m_nLongCounter
)
if
(
m_nNextLongUpdate
[
x_idx
]
==
m_nLongCounter
)
{
{
// add the oldest pixel from Mid to the list of values (for each color)
// add the oldest pixel from Mid to the list of values (for each color)
memcpy
(
&
m_aModel
[
offsetLong
],
&
m_aModel
[
offsetMid
],
ndata
*
sizeof
(
unsigned
char
));
memcpy
(
&
m_aModel
[
offsetLong
],
&
m_aModel
[
offsetMid
],
ndata
*
sizeof
(
unsigned
char
));
// increase the index
// increase the index
m_aModelIndexLong
[
pixel
]
=
(
m_aModelIndexLong
[
pixel
]
>=
(
m_nN
-
1
))
?
0
:
(
m_aModelIndexLong
[
pixel
]
+
1
);
m_aModelIndexLong
[
x_idx
]
=
(
m_aModelIndexLong
[
x_idx
]
>=
(
m_nN
-
1
))
?
0
:
(
m_aModelIndexLong
[
x_idx
]
+
1
);
};
if
(
m_nLongCounter
==
(
m_nLongUpdate
-
1
))
{
//m_nNextLongUpdate[pixel] = (uchar)(((m_nLongUpdate)*(rand()-1))/RAND_MAX);//0,...m_nLongUpdate-1;
m_nNextLongUpdate
[
pixel
]
=
(
uchar
)(
rand
()
%
m_nLongUpdate
);
//0,...m_nLongUpdate-1;
};
};
// Mid update?
// Mid update?
if
(
m_nNextMidUpdate
[
pixel
]
==
m_nMidCounter
)
if
(
m_nNextMidUpdate
[
x_idx
]
==
m_nMidCounter
)
{
{
// add this pixel to the list of values (for each color)
// add this pixel to the list of values (for each color)
memcpy
(
&
m_aModel
[
offsetMid
],
&
m_aModel
[
offsetShort
],
ndata
*
sizeof
(
unsigned
char
));
memcpy
(
&
m_aModel
[
offsetMid
],
&
m_aModel
[
offsetShort
],
ndata
*
sizeof
(
unsigned
char
));
// increase the index
// increase the index
m_aModelIndexMid
[
pixel
]
=
(
m_aModelIndexMid
[
pixel
]
>=
(
m_nN
-
1
))
?
0
:
(
m_aModelIndexMid
[
pixel
]
+
1
);
m_aModelIndexMid
[
x_idx
]
=
(
m_aModelIndexMid
[
x_idx
]
>=
(
m_nN
-
1
))
?
0
:
(
m_aModelIndexMid
[
x_idx
]
+
1
);
};
if
(
m_nMidCounter
==
(
m_nMidUpdate
-
1
))
{
m_nNextMidUpdate
[
pixel
]
=
(
uchar
)(
rand
()
%
m_nMidUpdate
);
};
};
// Short update?
// Short update?
if
(
m_nNextShortUpdate
[
pixel
]
==
m_nShortCounter
)
if
(
m_nNextShortUpdate
[
x_idx
]
==
m_nShortCounter
)
{
{
// add this pixel to the list of values (for each color)
// add this pixel to the list of values (for each color)
memcpy
(
&
m_aModel
[
offsetShort
],
data
,
n
data
*
sizeof
(
unsigned
char
));
memcpy
(
&
m_aModel
[
offsetShort
],
data
,
n
channels
*
sizeof
(
unsigned
char
));
//set the include flag
//set the include flag
m_aModel
[
offsetShort
+
nchannels
]
=
include
;
m_aModel
[
offsetShort
+
nchannels
]
=
include
;
// increase the index
// increase the index
m_aModelIndexShort
[
pixel
]
=
(
m_aModelIndexShort
[
pixel
]
>=
(
m_nN
-
1
))
?
0
:
(
m_aModelIndexShort
[
pixel
]
+
1
);
m_aModelIndexShort
[
x_idx
]
=
(
m_aModelIndexShort
[
x_idx
]
>=
(
m_nN
-
1
))
?
0
:
(
m_aModelIndexShort
[
x_idx
]
+
1
);
};
if
(
m_nShortCounter
==
(
m_nShortUpdate
-
1
))
{
m_nNextShortUpdate
[
pixel
]
=
(
uchar
)(
rand
()
%
m_nShortUpdate
);
};
};
}
}
CV_INLINE
int
CV_INLINE
int
_cvCheckPixelBackgroundNP
(
long
pixel
,
_cvCheckPixelBackgroundNP
(
const
uchar
*
data
,
int
nchannels
,
const
uchar
*
data
,
int
nchannels
,
int
m_nN
,
int
m_nN
,
uchar
*
m_aModel
,
uchar
*
m_aModel
,
float
m_fTb
,
float
m_fTb
,
int
m_nkNN
,
int
m_nkNN
,
float
tau
,
float
tau
,
int
m_n
ShadowDetection
,
bool
m_b
ShadowDetection
,
uchar
&
include
)
uchar
&
include
)
{
{
int
Pbf
=
0
;
// the total probability that this pixel is background
int
Pbf
=
0
;
// the total probability that this pixel is background
...
@@ -347,12 +328,11 @@ CV_INLINE int
...
@@ -347,12 +328,11 @@ CV_INLINE int
include
=
0
;
//do we include this pixel into background model?
include
=
0
;
//do we include this pixel into background model?
int
ndata
=
nchannels
+
1
;
int
ndata
=
nchannels
+
1
;
long
posPixel
=
pixel
*
ndata
*
m_nN
*
3
;
// float k;
// float k;
// now increase the probability for each pixel
// now increase the probability for each pixel
for
(
int
n
=
0
;
n
<
m_nN
*
3
;
n
++
)
for
(
int
n
=
0
;
n
<
m_nN
*
3
;
n
++
)
{
{
uchar
*
mean_m
=
&
m_aModel
[
posPixel
+
n
*
ndata
];
uchar
*
mean_m
=
&
m_aModel
[
n
*
ndata
];
//calculate difference and distance
//calculate difference and distance
float
dist2
;
float
dist2
;
...
@@ -399,12 +379,12 @@ CV_INLINE int
...
@@ -399,12 +379,12 @@ CV_INLINE int
int
Ps
=
0
;
// the total probability that this pixel is background shadow
int
Ps
=
0
;
// the total probability that this pixel is background shadow
// Detected as moving object, perform shadow detection
// Detected as moving object, perform shadow detection
if
(
m_
n
ShadowDetection
)
if
(
m_
b
ShadowDetection
)
{
{
for
(
int
n
=
0
;
n
<
m_nN
*
3
;
n
++
)
for
(
int
n
=
0
;
n
<
m_nN
*
3
;
n
++
)
{
{
//long subPosPixel = posPixel + n*ndata;
//long subPosPixel = posPixel + n*ndata;
uchar
*
mean_m
=
&
m_aModel
[
posPixel
+
n
*
ndata
];
uchar
*
mean_m
=
&
m_aModel
[
n
*
ndata
];
if
(
mean_m
[
nchannels
])
//check only background
if
(
mean_m
[
nchannels
])
//check only background
{
{
...
@@ -445,123 +425,126 @@ CV_INLINE int
...
@@ -445,123 +425,126 @@ CV_INLINE int
return
0
;
return
0
;
}
}
CV_INLINE
void
class
KNNInvoker
:
public
ParallelLoopBody
icvUpdatePixelBackgroundNP
(
const
Mat
&
_src
,
Mat
&
_dst
,
Mat
&
_bgmodel
,
Mat
&
_nNextLongUpdate
,
Mat
&
_nNextMidUpdate
,
Mat
&
_nNextShortUpdate
,
Mat
&
_aModelIndexLong
,
Mat
&
_aModelIndexMid
,
Mat
&
_aModelIndexShort
,
int
&
_nLongCounter
,
int
&
_nMidCounter
,
int
&
_nShortCounter
,
int
_nN
,
float
_fAlphaT
,
float
_fTb
,
int
_nkNN
,
float
_fTau
,
int
_bShadowDetection
,
uchar
nShadowDetection
)
{
{
int
nchannels
=
CV_MAT_CN
(
_src
.
type
());
public
:
KNNInvoker
(
const
Mat
&
_src
,
Mat
&
_dst
,
//model
uchar
*
_bgmodel
,
uchar
*
m_aModel
=
_bgmodel
.
ptr
(
0
);
uchar
*
_nNextLongUpdate
,
uchar
*
m_nNextLongUpdate
=
_nNextLongUpdate
.
ptr
(
0
);
uchar
*
_nNextMidUpdate
,
uchar
*
m_nNextMidUpdate
=
_nNextMidUpdate
.
ptr
(
0
);
uchar
*
_nNextShortUpdate
,
uchar
*
m_nNextShortUpdate
=
_nNextShortUpdate
.
ptr
(
0
);
uchar
*
_aModelIndexLong
,
uchar
*
m_aModelIndexLong
=
_aModelIndexLong
.
ptr
(
0
);
uchar
*
_aModelIndexMid
,
uchar
*
m_aModelIndexMid
=
_aModelIndexMid
.
ptr
(
0
);
uchar
*
_aModelIndexShort
,
uchar
*
m_aModelIndexShort
=
_aModelIndexShort
.
ptr
(
0
);
int
_nLongCounter
,
int
_nMidCounter
,
//some constants
int
_nShortCounter
,
int
m_nN
=
_nN
;
int
_nN
,
float
m_fAlphaT
=
_fAlphaT
;
float
_fTb
,
float
m_fTb
=
_fTb
;
//Tb - threshold on the distance
int
_nkNN
,
float
m_fTau
=
_fTau
;
float
_fTau
,
int
m_nkNN
=
_nkNN
;
bool
_bShadowDetection
,
int
m_bShadowDetection
=
_bShadowDetection
;
uchar
_nShadowDetection
)
{
//recalculate update rates - in case alpha is changed
src
=
&
_src
;
// calculate update parameters (using alpha)
dst
=
&
_dst
;
int
Kshort
,
Kmid
,
Klong
;
m_aModel0
=
_bgmodel
;
//approximate exponential learning curve
m_nNextLongUpdate0
=
_nNextLongUpdate
;
Kshort
=
(
int
)(
log
(
0.7
)
/
log
(
1
-
m_fAlphaT
))
+
1
;
//Kshort
m_nNextMidUpdate0
=
_nNextMidUpdate
;
Kmid
=
(
int
)(
log
(
0.4
)
/
log
(
1
-
m_fAlphaT
))
-
Kshort
+
1
;
//Kmid
m_nNextShortUpdate0
=
_nNextShortUpdate
;
Klong
=
(
int
)(
log
(
0.1
)
/
log
(
1
-
m_fAlphaT
))
-
Kshort
-
Kmid
+
1
;
//Klong
m_aModelIndexLong0
=
_aModelIndexLong
;
m_aModelIndexMid0
=
_aModelIndexMid
;
m_aModelIndexShort0
=
_aModelIndexShort
;
m_nLongCounter
=
_nLongCounter
;
m_nMidCounter
=
_nMidCounter
;
m_nShortCounter
=
_nShortCounter
;
m_nN
=
_nN
;
m_fTb
=
_fTb
;
m_fTau
=
_fTau
;
m_nkNN
=
_nkNN
;
m_bShadowDetection
=
_bShadowDetection
;
m_nShadowDetection
=
_nShadowDetection
;
}
//refresh rates
void
operator
()(
const
Range
&
range
)
const
int
m_nShortUpdate
=
(
Kshort
/
m_nN
)
+
1
;
int
m_nMidUpdate
=
(
Kmid
/
m_nN
)
+
1
;
int
m_nLongUpdate
=
(
Klong
/
m_nN
)
+
1
;
//int m_nShortUpdate = MAX((Kshort/m_nN),m_nN);
//int m_nMidUpdate = MAX((Kmid/m_nN),m_nN);
//int m_nLongUpdate = MAX((Klong/m_nN),m_nN);
//update counters for the refresh rate
int
m_nLongCounter
=
_nLongCounter
;
int
m_nMidCounter
=
_nMidCounter
;
int
m_nShortCounter
=
_nShortCounter
;
_nShortCounter
++
;
//0,1,...,m_nShortUpdate-1
_nMidCounter
++
;
_nLongCounter
++
;
if
(
_nShortCounter
>=
m_nShortUpdate
)
_nShortCounter
=
0
;
if
(
_nMidCounter
>=
m_nMidUpdate
)
_nMidCounter
=
0
;
if
(
_nLongCounter
>=
m_nLongUpdate
)
_nLongCounter
=
0
;
//go through the image
long
i
=
0
;
for
(
long
y
=
0
;
y
<
_src
.
rows
;
y
++
)
{
{
for
(
long
x
=
0
;
x
<
_src
.
cols
;
x
++
)
int
y0
=
range
.
start
,
y1
=
range
.
end
;
int
ncols
=
src
->
cols
,
nchannels
=
src
->
channels
();
int
ndata
=
nchannels
+
1
;
for
(
int
y
=
y0
;
y
<
y1
;
y
++
)
{
{
const
uchar
*
data
=
_src
.
ptr
((
int
)
y
,
(
int
)
x
);
const
uchar
*
data
=
src
->
ptr
(
y
);
uchar
*
m_aModel
=
m_aModel0
+
ncols
*
m_nN
*
3
*
ndata
*
y
;
//update model+ background subtract
uchar
*
m_nNextLongUpdate
=
m_nNextLongUpdate0
+
ncols
*
y
;
uchar
include
=
0
;
uchar
*
m_nNextMidUpdate
=
m_nNextMidUpdate0
+
ncols
*
y
;
int
result
=
_cvCheckPixelBackgroundNP
(
i
,
data
,
nchannels
,
uchar
*
m_nNextShortUpdate
=
m_nNextShortUpdate0
+
ncols
*
y
;
m_nN
,
m_aModel
,
m_fTb
,
m_nkNN
,
m_fTau
,
m_bShadowDetection
,
include
);
uchar
*
m_aModelIndexLong
=
m_aModelIndexLong0
+
ncols
*
y
;
uchar
*
m_aModelIndexMid
=
m_aModelIndexMid0
+
ncols
*
y
;
_cvUpdatePixelBackgroundNP
(
i
,
data
,
nchannels
,
uchar
*
m_aModelIndexShort
=
m_aModelIndexShort0
+
ncols
*
y
;
m_nN
,
m_aModel
,
uchar
*
mask
=
dst
->
ptr
(
y
);
m_nNextLongUpdate
,
m_nNextMidUpdate
,
for
(
int
x
=
0
;
x
<
ncols
;
x
++
)
m_nNextShortUpdate
,
m_aModelIndexLong
,
m_aModelIndexMid
,
m_aModelIndexShort
,
m_nLongCounter
,
m_nMidCounter
,
m_nShortCounter
,
m_nLongUpdate
,
m_nMidUpdate
,
m_nShortUpdate
,
include
);
switch
(
result
)
{
{
case
0
:
//foreground
//update model+ background subtract
*
_dst
.
ptr
((
int
)
y
,
(
int
)
x
)
=
255
;
uchar
include
=
0
;
break
;
int
result
=
_cvCheckPixelBackgroundNP
(
data
,
nchannels
,
case
1
:
m_nN
,
m_aModel
,
m_fTb
,
m_nkNN
,
m_fTau
,
m_bShadowDetection
,
include
);
//background
*
_dst
.
ptr
((
int
)
y
,
(
int
)
x
)
=
0
;
_cvUpdatePixelBackgroundNP
(
x
,
data
,
nchannels
,
break
;
m_nN
,
m_aModel
,
case
2
:
m_nNextLongUpdate
,
//shadow
m_nNextMidUpdate
,
*
_dst
.
ptr
((
int
)
y
,
(
int
)
x
)
=
nShadowDetection
;
m_nNextShortUpdate
,
break
;
m_aModelIndexLong
,
m_aModelIndexMid
,
m_aModelIndexShort
,
m_nLongCounter
,
m_nMidCounter
,
m_nShortCounter
,
include
);
switch
(
result
)
{
case
0
:
//foreground
mask
[
x
]
=
255
;
break
;
case
1
:
//background
mask
[
x
]
=
0
;
break
;
case
2
:
//shadow
mask
[
x
]
=
m_nShadowDetection
;
break
;
}
data
+=
nchannels
;
m_aModel
+=
m_nN
*
3
*
ndata
;
}
}
i
++
;
}
}
}
}
}
const
Mat
*
src
;
Mat
*
dst
;
uchar
*
m_aModel0
;
uchar
*
m_nNextLongUpdate0
;
uchar
*
m_nNextMidUpdate0
;
uchar
*
m_nNextShortUpdate0
;
uchar
*
m_aModelIndexLong0
;
uchar
*
m_aModelIndexMid0
;
uchar
*
m_aModelIndexShort0
;
int
m_nLongCounter
;
int
m_nMidCounter
;
int
m_nShortCounter
;
int
m_nN
;
float
m_fTb
;
float
m_fTau
;
int
m_nkNN
;
bool
m_bShadowDetection
;
uchar
m_nShadowDetection
;
};
...
@@ -582,27 +565,57 @@ void BackgroundSubtractorKNNImpl::apply(InputArray _image, OutputArray _fgmask,
...
@@ -582,27 +565,57 @@ void BackgroundSubtractorKNNImpl::apply(InputArray _image, OutputArray _fgmask,
learningRate
=
learningRate
>=
0
&&
nframes
>
1
?
learningRate
:
1.
/
std
::
min
(
2
*
nframes
,
history
);
learningRate
=
learningRate
>=
0
&&
nframes
>
1
?
learningRate
:
1.
/
std
::
min
(
2
*
nframes
,
history
);
CV_Assert
(
learningRate
>=
0
);
CV_Assert
(
learningRate
>=
0
);
//parallel_for_(Range(0, image.rows),
//recalculate update rates - in case alpha is changed
// KNNInvoker(image, fgmask,
// calculate update parameters (using alpha)
icvUpdatePixelBackgroundNP
(
image
,
fgmask
,
int
Kshort
,
Kmid
,
Klong
;
bgmodel
,
//approximate exponential learning curve
nNextLongUpdate
,
Kshort
=
(
int
)(
log
(
0.7
)
/
log
(
1
-
learningRate
))
+
1
;
//Kshort
nNextMidUpdate
,
Kmid
=
(
int
)(
log
(
0.4
)
/
log
(
1
-
learningRate
))
-
Kshort
+
1
;
//Kmid
nNextShortUpdate
,
Klong
=
(
int
)(
log
(
0.1
)
/
log
(
1
-
learningRate
))
-
Kshort
-
Kmid
+
1
;
//Klong
aModelIndexLong
,
aModelIndexMid
,
//refresh rates
aModelIndexShort
,
int
nShortUpdate
=
(
Kshort
/
nN
)
+
1
;
nLongCounter
,
int
nMidUpdate
=
(
Kmid
/
nN
)
+
1
;
nMidCounter
,
int
nLongUpdate
=
(
Klong
/
nN
)
+
1
;
nShortCounter
,
nN
,
parallel_for_
(
Range
(
0
,
image
.
rows
),
(
float
)
learningRate
,
KNNInvoker
(
image
,
fgmask
,
fTb
,
bgmodel
.
ptr
(),
nkNN
,
nNextLongUpdate
.
ptr
(),
fTau
,
nNextMidUpdate
.
ptr
(),
bShadowDetection
,
nNextShortUpdate
.
ptr
(),
nShadowDetection
aModelIndexLong
.
ptr
(),
);
aModelIndexMid
.
ptr
(),
aModelIndexShort
.
ptr
(),
nLongCounter
,
nMidCounter
,
nShortCounter
,
nN
,
fTb
,
nkNN
,
fTau
,
bShadowDetection
,
nShadowDetection
),
image
.
total
()
/
(
double
)(
1
<<
16
));
nShortCounter
++
;
//0,1,...,nShortUpdate-1
nMidCounter
++
;
nLongCounter
++
;
if
(
nShortCounter
>=
nShortUpdate
)
{
nShortCounter
=
0
;
randu
(
nNextShortUpdate
,
Scalar
::
all
(
0
),
Scalar
::
all
(
nShortUpdate
));
}
if
(
nMidCounter
>=
nMidUpdate
)
{
nMidCounter
=
0
;
randu
(
nNextMidUpdate
,
Scalar
::
all
(
0
),
Scalar
::
all
(
nMidUpdate
));
}
if
(
nLongCounter
>=
nLongUpdate
)
{
nLongCounter
=
0
;
randu
(
nNextLongUpdate
,
Scalar
::
all
(
0
),
Scalar
::
all
(
nLongUpdate
));
}
}
}
void
BackgroundSubtractorKNNImpl
::
getBackgroundImage
(
OutputArray
backgroundImage
)
const
void
BackgroundSubtractorKNNImpl
::
getBackgroundImage
(
OutputArray
backgroundImage
)
const
...
...
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