mirror of https://github.com/davisking/dlib.git
Added initial version of shape training example
This commit is contained in:
parent
5ae170c461
commit
b191400a00
|
@ -94,5 +94,6 @@ add_example(thread_pool_ex)
|
||||||
add_example(threads_ex)
|
add_example(threads_ex)
|
||||||
add_example(timer_ex)
|
add_example(timer_ex)
|
||||||
add_example(train_object_detector)
|
add_example(train_object_detector)
|
||||||
|
add_example(train_shape_predictor_ex)
|
||||||
add_example(using_custom_kernels_ex)
|
add_example(using_custom_kernels_ex)
|
||||||
add_example(xml_parser_ex)
|
add_example(xml_parser_ex)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,139 @@
|
||||||
|
// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
The pose estimator was created by using dlib's implementation of the paper:
|
||||||
|
One Millisecond Face Alignment with an Ensemble of Regression Trees by
|
||||||
|
Vahid Kazemi and Josephine Sullivan, CVPR 2014
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <dlib/image_processing.h>
|
||||||
|
#include <dlib/data_io.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace dlib;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
std::vector<std::vector<double> > get_interocular_distances (
|
||||||
|
const std::vector<std::vector<full_object_detection> >& objects
|
||||||
|
);
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// In this example we are going to train a shape_predictor based on the
|
||||||
|
// small faces dataset in the examples/faces directory. So the first
|
||||||
|
// thing we do is load that dataset. This means you need to supply the
|
||||||
|
// path to this faces folder as a command line argument so we will know
|
||||||
|
// where it is.
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
cout << "Give the path to the examples/faces directory as the argument to this" << endl;
|
||||||
|
cout << "program. For example, if you are in the examples folder then execute " << endl;
|
||||||
|
cout << "this program by running: " << endl;
|
||||||
|
cout << " ./train_shape_predictor_ex faces" << endl;
|
||||||
|
cout << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const std::string faces_directory = argv[1];
|
||||||
|
// The faces directory contains a training dataset and a separate
|
||||||
|
// testing dataset. The training data consists of 4 images, each
|
||||||
|
// annotated with rectangles that bound each human face along with 68
|
||||||
|
// face landmarks on each face. The idea is to use this training data
|
||||||
|
// to learn to identify the position of landmarks on human faces in new
|
||||||
|
// images.
|
||||||
|
//
|
||||||
|
// Once you have trained a shape_predictor it is always important to
|
||||||
|
// test it on data it wasn't trained on. Therefore, we will also load
|
||||||
|
// a separate testing set of 5 images. Once we have a shape_predictor
|
||||||
|
// created from the training data we will see how well it works by
|
||||||
|
// running it on the testing images.
|
||||||
|
//
|
||||||
|
// So here we create the variables that will hold our dataset.
|
||||||
|
// images_train will hold the 4 training images and face_boxes_train
|
||||||
|
// holds the locations of the faces in the training images. So for
|
||||||
|
// example, the image images_train[0] has the faces given by the
|
||||||
|
// full_object_detections in face_boxes_train[0].
|
||||||
|
dlib::array<array2d<unsigned char> > images_train, images_test;
|
||||||
|
std::vector<std::vector<full_object_detection> > faces_train, faces_test;
|
||||||
|
|
||||||
|
// Now we load the data. These XML files list the images in each
|
||||||
|
// dataset and also contain the positions of the face boxes and landmark
|
||||||
|
// (called parts in the XML file). Obviously you can use any kind of
|
||||||
|
// input format you like so long as you store the data into images_train
|
||||||
|
// and faces_train.
|
||||||
|
load_image_dataset(images_train, faces_train, faces_directory+"/training_with_face_landmarks.xml");
|
||||||
|
load_image_dataset(images_test, faces_test, faces_directory+"/testing_with_face_landmarks.xml");
|
||||||
|
|
||||||
|
shape_predictor_trainer trainer;
|
||||||
|
shape_predictor sp = trainer.train(images_train, faces_train);
|
||||||
|
|
||||||
|
|
||||||
|
cout << "mean training error: "<< test_shape_predictor(sp, images_train, faces_train, get_interocular_distances(faces_train)) << endl;
|
||||||
|
cout << "mean testing error: "<< test_shape_predictor(sp, images_test, faces_test, get_interocular_distances(faces_test)) << endl;
|
||||||
|
|
||||||
|
serialize("sp.dat") << sp;
|
||||||
|
}
|
||||||
|
catch (exception& e)
|
||||||
|
{
|
||||||
|
cout << "\nexception thrown!" << endl;
|
||||||
|
cout << e.what() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
double interocular_distance (
|
||||||
|
const full_object_detection& det
|
||||||
|
)
|
||||||
|
{
|
||||||
|
dlib::vector<double,2> l, r;
|
||||||
|
double cnt = 0;
|
||||||
|
// Find the center of the left eye by averaging the points around
|
||||||
|
// the eye.
|
||||||
|
for (unsigned long i = 36; i <= 41; ++i)
|
||||||
|
{
|
||||||
|
l += det.part(i);
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
l /= cnt;
|
||||||
|
|
||||||
|
// Find the center of the right eye by averaging the points around
|
||||||
|
// the eye.
|
||||||
|
cnt = 0;
|
||||||
|
for (unsigned long i = 42; i <= 47; ++i)
|
||||||
|
{
|
||||||
|
r += det.part(i);
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
r /= cnt;
|
||||||
|
|
||||||
|
// Now return the distance between the centers of the eyes
|
||||||
|
return length(l-r);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::vector<double> > get_interocular_distances (
|
||||||
|
const std::vector<std::vector<full_object_detection> >& objects
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::vector<double> > temp(objects.size());
|
||||||
|
for (unsigned long i = 0; i < objects.size(); ++i)
|
||||||
|
{
|
||||||
|
for (unsigned long j = 0; j < objects[i].size(); ++j)
|
||||||
|
{
|
||||||
|
temp[i].push_back(interocular_distance(objects[i][j]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue