Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv_contrib
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_contrib
Commits
3f1cce24
Commit
3f1cce24
authored
Jul 01, 2015
by
Vlad Shakhuro
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Waldboost with LBP
parent
c05a7e01
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
946 additions
and
0 deletions
+946
-0
cascadeclassifier.h
modules/xobjdetect/src/cascadeclassifier.h
+53
-0
features.cpp
modules/xobjdetect/src/features.cpp
+87
-0
lbpfeatures.cpp
modules/xobjdetect/src/lbpfeatures.cpp
+84
-0
lbpfeatures.h
modules/xobjdetect/src/lbpfeatures.h
+65
-0
main.cpp
modules/xobjdetect/src/main.cpp
+556
-0
traincascade_features.h
modules/xobjdetect/src/traincascade_features.h
+101
-0
No files found.
modules/xobjdetect/src/cascadeclassifier.h
0 → 100644
View file @
3f1cce24
#ifndef _OPENCV_CASCADECLASSIFIER_H_
#define _OPENCV_CASCADECLASSIFIER_H_
#include <ctime>
#include "traincascade_features.h"
#include "lbpfeatures.h"
#define CC_CASCADE_FILENAME "cascade.xml"
#define CC_PARAMS_FILENAME "params.xml"
#define CC_CASCADE_PARAMS "cascadeParams"
#define CC_STAGE_TYPE "stageType"
#define CC_FEATURE_TYPE "featureType"
#define CC_HEIGHT "height"
#define CC_WIDTH "width"
#define CC_STAGE_NUM "stageNum"
#define CC_STAGES "stages"
#define CC_STAGE_PARAMS "stageParams"
#define CC_BOOST "BOOST"
#define CC_BOOST_TYPE "boostType"
#define CC_DISCRETE_BOOST "DAB"
#define CC_REAL_BOOST "RAB"
#define CC_LOGIT_BOOST "LB"
#define CC_GENTLE_BOOST "GAB"
#define CC_MINHITRATE "minHitRate"
#define CC_MAXFALSEALARM "maxFalseAlarm"
#define CC_TRIM_RATE "weightTrimRate"
#define CC_MAX_DEPTH "maxDepth"
#define CC_WEAK_COUNT "maxWeakCount"
#define CC_STAGE_THRESHOLD "stageThreshold"
#define CC_WEAK_CLASSIFIERS "weakClassifiers"
#define CC_INTERNAL_NODES "internalNodes"
#define CC_LEAF_VALUES "leafValues"
#define CC_FEATURES FEATURES
#define CC_FEATURE_PARAMS "featureParams"
#define CC_MAX_CAT_COUNT "maxCatCount"
#define CC_FEATURE_SIZE "featSize"
#define CC_HAAR "HAAR"
#define CC_MODE "mode"
#define CC_MODE_BASIC "BASIC"
#define CC_MODE_CORE "CORE"
#define CC_MODE_ALL "ALL"
#define CC_RECTS "rects"
#define CC_TILTED "tilted"
#define CC_LBP "LBP"
#define CC_RECT "rect"
#endif
modules/xobjdetect/src/features.cpp
0 → 100644
View file @
3f1cce24
#include <opencv2/opencv.hpp>
#include "traincascade_features.h"
#include "cascadeclassifier.h"
using
namespace
std
;
using
namespace
cv
;
float
calcNormFactor
(
const
Mat
&
sum
,
const
Mat
&
sqSum
)
{
CV_DbgAssert
(
sum
.
cols
>
3
&&
sqSum
.
rows
>
3
);
Rect
normrect
(
1
,
1
,
sum
.
cols
-
3
,
sum
.
rows
-
3
);
size_t
p0
,
p1
,
p2
,
p3
;
CV_SUM_OFFSETS
(
p0
,
p1
,
p2
,
p3
,
normrect
,
sum
.
step1
()
)
double
area
=
normrect
.
width
*
normrect
.
height
;
const
int
*
sp
=
sum
.
ptr
<
int
>
();
int
valSum
=
sp
[
p0
]
-
sp
[
p1
]
-
sp
[
p2
]
+
sp
[
p3
];
const
double
*
sqp
=
sqSum
.
ptr
<
double
>
();
double
valSqSum
=
sqp
[
p0
]
-
sqp
[
p1
]
-
sqp
[
p2
]
+
sqp
[
p3
];
return
(
float
)
sqrt
(
(
double
)
(
area
*
valSqSum
-
(
double
)
valSum
*
valSum
)
);
}
CvParams
::
CvParams
()
:
name
(
"params"
)
{}
void
CvParams
::
printDefaults
()
const
{
cout
<<
"--"
<<
name
<<
"--"
<<
endl
;
}
void
CvParams
::
printAttrs
()
const
{}
bool
CvParams
::
scanAttr
(
const
string
,
const
string
)
{
return
false
;
}
//---------------------------- FeatureParams --------------------------------------
CvFeatureParams
::
CvFeatureParams
()
:
maxCatCount
(
0
),
featSize
(
1
)
{
name
=
CC_FEATURE_PARAMS
;
}
void
CvFeatureParams
::
init
(
const
CvFeatureParams
&
fp
)
{
maxCatCount
=
fp
.
maxCatCount
;
featSize
=
fp
.
featSize
;
}
void
CvFeatureParams
::
write
(
FileStorage
&
fs
)
const
{
fs
<<
CC_MAX_CAT_COUNT
<<
maxCatCount
;
fs
<<
CC_FEATURE_SIZE
<<
featSize
;
}
bool
CvFeatureParams
::
read
(
const
FileNode
&
node
)
{
if
(
node
.
empty
()
)
return
false
;
maxCatCount
=
node
[
CC_MAX_CAT_COUNT
];
featSize
=
node
[
CC_FEATURE_SIZE
];
return
(
maxCatCount
>=
0
&&
featSize
>=
1
);
}
Ptr
<
CvFeatureParams
>
CvFeatureParams
::
create
(
int
featureType
)
{
return
Ptr
<
CvFeatureParams
>
(
new
CvLBPFeatureParams
);
}
//------------------------------------- FeatureEvaluator ---------------------------------------
void
CvFeatureEvaluator
::
init
(
const
CvFeatureParams
*
_featureParams
,
int
_maxSampleCount
,
Size
_winSize
)
{
CV_Assert
(
_maxSampleCount
>
0
);
featureParams
=
(
CvFeatureParams
*
)
_featureParams
;
winSize
=
_winSize
;
numFeatures
=
0
;
cls
.
create
(
(
int
)
_maxSampleCount
,
1
,
CV_32FC1
);
generateFeatures
();
}
void
CvFeatureEvaluator
::
setImage
(
const
Mat
&
img
,
uchar
clsLabel
,
int
idx
,
const
std
::
vector
<
int
>&
feature_ind
)
{
//CV_Assert(img.cols == winSize.width);
//CV_Assert(img.rows == winSize.height);
CV_Assert
(
idx
<
cls
.
rows
);
cls
.
ptr
<
float
>
(
idx
)[
0
]
=
clsLabel
;
}
Ptr
<
CvFeatureEvaluator
>
CvFeatureEvaluator
::
create
(
int
type
)
{
return
Ptr
<
CvFeatureEvaluator
>
(
new
CvLBPEvaluator
);
}
modules/xobjdetect/src/lbpfeatures.cpp
0 → 100644
View file @
3f1cce24
#include <opencv2/opencv.hpp>
#include "lbpfeatures.h"
#include "cascadeclassifier.h"
#include <iostream>
using
namespace
cv
;
CvLBPFeatureParams
::
CvLBPFeatureParams
()
{
maxCatCount
=
256
;
name
=
LBPF_NAME
;
}
void
CvLBPEvaluator
::
init
(
const
CvFeatureParams
*
_featureParams
,
int
_maxSampleCount
,
Size
_winSize
)
{
CV_Assert
(
_maxSampleCount
>
0
);
sum
.
create
((
int
)
_maxSampleCount
,
(
_winSize
.
width
+
1
)
*
(
_winSize
.
height
+
1
),
CV_32SC1
);
CvFeatureEvaluator
::
init
(
_featureParams
,
_maxSampleCount
,
_winSize
);
}
void
CvLBPEvaluator
::
setImage
(
const
Mat
&
img
,
uchar
clsLabel
,
int
idx
,
const
std
::
vector
<
int
>
&
feature_ind
)
{
CV_DbgAssert
(
!
sum
.
empty
()
);
CvFeatureEvaluator
::
setImage
(
img
,
clsLabel
,
idx
,
feature_ind
);
integral
(
img
,
sum
);
cur_sum
=
sum
;
offset_
=
int
(
sum
.
ptr
<
int
>
(
1
)
-
sum
.
ptr
<
int
>
());
for
(
size_t
i
=
0
;
i
<
feature_ind
.
size
();
++
i
)
{
features
[
feature_ind
[
i
]].
calcPoints
(
offset_
);
}
}
void
CvLBPEvaluator
::
writeFeatures
(
FileStorage
&
fs
,
const
Mat
&
featureMap
)
const
{
_writeFeatures
(
features
,
fs
,
featureMap
);
}
void
CvLBPEvaluator
::
generateFeatures
()
{
int
offset
=
winSize
.
width
+
1
;
for
(
int
x
=
0
;
x
<
winSize
.
width
;
x
++
)
for
(
int
y
=
0
;
y
<
winSize
.
height
;
y
++
)
for
(
int
w
=
1
;
w
<=
winSize
.
width
/
3
;
w
++
)
for
(
int
h
=
1
;
h
<=
winSize
.
height
/
3
;
h
++
)
if
(
(
x
+
3
*
w
<=
winSize
.
width
)
&&
(
y
+
3
*
h
<=
winSize
.
height
)
)
features
.
push_back
(
Feature
(
offset
,
x
,
y
,
w
,
h
)
);
numFeatures
=
(
int
)
features
.
size
();
}
CvLBPEvaluator
::
Feature
::
Feature
()
{
rect
=
cvRect
(
0
,
0
,
0
,
0
);
}
CvLBPEvaluator
::
Feature
::
Feature
(
int
offset
,
int
x
,
int
y
,
int
_blockWidth
,
int
_blockHeight
)
{
x_
=
x
;
y_
=
y
;
block_w_
=
_blockWidth
;
block_h_
=
_blockHeight
;
offset_
=
offset
;
calcPoints
(
offset
);
}
void
CvLBPEvaluator
::
Feature
::
calcPoints
(
int
offset
)
{
Rect
tr
=
rect
=
cvRect
(
x_
,
y_
,
block_w_
,
block_h_
);
CV_SUM_OFFSETS
(
p
[
0
],
p
[
1
],
p
[
4
],
p
[
5
],
tr
,
offset
)
tr
.
x
+=
2
*
rect
.
width
;
CV_SUM_OFFSETS
(
p
[
2
],
p
[
3
],
p
[
6
],
p
[
7
],
tr
,
offset
)
tr
.
y
+=
2
*
rect
.
height
;
CV_SUM_OFFSETS
(
p
[
10
],
p
[
11
],
p
[
14
],
p
[
15
],
tr
,
offset
)
tr
.
x
-=
2
*
rect
.
width
;
CV_SUM_OFFSETS
(
p
[
8
],
p
[
9
],
p
[
12
],
p
[
13
],
tr
,
offset
)
offset_
=
offset
;
}
void
CvLBPEvaluator
::
Feature
::
write
(
FileStorage
&
fs
)
const
{
fs
<<
CC_RECT
<<
"[:"
<<
rect
.
x
<<
rect
.
y
<<
rect
.
width
<<
rect
.
height
<<
"]"
;
}
modules/xobjdetect/src/lbpfeatures.h
0 → 100644
View file @
3f1cce24
#ifndef _OPENCV_LBPFEATURES_H_
#define _OPENCV_LBPFEATURES_H_
#include "traincascade_features.h"
#define LBPF_NAME "lbpFeatureParams"
struct
CvLBPFeatureParams
:
CvFeatureParams
{
CvLBPFeatureParams
();
};
class
CvLBPEvaluator
:
public
CvFeatureEvaluator
{
public
:
virtual
~
CvLBPEvaluator
()
{}
virtual
void
init
(
const
CvFeatureParams
*
_featureParams
,
int
_maxSampleCount
,
cv
::
Size
_winSize
);
virtual
void
setImage
(
const
cv
::
Mat
&
img
,
uchar
clsLabel
,
int
idx
,
const
std
::
vector
<
int
>
&
feature_ind
);
virtual
void
setWindow
(
const
cv
::
Point
&
p
)
{
cur_sum
=
sum
.
rowRange
(
p
.
y
,
p
.
y
+
winSize
.
height
).
colRange
(
p
.
x
,
p
.
x
+
winSize
.
width
);
}
virtual
float
operator
()(
int
featureIdx
,
int
sampleIdx
)
{
return
(
float
)
features
[
featureIdx
].
calc
(
cur_sum
,
offset_
,
sampleIdx
);
}
virtual
void
writeFeatures
(
cv
::
FileStorage
&
fs
,
const
cv
::
Mat
&
featureMap
)
const
;
protected
:
virtual
void
generateFeatures
();
class
Feature
{
public
:
Feature
();
Feature
(
int
offset
,
int
x
,
int
y
,
int
_block_w
,
int
_block_h
);
uchar
calc
(
const
cv
::
Mat
&
_sum
,
int
offset
,
size_t
y
);
void
write
(
cv
::
FileStorage
&
fs
)
const
;
cv
::
Rect
rect
;
int
p
[
16
];
int
x_
,
y_
,
block_w_
,
block_h_
,
offset_
;
void
calcPoints
(
int
offset
);
};
std
::
vector
<
Feature
>
features
;
cv
::
Mat
sum
,
cur_sum
;
int
offset_
;
};
inline
uchar
CvLBPEvaluator
::
Feature
::
calc
(
const
cv
::
Mat
&
_sum
,
int
offset
,
size_t
y
)
{
const
int
*
psum
=
_sum
.
ptr
<
int
>
();
int
cval
=
psum
[
p
[
5
]]
-
psum
[
p
[
6
]]
-
psum
[
p
[
9
]]
+
psum
[
p
[
10
]];
return
(
uchar
)((
psum
[
p
[
0
]]
-
psum
[
p
[
1
]]
-
psum
[
p
[
4
]]
+
psum
[
p
[
5
]]
>=
cval
?
128
:
0
)
|
// 0
(
psum
[
p
[
1
]]
-
psum
[
p
[
2
]]
-
psum
[
p
[
5
]]
+
psum
[
p
[
6
]]
>=
cval
?
64
:
0
)
|
// 1
(
psum
[
p
[
2
]]
-
psum
[
p
[
3
]]
-
psum
[
p
[
6
]]
+
psum
[
p
[
7
]]
>=
cval
?
32
:
0
)
|
// 2
(
psum
[
p
[
6
]]
-
psum
[
p
[
7
]]
-
psum
[
p
[
10
]]
+
psum
[
p
[
11
]]
>=
cval
?
16
:
0
)
|
// 5
(
psum
[
p
[
10
]]
-
psum
[
p
[
11
]]
-
psum
[
p
[
14
]]
+
psum
[
p
[
15
]]
>=
cval
?
8
:
0
)
|
// 8
(
psum
[
p
[
9
]]
-
psum
[
p
[
10
]]
-
psum
[
p
[
13
]]
+
psum
[
p
[
14
]]
>=
cval
?
4
:
0
)
|
// 7
(
psum
[
p
[
8
]]
-
psum
[
p
[
9
]]
-
psum
[
p
[
12
]]
+
psum
[
p
[
13
]]
>=
cval
?
2
:
0
)
|
// 6
(
psum
[
p
[
4
]]
-
psum
[
p
[
5
]]
-
psum
[
p
[
8
]]
+
psum
[
p
[
9
]]
>=
cval
?
1
:
0
));
// 3
}
#endif
modules/xobjdetect/src/main.cpp
0 → 100644
View file @
3f1cce24
#include <opencv2/opencv.hpp>
#include <vector>
#include <sstream>
#include <cassert>
#include <iostream>
#include <fstream>
#include <iomanip>
#include "lbpfeatures.h"
using
namespace
std
;
using
namespace
cv
;
static
void
compute_cdf
(
const
Mat1b
&
data
,
const
Mat1f
&
weights
,
Mat1f
&
cdf
)
{
for
(
int
i
=
0
;
i
<
cdf
.
cols
;
++
i
)
cdf
(
0
,
i
)
=
0
;
for
(
int
i
=
0
;
i
<
weights
.
cols
;
++
i
)
{
cdf
(
0
,
data
(
0
,
i
))
+=
weights
(
0
,
i
);
}
for
(
int
i
=
1
;
i
<
cdf
.
cols
;
++
i
)
{
cdf
(
0
,
i
)
+=
cdf
(
0
,
i
-
1
);
}
}
void
compute_min_step
(
const
Mat
&
data_pos
,
const
Mat
&
data_neg
,
size_t
n_bins
,
Mat
&
data_min
,
Mat
&
data_step
)
{
// Check that quantized data will fit in unsigned char
assert
(
n_bins
<=
256
);
assert
(
data_pos
.
rows
==
data_neg
.
rows
);
Mat
reduced_pos
,
reduced_neg
;
reduce
(
data_pos
,
reduced_pos
,
1
,
CV_REDUCE_MIN
);
reduce
(
data_neg
,
reduced_neg
,
1
,
CV_REDUCE_MIN
);
min
(
reduced_pos
,
reduced_neg
,
data_min
);
data_min
-=
0.01
;
Mat
data_max
;
reduce
(
data_pos
,
reduced_pos
,
1
,
CV_REDUCE_MAX
);
reduce
(
data_neg
,
reduced_neg
,
1
,
CV_REDUCE_MAX
);
max
(
reduced_pos
,
reduced_neg
,
data_max
);
data_max
+=
0.01
;
data_step
=
(
data_max
-
data_min
)
/
(
n_bins
-
1
);
}
void
quantize_data
(
Mat
&
data
,
Mat1f
&
data_min
,
Mat1f
&
data_step
)
{
#pragma omp parallel for
for
(
int
col
=
0
;
col
<
data
.
cols
;
++
col
)
{
data
.
col
(
col
)
-=
data_min
;
data
.
col
(
col
)
/=
data_step
;
}
data
.
convertTo
(
data
,
CV_8U
);
}
class
WaldBoost
{
public
:
WaldBoost
(
int
weak_count
)
:
weak_count_
(
weak_count
),
thresholds_
(),
alphas_
(),
feature_indices_
(),
polarities_
(),
cascade_thresholds_
()
{}
WaldBoost
()
:
weak_count_
(),
thresholds_
(),
alphas_
(),
feature_indices_
(),
polarities_
(),
cascade_thresholds_
()
{}
vector
<
int
>
get_feature_indices
()
{
return
feature_indices_
;
}
void
detect
(
Ptr
<
CvFeatureEvaluator
>
eval
,
const
Mat
&
img
,
const
vector
<
float
>&
scales
,
vector
<
Rect
>&
bboxes
,
Mat1f
&
confidences
)
{
bboxes
.
clear
();
confidences
.
release
();
Mat
resized_img
;
int
step
=
4
;
float
h
;
for
(
size_t
i
=
0
;
i
<
scales
.
size
();
++
i
)
{
float
scale
=
scales
[
i
];
resize
(
img
,
resized_img
,
Size
(),
scale
,
scale
);
eval
->
setImage
(
resized_img
,
0
,
0
,
feature_indices_
);
int
n_rows
=
24
/
scale
;
int
n_cols
=
24
/
scale
;
for
(
int
r
=
0
;
r
+
24
<
resized_img
.
rows
;
r
+=
step
)
{
for
(
int
c
=
0
;
c
+
24
<
resized_img
.
cols
;
c
+=
step
)
{
//eval->setImage(resized_img(Rect(c, r, 24, 24)), 0, 0);
eval
->
setWindow
(
Point
(
c
,
r
));
if
(
predict
(
eval
,
&
h
)
==
+
1
)
{
int
row
=
r
/
scale
;
int
col
=
c
/
scale
;
bboxes
.
push_back
(
Rect
(
col
,
row
,
n_cols
,
n_rows
));
confidences
.
push_back
(
h
);
}
}
}
}
groupRectangles
(
bboxes
,
3
,
0.7
);
}
void
fit
(
Mat
&
data_pos
,
Mat
&
data_neg
)
{
// data_pos: F x N_pos
// data_neg: F x N_neg
// every feature corresponds to row
// every sample corresponds to column
assert
(
data_pos
.
rows
>=
weak_count_
);
assert
(
data_pos
.
rows
==
data_neg
.
rows
);
vector
<
bool
>
feature_ignore
;
for
(
int
i
=
0
;
i
<
data_pos
.
rows
;
++
i
)
{
feature_ignore
.
push_back
(
false
);
}
Mat1f
pos_weights
(
1
,
data_pos
.
cols
,
1.0
f
/
(
2
*
data_pos
.
cols
));
Mat1f
neg_weights
(
1
,
data_neg
.
cols
,
1.0
f
/
(
2
*
data_neg
.
cols
));
Mat1f
pos_trace
(
1
,
data_pos
.
cols
,
0.0
f
);
Mat1f
neg_trace
(
1
,
data_neg
.
cols
,
0.0
f
);
bool
quantize
=
false
;
if
(
data_pos
.
type
()
!=
CV_8U
)
{
cerr
<<
"quantize"
<<
endl
;
quantize
=
true
;
}
Mat1f
data_min
,
data_step
;
int
n_bins
=
256
;
if
(
quantize
)
{
compute_min_step
(
data_pos
,
data_neg
,
n_bins
,
data_min
,
data_step
);
quantize_data
(
data_pos
,
data_min
,
data_step
);
quantize_data
(
data_neg
,
data_min
,
data_step
);
}
cerr
<<
"pos="
<<
data_pos
.
cols
<<
" neg="
<<
data_neg
.
cols
<<
endl
;
for
(
int
i
=
0
;
i
<
weak_count_
;
++
i
)
{
// Train weak learner with lowest error using weights
double
min_err
=
DBL_MAX
;
int
min_feature_ind
=
-
1
;
int
min_polarity
=
0
;
int
threshold_q
=
0
;
float
min_threshold
=
0
;
#pragma omp parallel for
for
(
int
feat_i
=
0
;
feat_i
<
data_pos
.
rows
;
++
feat_i
)
{
if
(
feature_ignore
[
feat_i
])
continue
;
// Construct cdf
Mat1f
pos_cdf
(
1
,
n_bins
),
neg_cdf
(
1
,
n_bins
);
compute_cdf
(
data_pos
.
row
(
feat_i
),
pos_weights
,
pos_cdf
);
compute_cdf
(
data_neg
.
row
(
feat_i
),
neg_weights
,
neg_cdf
);
float
neg_total
=
sum
(
neg_weights
)[
0
];
Mat1f
err_direct
=
pos_cdf
+
neg_total
-
neg_cdf
;
Mat1f
err_backward
=
1.0
f
-
err_direct
;
int
idx1
[
2
],
idx2
[
2
];
double
err1
,
err2
;
minMaxIdx
(
err_direct
,
&
err1
,
NULL
,
idx1
);
minMaxIdx
(
err_backward
,
&
err2
,
NULL
,
idx2
);
#pragma omp critical
{
if
(
min
(
err1
,
err2
)
<
min_err
)
{
if
(
err1
<
err2
)
{
min_err
=
err1
;
min_polarity
=
+
1
;
threshold_q
=
idx1
[
1
];
}
else
{
min_err
=
err2
;
min_polarity
=
-
1
;
threshold_q
=
idx2
[
1
];
}
min_feature_ind
=
feat_i
;
if
(
quantize
)
{
min_threshold
=
data_min
(
feat_i
,
0
)
+
data_step
(
feat_i
,
0
)
*
(
threshold_q
+
.5
f
);
}
else
{
min_threshold
=
threshold_q
+
.5
f
;
}
}
}
}
float
alpha
=
.5
f
*
log
((
1
-
min_err
)
/
min_err
);
alphas_
.
push_back
(
alpha
);
feature_indices_
.
push_back
(
min_feature_ind
);
thresholds_
.
push_back
(
min_threshold
);
polarities_
.
push_back
(
min_polarity
);
feature_ignore
[
min_feature_ind
]
=
true
;
double
loss
=
0
;
// Update positive weights
for
(
int
j
=
0
;
j
<
data_pos
.
cols
;
++
j
)
{
int
val
=
data_pos
.
at
<
unsigned
char
>
(
min_feature_ind
,
j
);
int
label
=
min_polarity
*
(
val
-
threshold_q
)
>=
0
?
+
1
:
-
1
;
pos_weights
(
0
,
j
)
*=
exp
(
-
alpha
*
label
);
pos_trace
(
0
,
j
)
+=
alpha
*
label
;
loss
+=
exp
(
-
pos_trace
(
0
,
j
))
/
(
2.0
f
*
data_pos
.
cols
);
}
double
min_pos
,
max_neg
=
-
100000
;
minMaxIdx
(
pos_trace
,
&
min_pos
,
NULL
);
// Update negative weights
for
(
int
j
=
0
;
j
<
data_neg
.
cols
;
++
j
)
{
int
val
=
data_neg
.
at
<
unsigned
char
>
(
min_feature_ind
,
j
);
int
label
=
min_polarity
*
(
val
-
threshold_q
)
>=
0
?
+
1
:
-
1
;
neg_weights
(
0
,
j
)
*=
exp
(
alpha
*
label
);
neg_trace
(
0
,
j
)
+=
alpha
*
label
;
loss
+=
exp
(
+
neg_trace
(
0
,
j
))
/
(
2.0
f
*
data_neg
.
cols
);
}
// Compute threshold
double
a
=
0.02
;
int
col_pos
=
0
,
col_neg
=
0
;
int
cur_pos
=
0
,
cur_neg
=
0
;
int
max_col
=
-
1
;
bool
max_pos
=
false
;
for
(;
col_pos
<
data_pos
.
cols
&&
col_neg
<
data_neg
.
cols
;
)
{
bool
pos
=
false
;
if
(
data_pos
.
at
<
uchar
>
(
min_feature_ind
,
col_pos
)
<
data_pos
.
at
<
uchar
>
(
min_feature_ind
,
col_neg
))
{
col_pos
+=
1
;
cur_pos
+=
1
;
pos
=
true
;
}
else
{
col_neg
+=
1
;
cur_neg
+=
1
;
}
float
p_neg
=
cur_neg
/
(
float
)
data_neg
.
cols
;
float
p_pos
=
cur_pos
/
(
float
)
data_pos
.
cols
;
if
(
a
*
p_neg
>
p_pos
)
{
if
(
pos
)
max_col
=
col_pos
;
else
max_col
=
col_neg
;
max_pos
=
pos
;
}
}
if
(
max_pos
)
{
cascade_thresholds_
.
push_back
(
pos_trace
(
0
,
max_col
));
}
else
{
cascade_thresholds_
.
push_back
(
neg_trace
(
0
,
max_col
));
}
cerr
<<
"i="
<<
setw
(
4
)
<<
i
;
cerr
<<
" feat="
<<
setw
(
5
)
<<
min_feature_ind
;
cerr
<<
" thr="
<<
setw
(
3
)
<<
threshold_q
;
cerr
<<
" alpha="
<<
fixed
<<
setprecision
(
3
)
<<
alpha
<<
" err="
<<
fixed
<<
setprecision
(
3
)
<<
min_err
<<
" loss="
<<
scientific
<<
loss
<<
endl
;
if
(
loss
<
1e-50
||
min_err
>
0.5
)
{
cerr
<<
"Stopping early"
<<
endl
;
weak_count_
=
i
+
1
;
break
;
}
// Normalize weights
double
z
=
(
sum
(
pos_weights
)
+
sum
(
neg_weights
))[
0
];
pos_weights
/=
z
;
neg_weights
/=
z
;
}
}
int
predict
(
Ptr
<
CvFeatureEvaluator
>
eval
,
float
*
h
)
const
{
const
float
thr
=
-
2.5
;
assert
(
feature_indices_
.
size
()
==
size_t
(
weak_count_
));
float
res
=
0
;
for
(
int
i
=
0
;
i
<
weak_count_
;
++
i
)
{
float
val
=
(
*
eval
)(
feature_indices_
[
i
],
0
);
int
label
=
polarities_
[
i
]
*
(
val
-
thresholds_
[
i
])
>
0
?
+
1
:
-
1
;
res
+=
alphas_
[
i
]
*
label
;
if
(
res
<
cascade_thresholds_
[
i
])
{
return
-
1
;
}
}
*
h
=
res
;
return
res
>
thr
?
+
1
:
-
1
;
}
void
save
(
const
string
&
filename
)
{
ofstream
f
(
filename
.
c_str
());
f
<<
weak_count_
<<
endl
;
for
(
size_t
i
=
0
;
i
<
thresholds_
.
size
();
++
i
)
{
f
<<
thresholds_
[
i
]
<<
" "
;
}
f
<<
endl
;
for
(
size_t
i
=
0
;
i
<
alphas_
.
size
();
++
i
)
{
f
<<
alphas_
[
i
]
<<
" "
;
}
f
<<
endl
;
for
(
size_t
i
=
0
;
i
<
polarities_
.
size
();
++
i
)
{
f
<<
polarities_
[
i
]
<<
" "
;
}
f
<<
endl
;
for
(
size_t
i
=
0
;
i
<
cascade_thresholds_
.
size
();
++
i
)
{
f
<<
cascade_thresholds_
[
i
]
<<
" "
;
}
f
<<
endl
;
for
(
size_t
i
=
0
;
i
<
feature_indices_
.
size
();
++
i
)
{
f
<<
feature_indices_
[
i
]
<<
" "
;
}
f
<<
endl
;
}
void
load
(
const
string
&
filename
)
{
ifstream
f
(
filename
.
c_str
());
f
>>
weak_count_
;
thresholds_
.
resize
(
weak_count_
);
alphas_
.
resize
(
weak_count_
);
polarities_
.
resize
(
weak_count_
);
cascade_thresholds_
.
resize
(
weak_count_
);
feature_indices_
.
resize
(
weak_count_
);
for
(
int
i
=
0
;
i
<
weak_count_
;
++
i
)
{
f
>>
thresholds_
[
i
];
}
for
(
int
i
=
0
;
i
<
weak_count_
;
++
i
)
{
f
>>
alphas_
[
i
];
}
for
(
int
i
=
0
;
i
<
weak_count_
;
++
i
)
{
f
>>
polarities_
[
i
];
}
for
(
int
i
=
0
;
i
<
weak_count_
;
++
i
)
{
f
>>
cascade_thresholds_
[
i
];
}
for
(
int
i
=
0
;
i
<
weak_count_
;
++
i
)
{
f
>>
feature_indices_
[
i
];
}
}
void
reset
(
int
weak_count
)
{
weak_count_
=
weak_count
;
thresholds_
.
clear
();
alphas_
.
clear
();
feature_indices_
.
clear
();
polarities_
.
clear
();
cascade_thresholds_
.
clear
();
}
~
WaldBoost
()
{
}
private
:
int
weak_count_
;
vector
<
float
>
thresholds_
;
vector
<
float
>
alphas_
;
vector
<
int
>
feature_indices_
;
vector
<
int
>
polarities_
;
vector
<
float
>
cascade_thresholds_
;
};
void
test_boosting
();
void
train_boosting
();
int
main
(
int
argc
,
char
**
argv
)
{
string
stage
=
argv
[
1
];
if
(
stage
==
"train"
)
{
train_boosting
();
}
else
if
(
stage
==
"detect"
)
{
test_boosting
();
}
}
vector
<
Mat
>
read_imgs
(
const
string
&
path
)
{
vector
<
String
>
filenames
;
glob
(
path
,
filenames
);
vector
<
Mat
>
imgs
;
for
(
size_t
i
=
0
;
i
<
filenames
.
size
();
++
i
)
{
imgs
.
push_back
(
imread
(
filenames
[
i
],
CV_LOAD_IMAGE_GRAYSCALE
));
}
return
imgs
;
}
vector
<
Mat
>
sample_patches
(
const
string
&
path
,
int
n_rows
,
int
n_cols
,
int
n_patches
)
{
vector
<
String
>
filenames
;
glob
(
path
,
filenames
);
vector
<
Mat
>
patches
;
int
patch_count
=
0
;
for
(
size_t
i
=
0
;
i
<
filenames
.
size
();
++
i
)
{
Mat
img
=
imread
(
filenames
[
i
],
CV_LOAD_IMAGE_GRAYSCALE
);
for
(
int
row
=
0
;
row
+
n_rows
<
img
.
rows
;
row
+=
n_rows
)
{
for
(
int
col
=
0
;
col
+
n_cols
<
img
.
cols
;
col
+=
n_cols
)
{
patches
.
push_back
(
img
(
Rect
(
col
,
row
,
n_cols
,
n_rows
)).
clone
());
patch_count
+=
1
;
if
(
patch_count
==
n_patches
)
{
goto
sampling_finished
;
}
}
}
}
sampling_finished
:
return
patches
;
}
void
train_boosting
()
{
cerr
<<
"read imgs"
<<
endl
;
vector
<
Mat
>
pos_imgs
=
read_imgs
(
"/home/vlad/gsoc/lfw_faces"
);
assert
(
pos_imgs
.
size
());
const
char
neg_path
[]
=
"/home/vlad/gsoc/rtsd_bg"
;
vector
<
Mat
>
neg_imgs
=
sample_patches
(
neg_path
,
24
,
24
,
pos_imgs
.
size
());
assert
(
neg_imgs
.
size
());
int
n_features
;
Mat
pos_data
,
neg_data
;
Ptr
<
CvFeatureEvaluator
>
eval
=
CvFeatureEvaluator
::
create
(
CvFeatureParams
::
LBP
);
eval
->
init
(
CvFeatureParams
::
create
(
CvFeatureParams
::
LBP
),
1
,
Size
(
24
,
24
));
n_features
=
eval
->
getNumFeatures
();
const
int
stages
[]
=
{
32
,
64
,
128
,
256
,
512
,
1024
,
2048
,
4096
};
const
int
stage_count
=
sizeof
(
stages
)
/
sizeof
(
*
stages
);
const
int
stage_neg
=
5000
;
const
int
max_per_image
=
25
;
const
float
scales_arr
[]
=
{
.3
,
.4
,
.5
,
.6
,
.7
,
.8
,
.9
,
1
};
const
vector
<
float
>
scales
(
scales_arr
,
scales_arr
+
sizeof
(
scales_arr
)
/
sizeof
(
*
scales_arr
));
WaldBoost
boost
;
vector
<
String
>
neg_filenames
;
glob
(
neg_path
,
neg_filenames
);
for
(
int
i
=
0
;
i
<
stage_count
;
++
i
)
{
cerr
<<
"compute features"
<<
endl
;
pos_data
=
Mat1b
(
n_features
,
pos_imgs
.
size
());
neg_data
=
Mat1b
(
n_features
,
neg_imgs
.
size
());
for
(
size_t
k
=
0
;
k
<
pos_imgs
.
size
();
++
k
)
{
eval
->
setImage
(
pos_imgs
[
k
],
+
1
,
0
,
boost
.
get_feature_indices
());
for
(
int
j
=
0
;
j
<
n_features
;
++
j
)
{
pos_data
.
at
<
uchar
>
(
j
,
k
)
=
(
*
eval
)(
j
,
0
);
}
}
for
(
size_t
k
=
0
;
k
<
neg_imgs
.
size
();
++
k
)
{
eval
->
setImage
(
neg_imgs
[
k
],
0
,
0
,
boost
.
get_feature_indices
());
for
(
int
j
=
0
;
j
<
n_features
;
++
j
)
{
neg_data
.
at
<
uchar
>
(
j
,
k
)
=
(
*
eval
)(
j
,
0
);
}
}
boost
.
reset
(
stages
[
i
]);
boost
.
fit
(
pos_data
,
neg_data
);
if
(
i
+
1
==
stage_count
)
{
break
;
}
int
bootstrap_count
=
0
;
int
img_i
=
0
;
for
(;
img_i
<
neg_filenames
.
size
();
++
img_i
)
{
cerr
<<
"win "
<<
bootstrap_count
<<
"/"
<<
stage_neg
<<
" img "
<<
(
img_i
+
1
)
<<
"/"
<<
neg_filenames
.
size
()
<<
"
\r
"
;
Mat
img
=
imread
(
neg_filenames
[
img_i
],
CV_LOAD_IMAGE_GRAYSCALE
);
vector
<
Rect
>
bboxes
;
Mat1f
confidences
;
boost
.
detect
(
eval
,
img
,
scales
,
bboxes
,
confidences
);
if
(
confidences
.
rows
>
0
)
{
Mat1i
indices
;
sortIdx
(
confidences
,
indices
,
CV_SORT_EVERY_COLUMN
+
CV_SORT_DESCENDING
);
int
win_count
=
min
(
max_per_image
,
confidences
.
rows
);
win_count
=
min
(
win_count
,
stage_neg
-
bootstrap_count
);
Mat
window
;
for
(
int
k
=
0
;
k
<
win_count
;
++
k
)
{
resize
(
img
(
bboxes
[
indices
(
k
,
0
)]),
window
,
Size
(
24
,
24
));
neg_imgs
.
push_back
(
window
.
clone
());
bootstrap_count
+=
1
;
}
if
(
bootstrap_count
>=
stage_neg
)
{
break
;
}
}
}
cerr
<<
"bootstrapped "
<<
bootstrap_count
<<
" windows from "
<<
(
img_i
+
1
)
<<
" images"
<<
endl
;
}
boost
.
save
(
"models/model.txt"
);
vector
<
int
>
feature_indices
=
boost
.
get_feature_indices
();
Mat1i
feature_map
(
1
,
feature_indices
.
size
());
for
(
size_t
i
=
0
;
i
<
feature_indices
.
size
();
++
i
)
{
feature_map
(
0
,
i
)
=
feature_indices
[
i
];
}
FileStorage
fs
(
"models/features.yaml"
,
FileStorage
::
WRITE
);
eval
->
writeFeatures
(
fs
,
feature_map
);
}
void
test_boosting
()
{
WaldBoost
boost
;
const
char
model_filename
[]
=
"models/model.txt"
;
boost
.
load
(
model_filename
);
Mat
test_img
=
imread
(
"imgs/test4.png"
,
CV_LOAD_IMAGE_GRAYSCALE
);
vector
<
Rect
>
bboxes
;
Mat1f
confidences
;
vector
<
float
>
scales
;
for
(
float
scale
=
0.2
f
;
scale
<
1.2
f
;
scale
*=
1.2
)
{
scales
.
push_back
(
scale
);
}
Ptr
<
CvFeatureParams
>
params
=
CvFeatureParams
::
create
(
CvFeatureParams
::
LBP
);
Ptr
<
CvFeatureEvaluator
>
eval
=
CvFeatureEvaluator
::
create
(
CvFeatureParams
::
LBP
);
eval
->
init
(
params
,
1
,
Size
(
24
,
24
));
boost
.
detect
(
eval
,
test_img
,
scales
,
bboxes
,
confidences
);
cerr
<<
"detected "
<<
bboxes
.
size
()
<<
" objects"
<<
endl
;
for
(
size_t
i
=
0
;
i
<
bboxes
.
size
();
++
i
)
{
rectangle
(
test_img
,
bboxes
[
i
],
Scalar
(
255
,
0
,
0
));
}
imwrite
(
"imgs/out.png"
,
test_img
);
}
modules/xobjdetect/src/traincascade_features.h
0 → 100644
View file @
3f1cce24
#ifndef _OPENCV_FEATURES_H_
#define _OPENCV_FEATURES_H_
#include <stdio.h>
#define FEATURES "features"
#define CV_SUM_OFFSETS( p0, p1, p2, p3, rect, step ) \
/* (x, y) */
\
(p0) = (rect).x + (step) * (rect).y; \
/* (x + w, y) */
\
(p1) = (rect).x + (rect).width + (step) * (rect).y; \
/* (x + w, y) */
\
(p2) = (rect).x + (step) * ((rect).y + (rect).height); \
/* (x + w, y + h) */
\
(p3) = (rect).x + (rect).width + (step) * ((rect).y + (rect).height);
#define CV_TILTED_OFFSETS( p0, p1, p2, p3, rect, step ) \
/* (x, y) */
\
(p0) = (rect).x + (step) * (rect).y; \
/* (x - h, y + h) */
\
(p1) = (rect).x - (rect).height + (step) * ((rect).y + (rect).height);\
/* (x + w, y + w) */
\
(p2) = (rect).x + (rect).width + (step) * ((rect).y + (rect).width); \
/* (x + w - h, y + w + h) */
\
(p3) = (rect).x + (rect).width - (rect).height \
+ (step) * ((rect).y + (rect).width + (rect).height);
float
calcNormFactor
(
const
cv
::
Mat
&
sum
,
const
cv
::
Mat
&
sqSum
);
template
<
class
Feature
>
void
_writeFeatures
(
const
std
::
vector
<
Feature
>
features
,
cv
::
FileStorage
&
fs
,
const
cv
::
Mat
&
featureMap
)
{
fs
<<
FEATURES
<<
"["
;
const
cv
::
Mat_
<
int
>&
featureMap_
=
(
const
cv
::
Mat_
<
int
>&
)
featureMap
;
for
(
int
fi
=
0
;
fi
<
featureMap
.
cols
;
fi
++
)
if
(
featureMap_
(
0
,
fi
)
>=
0
)
{
fs
<<
"{"
;
features
[
fi
].
write
(
fs
);
fs
<<
"}"
;
}
fs
<<
"]"
;
}
class
CvParams
{
public
:
CvParams
();
virtual
~
CvParams
()
{}
// from|to file
virtual
void
write
(
cv
::
FileStorage
&
fs
)
const
=
0
;
virtual
bool
read
(
const
cv
::
FileNode
&
node
)
=
0
;
// from|to screen
virtual
void
printDefaults
()
const
;
virtual
void
printAttrs
()
const
;
virtual
bool
scanAttr
(
const
std
::
string
prmName
,
const
std
::
string
val
);
std
::
string
name
;
};
class
CvFeatureParams
:
public
CvParams
{
public
:
enum
{
HAAR
=
0
,
LBP
=
1
,
HOG
=
2
};
CvFeatureParams
();
virtual
void
init
(
const
CvFeatureParams
&
fp
);
virtual
void
write
(
cv
::
FileStorage
&
fs
)
const
;
virtual
bool
read
(
const
cv
::
FileNode
&
node
);
static
cv
::
Ptr
<
CvFeatureParams
>
create
(
int
featureType
);
int
maxCatCount
;
// 0 in case of numerical features
int
featSize
;
// 1 in case of simple features (HAAR, LBP) and N_BINS(9)*N_CELLS(4) in case of Dalal's HOG features
};
class
CvFeatureEvaluator
{
public
:
virtual
~
CvFeatureEvaluator
()
{}
virtual
void
init
(
const
CvFeatureParams
*
_featureParams
,
int
_maxSampleCount
,
cv
::
Size
_winSize
);
virtual
void
setImage
(
const
cv
::
Mat
&
img
,
uchar
clsLabel
,
int
idx
,
const
std
::
vector
<
int
>
&
feature_ind
);
virtual
void
setWindow
(
const
cv
::
Point
&
p
)
=
0
;
virtual
void
writeFeatures
(
cv
::
FileStorage
&
fs
,
const
cv
::
Mat
&
featureMap
)
const
=
0
;
virtual
float
operator
()(
int
featureIdx
,
int
sampleIdx
)
=
0
;
static
cv
::
Ptr
<
CvFeatureEvaluator
>
create
(
int
type
);
int
getNumFeatures
()
const
{
return
numFeatures
;
}
int
getMaxCatCount
()
const
{
return
featureParams
->
maxCatCount
;
}
int
getFeatureSize
()
const
{
return
featureParams
->
featSize
;
}
const
cv
::
Mat
&
getCls
()
const
{
return
cls
;
}
float
getCls
(
int
si
)
const
{
return
cls
.
at
<
float
>
(
si
,
0
);
}
protected
:
virtual
void
generateFeatures
()
=
0
;
int
npos
,
nneg
;
int
numFeatures
;
cv
::
Size
winSize
;
CvFeatureParams
*
featureParams
;
cv
::
Mat
cls
;
};
#endif
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