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
047b1ca4
Commit
047b1ca4
authored
Nov 16, 2014
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3419 from samyak-268:2.4
parents
8ebd474c
a3f05474
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
239 additions
and
0 deletions
+239
-0
facial_features.cpp
samples/cpp/facial_features.cpp
+239
-0
No files found.
samples/cpp/facial_features.cpp
0 → 100644
View file @
047b1ca4
/*
* Author: Samyak Datta (datta[dot]samyak[at]gmail.com)
*
* A program to detect facial feature points using
* Haarcascade classifiers for face, eyes, nose and mouth
*
*/
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using
namespace
std
;
using
namespace
cv
;
// Functions to parse command-line arguments
static
string
getCommandOption
(
const
vector
<
string
>&
,
const
string
&
);
static
void
setCommandOptions
(
vector
<
string
>&
,
int
,
char
**
);
static
bool
doesCmdOptionExist
(
const
vector
<
string
>&
,
const
string
&
);
// Functions for facial feature detection
static
void
help
();
static
void
detectFaces
(
Mat
&
,
vector
<
Rect_
<
int
>
>&
,
string
);
static
void
detectEyes
(
Mat
&
,
vector
<
Rect_
<
int
>
>&
,
string
);
static
void
detectNose
(
Mat
&
,
vector
<
Rect_
<
int
>
>&
,
string
);
static
void
detectMouth
(
Mat
&
,
vector
<
Rect_
<
int
>
>&
,
string
);
static
void
detectFacialFeaures
(
Mat
&
,
const
vector
<
Rect_
<
int
>
>
,
string
,
string
,
string
);
string
input_image_path
;
string
face_cascade_path
,
eye_cascade_path
,
nose_cascade_path
,
mouth_cascade_path
;
int
main
(
int
argc
,
char
**
argv
)
{
if
(
argc
<
3
)
{
help
();
return
1
;
}
// Extract command-line options
vector
<
string
>
args
;
setCommandOptions
(
args
,
argc
,
argv
);
input_image_path
=
argv
[
1
];
face_cascade_path
=
argv
[
2
];
eye_cascade_path
=
(
doesCmdOptionExist
(
args
,
"-eyes"
))
?
getCommandOption
(
args
,
"-eyes"
)
:
""
;
nose_cascade_path
=
(
doesCmdOptionExist
(
args
,
"-nose"
))
?
getCommandOption
(
args
,
"-nose"
)
:
""
;
mouth_cascade_path
=
(
doesCmdOptionExist
(
args
,
"-mouth"
))
?
getCommandOption
(
args
,
"-mouth"
)
:
""
;
// Load image and cascade classifier files
Mat
image
;
image
=
imread
(
input_image_path
);
// Detect faces and facial features
vector
<
Rect_
<
int
>
>
faces
;
detectFaces
(
image
,
faces
,
face_cascade_path
);
detectFacialFeaures
(
image
,
faces
,
eye_cascade_path
,
nose_cascade_path
,
mouth_cascade_path
);
imshow
(
"Result"
,
image
);
waitKey
(
0
);
return
0
;
}
void
setCommandOptions
(
vector
<
string
>&
args
,
int
argc
,
char
**
argv
)
{
for
(
int
i
=
1
;
i
<
argc
;
++
i
)
{
args
.
push_back
(
argv
[
i
]);
}
return
;
}
string
getCommandOption
(
const
vector
<
string
>&
args
,
const
string
&
opt
)
{
string
answer
;
vector
<
string
>::
const_iterator
it
=
find
(
args
.
begin
(),
args
.
end
(),
opt
);
if
(
it
!=
args
.
end
()
&&
(
++
it
!=
args
.
end
()))
answer
=
*
it
;
return
answer
;
}
bool
doesCmdOptionExist
(
const
vector
<
string
>&
args
,
const
string
&
opt
)
{
vector
<
string
>::
const_iterator
it
=
find
(
args
.
begin
(),
args
.
end
(),
opt
);
return
(
it
!=
args
.
end
());
}
static
void
help
()
{
cout
<<
"
\n
This file demonstrates facial feature points detection using Haarcascade classifiers.
\n
"
"The program detects a face and eyes, nose and mouth inside the face."
"The code has been tested on the Japanese Female Facial Expression (JAFFE) database and found"
"to give reasonably accurate results.
\n
"
;
cout
<<
"
\n
USAGE: ./cpp-example-facial_features [IMAGE] [FACE_CASCADE] [OPTIONS]
\n
"
"IMAGE
\n\t
Path to the image of a face taken as input.
\n
"
"FACE_CASCSDE
\n\t
Path to a haarcascade classifier for face detection.
\n
"
"OPTIONS:
\n
There are 3 options available which are described in detail. There must be a "
"space between the option and it's argument (All three options accept arguments).
\n
"
"
\t
-eyes : Specify the haarcascade classifier for eye detection.
\n
"
"
\t
-nose : Specify the haarcascade classifier for nose detection.
\n
"
"
\t
-mouth : Specify the haarcascade classifier for mouth detection.
\n
"
;
cout
<<
"EXAMPLE:
\n
"
"(1) ./cpp-example-facial_features image.jpg face.xml -eyes eyes.xml -mouth mouth.xml
\n
"
"
\t
This will detect the face, eyes and mouth in image.jpg.
\n
"
"(2) ./cpp-example-facial_features image.jpg face.xml -nose nose.xml
\n
"
"
\t
This will detect the face and nose in image.jpg.
\n
"
"(3) ./cpp-example-facial_features image.jpg face.xml
\n
"
"
\t
This will detect only the face in image.jpg.
\n
"
;
cout
<<
"
\n\n
The classifiers for face and eyes can be downloaded from : "
"
\n
https://github.com/Itseez/opencv/tree/master/data/haarcascades"
;
cout
<<
"
\n\n
The classifiers for nose and mouth can be downloaded from : "
"
\n
https://github.com/Itseez/opencv_contrib/tree/master/modules/face/data/cascades
\n
"
;
}
static
void
detectFaces
(
Mat
&
img
,
vector
<
Rect_
<
int
>
>&
faces
,
string
cascade_path
)
{
CascadeClassifier
face_cascade
;
face_cascade
.
load
(
cascade_path
);
face_cascade
.
detectMultiScale
(
img
,
faces
,
1.15
,
3
,
0
|
CASCADE_SCALE_IMAGE
,
Size
(
30
,
30
));
return
;
}
static
void
detectFacialFeaures
(
Mat
&
img
,
const
vector
<
Rect_
<
int
>
>
faces
,
string
eye_cascade
,
string
nose_cascade
,
string
mouth_cascade
)
{
for
(
unsigned
int
i
=
0
;
i
<
faces
.
size
();
++
i
)
{
// Mark the bounding box enclosing the face
Rect
face
=
faces
[
i
];
rectangle
(
img
,
Point
(
face
.
x
,
face
.
y
),
Point
(
face
.
x
+
face
.
width
,
face
.
y
+
face
.
height
),
Scalar
(
255
,
0
,
0
),
1
,
4
);
// Eyes, nose and mouth will be detected inside the face (region of interest)
Mat
ROI
=
img
(
Rect
(
face
.
x
,
face
.
y
,
face
.
width
,
face
.
height
));
// Check if all features (eyes, nose and mouth) are being detected
bool
is_full_detection
=
false
;
if
(
(
!
eye_cascade
.
empty
())
&&
(
!
nose_cascade
.
empty
())
&&
(
!
mouth_cascade
.
empty
())
)
is_full_detection
=
true
;
// Detect eyes if classifier provided by the user
if
(
!
eye_cascade
.
empty
())
{
vector
<
Rect_
<
int
>
>
eyes
;
detectEyes
(
ROI
,
eyes
,
eye_cascade
);
// Mark points corresponding to the centre of the eyes
for
(
unsigned
int
j
=
0
;
j
<
eyes
.
size
();
++
j
)
{
Rect
e
=
eyes
[
j
];
circle
(
ROI
,
Point
(
e
.
x
+
e
.
width
/
2
,
e
.
y
+
e
.
height
/
2
),
3
,
Scalar
(
0
,
255
,
0
),
-
1
,
8
);
/* rectangle(ROI, Point(e.x, e.y), Point(e.x+e.width, e.y+e.height),
Scalar(0, 255, 0), 1, 4); */
}
}
// Detect nose if classifier provided by the user
double
nose_center_height
=
0.0
;
if
(
!
nose_cascade
.
empty
())
{
vector
<
Rect_
<
int
>
>
nose
;
detectNose
(
ROI
,
nose
,
nose_cascade
);
// Mark points corresponding to the centre (tip) of the nose
for
(
unsigned
int
j
=
0
;
j
<
nose
.
size
();
++
j
)
{
Rect
n
=
nose
[
j
];
circle
(
ROI
,
Point
(
n
.
x
+
n
.
width
/
2
,
n
.
y
+
n
.
height
/
2
),
3
,
Scalar
(
0
,
255
,
0
),
-
1
,
8
);
nose_center_height
=
(
n
.
y
+
n
.
height
/
2
);
}
}
// Detect mouth if classifier provided by the user
double
mouth_center_height
=
0.0
;
if
(
!
mouth_cascade
.
empty
())
{
vector
<
Rect_
<
int
>
>
mouth
;
detectMouth
(
ROI
,
mouth
,
mouth_cascade
);
for
(
unsigned
int
j
=
0
;
j
<
mouth
.
size
();
++
j
)
{
Rect
m
=
mouth
[
j
];
mouth_center_height
=
(
m
.
y
+
m
.
height
/
2
);
// The mouth should lie below the nose
if
(
(
is_full_detection
)
&&
(
mouth_center_height
>
nose_center_height
)
)
{
rectangle
(
ROI
,
Point
(
m
.
x
,
m
.
y
),
Point
(
m
.
x
+
m
.
width
,
m
.
y
+
m
.
height
),
Scalar
(
0
,
255
,
0
),
1
,
4
);
}
else
if
(
(
is_full_detection
)
&&
(
mouth_center_height
<=
nose_center_height
)
)
continue
;
else
rectangle
(
ROI
,
Point
(
m
.
x
,
m
.
y
),
Point
(
m
.
x
+
m
.
width
,
m
.
y
+
m
.
height
),
Scalar
(
0
,
255
,
0
),
1
,
4
);
}
}
}
return
;
}
static
void
detectEyes
(
Mat
&
img
,
vector
<
Rect_
<
int
>
>&
eyes
,
string
cascade_path
)
{
CascadeClassifier
eyes_cascade
;
eyes_cascade
.
load
(
cascade_path
);
eyes_cascade
.
detectMultiScale
(
img
,
eyes
,
1.20
,
5
,
0
|
CASCADE_SCALE_IMAGE
,
Size
(
30
,
30
));
return
;
}
static
void
detectNose
(
Mat
&
img
,
vector
<
Rect_
<
int
>
>&
nose
,
string
cascade_path
)
{
CascadeClassifier
nose_cascade
;
nose_cascade
.
load
(
cascade_path
);
nose_cascade
.
detectMultiScale
(
img
,
nose
,
1.20
,
5
,
0
|
CASCADE_SCALE_IMAGE
,
Size
(
30
,
30
));
return
;
}
static
void
detectMouth
(
Mat
&
img
,
vector
<
Rect_
<
int
>
>&
mouth
,
string
cascade_path
)
{
CascadeClassifier
mouth_cascade
;
mouth_cascade
.
load
(
cascade_path
);
mouth_cascade
.
detectMultiScale
(
img
,
mouth
,
1.20
,
5
,
0
|
CASCADE_SCALE_IMAGE
,
Size
(
30
,
30
));
return
;
}
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