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
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
140 additions
and
127 deletions
+140
-127
bgfg_KNN.cpp
modules/video/src/bgfg_KNN.cpp
+140
-127
No files found.
modules/video/src/bgfg_KNN.cpp
View file @
60456083
...
...
@@ -259,10 +259,8 @@ protected:
String
name_
;
};
//{ to do - paralelization ...
//struct KNNInvoker....
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_nNextLongUpdate
,
uchar
*
m_nNextMidUpdate
,
...
...
@@ -273,70 +271,53 @@ CV_INLINE void
int
m_nLongCounter
,
int
m_nMidCounter
,
int
m_nShortCounter
,
int
m_nLongUpdate
,
int
m_nMidUpdate
,
int
m_nShortUpdate
,
uchar
include
)
{
// hold the offset
int
ndata
=
1
+
nchannels
;
long
offsetLong
=
ndata
*
(
pixel
*
m_nN
*
3
+
m_aModelIndexLong
[
pixel
]
+
m_nN
*
2
);
long
offsetMid
=
ndata
*
(
pixel
*
m_nN
*
3
+
m_aModelIndexMid
[
pixel
]
+
m_nN
*
1
);
long
offsetShort
=
ndata
*
(
pixel
*
m_nN
*
3
+
m_aModelIndexShort
[
pixel
]);
long
offsetLong
=
ndata
*
(
m_aModelIndexLong
[
x_idx
]
+
m_nN
*
2
);
long
offsetMid
=
ndata
*
(
m_aModelIndexMid
[
x_idx
]
+
m_nN
*
1
);
long
offsetShort
=
ndata
*
(
m_aModelIndexShort
[
x_idx
]);
// 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)
memcpy
(
&
m_aModel
[
offsetLong
],
&
m_aModel
[
offsetMid
],
ndata
*
sizeof
(
unsigned
char
));
// increase the index
m_aModelIndexLong
[
pixel
]
=
(
m_aModelIndexLong
[
pixel
]
>=
(
m_nN
-
1
))
?
0
:
(
m_aModelIndexLong
[
pixel
]
+
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;
m_aModelIndexLong
[
x_idx
]
=
(
m_aModelIndexLong
[
x_idx
]
>=
(
m_nN
-
1
))
?
0
:
(
m_aModelIndexLong
[
x_idx
]
+
1
);
};
// 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)
memcpy
(
&
m_aModel
[
offsetMid
],
&
m_aModel
[
offsetShort
],
ndata
*
sizeof
(
unsigned
char
));
// increase the index
m_aModelIndexMid
[
pixel
]
=
(
m_aModelIndexMid
[
pixel
]
>=
(
m_nN
-
1
))
?
0
:
(
m_aModelIndexMid
[
pixel
]
+
1
);
};
if
(
m_nMidCounter
==
(
m_nMidUpdate
-
1
))
{
m_nNextMidUpdate
[
pixel
]
=
(
uchar
)(
rand
()
%
m_nMidUpdate
);
m_aModelIndexMid
[
x_idx
]
=
(
m_aModelIndexMid
[
x_idx
]
>=
(
m_nN
-
1
))
?
0
:
(
m_aModelIndexMid
[
x_idx
]
+
1
);
};
// 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)
memcpy
(
&
m_aModel
[
offsetShort
],
data
,
n
data
*
sizeof
(
unsigned
char
));
memcpy
(
&
m_aModel
[
offsetShort
],
data
,
n
channels
*
sizeof
(
unsigned
char
));
//set the include flag
m_aModel
[
offsetShort
+
nchannels
]
=
include
;
// increase the index
m_aModelIndexShort
[
pixel
]
=
(
m_aModelIndexShort
[
pixel
]
>=
(
m_nN
-
1
))
?
0
:
(
m_aModelIndexShort
[
pixel
]
+
1
);
};
if
(
m_nShortCounter
==
(
m_nShortUpdate
-
1
))
{
m_nNextShortUpdate
[
pixel
]
=
(
uchar
)(
rand
()
%
m_nShortUpdate
);
m_aModelIndexShort
[
x_idx
]
=
(
m_aModelIndexShort
[
x_idx
]
>=
(
m_nN
-
1
))
?
0
:
(
m_aModelIndexShort
[
x_idx
]
+
1
);
};
}
CV_INLINE
int
_cvCheckPixelBackgroundNP
(
long
pixel
,
const
uchar
*
data
,
int
nchannels
,
_cvCheckPixelBackgroundNP
(
const
uchar
*
data
,
int
nchannels
,
int
m_nN
,
uchar
*
m_aModel
,
float
m_fTb
,
int
m_nkNN
,
float
tau
,
int
m_n
ShadowDetection
,
bool
m_b
ShadowDetection
,
uchar
&
include
)
{
int
Pbf
=
0
;
// the total probability that this pixel is background
...
...
@@ -347,12 +328,11 @@ CV_INLINE int
include
=
0
;
//do we include this pixel into background model?
int
ndata
=
nchannels
+
1
;
long
posPixel
=
pixel
*
ndata
*
m_nN
*
3
;
// float k;
// now increase the probability for each pixel
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
float
dist2
;
...
...
@@ -399,12 +379,12 @@ CV_INLINE int
int
Ps
=
0
;
// the total probability that this pixel is background shadow
// Detected as moving object, perform shadow detection
if
(
m_
n
ShadowDetection
)
if
(
m_
b
ShadowDetection
)
{
for
(
int
n
=
0
;
n
<
m_nN
*
3
;
n
++
)
{
//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
{
...
...
@@ -445,89 +425,74 @@ CV_INLINE int
return
0
;
}
CV_INLINE
void
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
,
class
KNNInvoker
:
public
ParallelLoopBody
{
public
:
KNNInvoker
(
const
Mat
&
_src
,
Mat
&
_dst
,
uchar
*
_bgmodel
,
uchar
*
_nNextLongUpdate
,
uchar
*
_nNextMidUpdate
,
uchar
*
_nNextShortUpdate
,
uchar
*
_aModelIndexLong
,
uchar
*
_aModelIndexMid
,
uchar
*
_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
());
//model
uchar
*
m_aModel
=
_bgmodel
.
ptr
(
0
);
uchar
*
m_nNextLongUpdate
=
_nNextLongUpdate
.
ptr
(
0
);
uchar
*
m_nNextMidUpdate
=
_nNextMidUpdate
.
ptr
(
0
);
uchar
*
m_nNextShortUpdate
=
_nNextShortUpdate
.
ptr
(
0
);
uchar
*
m_aModelIndexLong
=
_aModelIndexLong
.
ptr
(
0
);
uchar
*
m_aModelIndexMid
=
_aModelIndexMid
.
ptr
(
0
);
uchar
*
m_aModelIndexShort
=
_aModelIndexShort
.
ptr
(
0
);
//some constants
int
m_nN
=
_nN
;
float
m_fAlphaT
=
_fAlphaT
;
float
m_fTb
=
_fTb
;
//Tb - threshold on the distance
float
m_fTau
=
_fTau
;
int
m_nkNN
=
_nkNN
;
int
m_bShadowDetection
=
_bShadowDetection
;
//recalculate update rates - in case alpha is changed
// calculate update parameters (using alpha)
int
Kshort
,
Kmid
,
Klong
;
//approximate exponential learning curve
Kshort
=
(
int
)(
log
(
0.7
)
/
log
(
1
-
m_fAlphaT
))
+
1
;
//Kshort
Kmid
=
(
int
)(
log
(
0.4
)
/
log
(
1
-
m_fAlphaT
))
-
Kshort
+
1
;
//Kmid
Klong
=
(
int
)(
log
(
0.1
)
/
log
(
1
-
m_fAlphaT
))
-
Kshort
-
Kmid
+
1
;
//Klong
//refresh rates
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
;
bool
_bShadowDetection
,
uchar
_nShadowDetection
)
{
src
=
&
_src
;
dst
=
&
_dst
;
m_aModel0
=
_bgmodel
;
m_nNextLongUpdate0
=
_nNextLongUpdate
;
m_nNextMidUpdate0
=
_nNextMidUpdate
;
m_nNextShortUpdate0
=
_nNextShortUpdate
;
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
;
}
_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
;
void
operator
()(
const
Range
&
range
)
const
{
int
y0
=
range
.
start
,
y1
=
range
.
end
;
int
ncols
=
src
->
cols
,
nchannels
=
src
->
channels
();
int
ndata
=
nchannels
+
1
;
//go through the image
long
i
=
0
;
for
(
long
y
=
0
;
y
<
_src
.
rows
;
y
++
)
for
(
int
y
=
y0
;
y
<
y1
;
y
++
)
{
for
(
long
x
=
0
;
x
<
_src
.
cols
;
x
++
)
const
uchar
*
data
=
src
->
ptr
(
y
);
uchar
*
m_aModel
=
m_aModel0
+
ncols
*
m_nN
*
3
*
ndata
*
y
;
uchar
*
m_nNextLongUpdate
=
m_nNextLongUpdate0
+
ncols
*
y
;
uchar
*
m_nNextMidUpdate
=
m_nNextMidUpdate0
+
ncols
*
y
;
uchar
*
m_nNextShortUpdate
=
m_nNextShortUpdate0
+
ncols
*
y
;
uchar
*
m_aModelIndexLong
=
m_aModelIndexLong0
+
ncols
*
y
;
uchar
*
m_aModelIndexMid
=
m_aModelIndexMid0
+
ncols
*
y
;
uchar
*
m_aModelIndexShort
=
m_aModelIndexShort0
+
ncols
*
y
;
uchar
*
mask
=
dst
->
ptr
(
y
);
for
(
int
x
=
0
;
x
<
ncols
;
x
++
)
{
const
uchar
*
data
=
_src
.
ptr
((
int
)
y
,
(
int
)
x
);
//update model+ background subtract
uchar
include
=
0
;
int
result
=
_cvCheckPixelBackgroundNP
(
i
,
data
,
nchannels
,
int
result
=
_cvCheckPixelBackgroundNP
(
data
,
nchannels
,
m_nN
,
m_aModel
,
m_fTb
,
m_nkNN
,
m_fTau
,
m_bShadowDetection
,
include
);
_cvUpdatePixelBackgroundNP
(
i
,
data
,
nchannels
,
_cvUpdatePixelBackgroundNP
(
x
,
data
,
nchannels
,
m_nN
,
m_aModel
,
m_nNextLongUpdate
,
m_nNextMidUpdate
,
...
...
@@ -538,30 +503,48 @@ CV_INLINE void
m_nLongCounter
,
m_nMidCounter
,
m_nShortCounter
,
m_nLongUpdate
,
m_nMidUpdate
,
m_nShortUpdate
,
include
);
switch
(
result
)
{
case
0
:
//foreground
*
_dst
.
ptr
((
int
)
y
,
(
int
)
x
)
=
255
;
mask
[
x
]
=
255
;
break
;
case
1
:
//background
*
_dst
.
ptr
((
int
)
y
,
(
int
)
x
)
=
0
;
mask
[
x
]
=
0
;
break
;
case
2
:
//shadow
*
_dst
.
ptr
((
int
)
y
,
(
int
)
x
)
=
nShadowDetection
;
mask
[
x
]
=
m_
nShadowDetection
;
break
;
}
i
++
;
data
+=
nchannels
;
m_aModel
+=
m_nN
*
3
*
ndata
;
}
}
}
}
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,
learningRate
=
learningRate
>=
0
&&
nframes
>
1
?
learningRate
:
1.
/
std
::
min
(
2
*
nframes
,
history
);
CV_Assert
(
learningRate
>=
0
);
//parallel_for_(Range(0, image.rows),
// KNNInvoker(image, fgmask,
icvUpdatePixelBackgroundNP
(
image
,
fgmask
,
bgmodel
,
nNextLongUpdate
,
nNextMidUpdate
,
nNextShortUpdate
,
aModelIndexLong
,
aModelIndexMid
,
aModelIndexShort
,
//recalculate update rates - in case alpha is changed
// calculate update parameters (using alpha)
int
Kshort
,
Kmid
,
Klong
;
//approximate exponential learning curve
Kshort
=
(
int
)(
log
(
0.7
)
/
log
(
1
-
learningRate
))
+
1
;
//Kshort
Kmid
=
(
int
)(
log
(
0.4
)
/
log
(
1
-
learningRate
))
-
Kshort
+
1
;
//Kmid
Klong
=
(
int
)(
log
(
0.1
)
/
log
(
1
-
learningRate
))
-
Kshort
-
Kmid
+
1
;
//Klong
//refresh rates
int
nShortUpdate
=
(
Kshort
/
nN
)
+
1
;
int
nMidUpdate
=
(
Kmid
/
nN
)
+
1
;
int
nLongUpdate
=
(
Klong
/
nN
)
+
1
;
parallel_for_
(
Range
(
0
,
image
.
rows
),
KNNInvoker
(
image
,
fgmask
,
bgmodel
.
ptr
(),
nNextLongUpdate
.
ptr
(),
nNextMidUpdate
.
ptr
(),
nNextShortUpdate
.
ptr
(),
aModelIndexLong
.
ptr
(),
aModelIndexMid
.
ptr
(),
aModelIndexShort
.
ptr
(),
nLongCounter
,
nMidCounter
,
nShortCounter
,
nN
,
(
float
)
learningRate
,
fTb
,
nkNN
,
fTau
,
bShadowDetection
,
nShadowDetection
);
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
...
...
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