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
246a793d
Commit
246a793d
authored
Jul 14, 2014
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2972 from apavlenko:24_face_rec_sample
parents
d31a0eab
64d8cf1e
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
75 additions
and
60 deletions
+75
-60
facerec_demo.cpp
samples/cpp/facerec_demo.cpp
+75
-60
No files found.
samples/cpp/facerec_demo.cpp
View file @
246a793d
...
...
@@ -27,35 +27,38 @@
using
namespace
cv
;
using
namespace
std
;
static
Mat
toGrayscale
(
InputArray
_src
)
{
Mat
src
=
_src
.
getMat
();
// only allow one channel
if
(
src
.
channels
()
!=
1
)
{
CV_Error
(
CV_StsBadArg
,
"Only Matrices with one channel are supported"
);
}
// create and return normalized image
Mat
dst
;
cv
::
normalize
(
_src
,
dst
,
0
,
255
,
NORM_MINMAX
,
CV_8UC1
);
return
dst
;
}
static
void
read_csv
(
const
string
&
filename
,
vector
<
Mat
>&
images
,
vector
<
int
>&
labels
,
std
::
map
<
int
,
string
>&
labelsInfo
,
char
separator
=
';'
)
{
std
::
ifstream
file
(
filename
.
c_str
(),
ifstream
::
in
);
if
(
!
file
)
{
string
error_message
=
"No valid input file was given, please check the given filename."
;
CV_Error
(
CV_StsBadArg
,
error_message
);
}
ifstream
csv
(
filename
.
c_str
());
if
(
!
csv
)
CV_Error
(
CV_StsBadArg
,
"No valid input file was given, please check the given filename."
);
string
line
,
path
,
classlabel
,
info
;
while
(
getline
(
file
,
line
))
{
while
(
getline
(
csv
,
line
))
{
stringstream
liness
(
line
);
path
.
clear
();
classlabel
.
clear
();
info
.
clear
();
getline
(
liness
,
path
,
separator
);
getline
(
liness
,
classlabel
,
separator
);
getline
(
liness
,
info
,
separator
);
if
(
!
path
.
empty
()
&&
!
classlabel
.
empty
())
{
images
.
push_back
(
imread
(
path
,
0
))
;
labels
.
push_back
(
atoi
(
classlabel
.
c_str
()
));
cout
<<
"Processing "
<<
path
<<
endl
;
int
label
=
atoi
(
classlabel
.
c_str
(
));
if
(
!
info
.
empty
())
labelsInfo
.
insert
(
std
::
make_pair
(
labels
.
back
(),
info
));
labelsInfo
.
insert
(
std
::
make_pair
(
label
,
info
));
// 'path' can be file, dir or wildcard path
String
root
(
path
.
c_str
());
vector
<
String
>
files
;
glob
(
root
,
files
,
true
);
for
(
vector
<
String
>::
const_iterator
f
=
files
.
begin
();
f
!=
files
.
end
();
++
f
)
{
cout
<<
"
\t
"
<<
*
f
<<
endl
;
Mat
img
=
imread
(
*
f
,
CV_LOAD_IMAGE_GRAYSCALE
);
static
int
w
=-
1
,
h
=-
1
;
static
bool
showSmallSizeWarning
=
true
;
if
(
w
>
0
&&
h
>
0
&&
(
w
!=
img
.
cols
||
h
!=
img
.
rows
))
cout
<<
"
\t
* Warning: images should be of the same size!"
<<
endl
;
if
(
showSmallSizeWarning
&&
(
img
.
cols
<
50
||
img
.
rows
<
50
))
{
cout
<<
"* Warning: for better results images should be not smaller than 50x50!"
<<
endl
;
showSmallSizeWarning
=
false
;
}
images
.
push_back
(
img
);
labels
.
push_back
(
label
);
}
}
}
}
...
...
@@ -63,8 +66,17 @@ static void read_csv(const string& filename, vector<Mat>& images, vector<int>& l
int
main
(
int
argc
,
const
char
*
argv
[])
{
// Check for valid command line arguments, print usage
// if no arguments were given.
if
(
argc
!=
2
)
{
cout
<<
"usage: "
<<
argv
[
0
]
<<
" <csv.ext>"
<<
endl
;
if
(
argc
!=
2
&&
argc
!=
3
)
{
cout
<<
"Usage: "
<<
argv
[
0
]
<<
" <csv> [arg2]
\n
"
<<
"
\t
<csv> - path to config file in CSV format
\n
"
<<
"
\t
arg2 - if the 2nd argument is provided (with any value) "
<<
"the advanced stuff is run and shown to console.
\n
"
<<
"The CSV config file consists of the following lines:
\n
"
<<
"<path>;<label>[;<comment>]
\n
"
<<
"
\t
<path> - file, dir or wildcard path
\n
"
<<
"
\t
<label> - non-negative integer person label
\n
"
<<
"
\t
<comment> - optional comment string (e.g. person name)"
<<
endl
;
exit
(
1
);
}
// Get the path to your CSV.
...
...
@@ -88,10 +100,6 @@ int main(int argc, const char *argv[]) {
string
error_message
=
"This demo needs at least 2 images to work. Please add more images to your data set!"
;
CV_Error
(
CV_StsError
,
error_message
);
}
// Get the height from the first image. We'll need this
// later in code to reshape the images to their original
// size:
int
height
=
images
[
0
].
rows
;
// The following lines simply get the last images from
// your dataset and remove it from the vector. This is
// done, so that the training data (which we learn the
...
...
@@ -118,6 +126,9 @@ int main(int argc, const char *argv[]) {
Ptr
<
FaceRecognizer
>
model
=
createEigenFaceRecognizer
();
model
->
setLabelsInfo
(
labelsInfo
);
model
->
train
(
images
,
labels
);
string
saveModelPath
=
"face-rec-model.txt"
;
cout
<<
"Saving the trained model to "
<<
saveModelPath
<<
endl
;
model
->
save
(
saveModelPath
);
// The following line predicts the label of a given
// test image:
...
...
@@ -133,39 +144,43 @@ int main(int argc, const char *argv[]) {
cout
<<
result_message
<<
endl
;
if
(
(
predictedLabel
==
testLabel
)
&&
!
model
->
getLabelInfo
(
predictedLabel
).
empty
()
)
cout
<<
format
(
"%d-th label's info: %s"
,
predictedLabel
,
model
->
getLabelInfo
(
predictedLabel
).
c_str
())
<<
endl
;
// Sometimes you'll need to get/set internal model data,
// which isn't exposed by the public cv::FaceRecognizer.
// Since each cv::FaceRecognizer is derived from a
// cv::Algorithm, you can query the data.
//
// First we'll use it to set the threshold of the FaceRecognizer
// to 0.0 without retraining the model. This can be useful if
// you are evaluating the model:
//
model
->
set
(
"threshold"
,
0.0
);
// Now the threshold of this model is set to 0.0. A prediction
// now returns -1, as it's impossible to have a distance below
// it
predictedLabel
=
model
->
predict
(
testSample
);
cout
<<
"Predicted class = "
<<
predictedLabel
<<
endl
;
// Here is how to get the eigenvalues of this Eigenfaces model:
Mat
eigenvalues
=
model
->
getMat
(
"eigenvalues"
);
// And we can do the same to display the Eigenvectors (read Eigenfaces):
Mat
W
=
model
->
getMat
(
"eigenvectors"
);
// From this we will display the (at most) first 10 Eigenfaces:
for
(
int
i
=
0
;
i
<
min
(
10
,
W
.
cols
);
i
++
)
{
string
msg
=
format
(
"Eigenvalue #%d = %.5f"
,
i
,
eigenvalues
.
at
<
double
>
(
i
));
cout
<<
msg
<<
endl
;
// get eigenvector #i
Mat
ev
=
W
.
col
(
i
).
clone
();
// Reshape to original size & normalize to [0...255] for imshow.
Mat
grayscale
=
toGrayscale
(
ev
.
reshape
(
1
,
height
));
// Show the image & apply a Jet colormap for better sensing.
Mat
cgrayscale
;
applyColorMap
(
grayscale
,
cgrayscale
,
COLORMAP_JET
);
imshow
(
format
(
"%d"
,
i
),
cgrayscale
);
}
waitKey
(
0
);
// advanced stuff
if
(
argc
>
2
)
{
// Sometimes you'll need to get/set internal model data,
// which isn't exposed by the public cv::FaceRecognizer.
// Since each cv::FaceRecognizer is derived from a
// cv::Algorithm, you can query the data.
//
// First we'll use it to set the threshold of the FaceRecognizer
// to 0.0 without retraining the model. This can be useful if
// you are evaluating the model:
//
model
->
set
(
"threshold"
,
0.0
);
// Now the threshold of this model is set to 0.0. A prediction
// now returns -1, as it's impossible to have a distance below
// it
predictedLabel
=
model
->
predict
(
testSample
);
cout
<<
"Predicted class = "
<<
predictedLabel
<<
endl
;
// Here is how to get the eigenvalues of this Eigenfaces model:
Mat
eigenvalues
=
model
->
getMat
(
"eigenvalues"
);
// And we can do the same to display the Eigenvectors (read Eigenfaces):
Mat
W
=
model
->
getMat
(
"eigenvectors"
);
// From this we will display the (at most) first 10 Eigenfaces:
for
(
int
i
=
0
;
i
<
min
(
10
,
W
.
cols
);
i
++
)
{
string
msg
=
format
(
"Eigenvalue #%d = %.5f"
,
i
,
eigenvalues
.
at
<
double
>
(
i
));
cout
<<
msg
<<
endl
;
// get eigenvector #i
Mat
ev
=
W
.
col
(
i
).
clone
();
// Reshape to original size & normalize to [0...255] for imshow.
Mat
grayscale
;
normalize
(
ev
.
reshape
(
1
),
grayscale
,
0
,
255
,
NORM_MINMAX
,
CV_8UC1
);
// Show the image & apply a Jet colormap for better sensing.
Mat
cgrayscale
;
applyColorMap
(
grayscale
,
cgrayscale
,
COLORMAP_JET
);
imshow
(
format
(
"%d"
,
i
),
cgrayscale
);
}
waitKey
(
0
);
}
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