| 69 | // ---------------------------------------------------------------------------------------- |
| 70 | |
| 71 | int main(int argc, char** argv) try |
| 72 | { |
| 73 | // In this example we are going to train a face detector based on the |
| 74 | // small faces dataset in the examples/faces directory. So the first |
| 75 | // thing we do is load that dataset. This means you need to supply the |
| 76 | // path to this faces folder as a command line argument so we will know |
| 77 | // where it is. |
| 78 | if (argc != 2) |
| 79 | { |
| 80 | cout << "Give the path to the examples/faces directory as the argument to this" << endl; |
| 81 | cout << "program. For example, if you are in the examples folder then execute " << endl; |
| 82 | cout << "this program by running: " << endl; |
| 83 | cout << " ./dnn_mmod_ex faces" << endl; |
| 84 | cout << endl; |
| 85 | return 0; |
| 86 | } |
| 87 | const std::string faces_directory = argv[1]; |
| 88 | // The faces directory contains a training dataset and a separate |
| 89 | // testing dataset. The training data consists of 4 images, each |
| 90 | // annotated with rectangles that bound each human face. The idea is |
| 91 | // to use this training data to learn to identify human faces in new |
| 92 | // images. |
| 93 | // |
| 94 | // Once you have trained an object detector it is always important to |
| 95 | // test it on data it wasn't trained on. Therefore, we will also load |
| 96 | // a separate testing set of 5 images. Once we have a face detector |
| 97 | // created from the training data we will see how well it works by |
| 98 | // running it on the testing images. |
| 99 | // |
| 100 | // So here we create the variables that will hold our dataset. |
| 101 | // images_train will hold the 4 training images and face_boxes_train |
| 102 | // holds the locations of the faces in the training images. So for |
| 103 | // example, the image images_train[0] has the faces given by the |
| 104 | // rectangles in face_boxes_train[0]. |
| 105 | std::vector<matrix<rgb_pixel>> images_train, images_test; |
| 106 | std::vector<std::vector<mmod_rect>> face_boxes_train, face_boxes_test; |
| 107 | |
| 108 | // Now we load the data. These XML files list the images in each dataset |
| 109 | // and also contain the positions of the face boxes. Obviously you can use |
| 110 | // any kind of input format you like so long as you store the data into |
| 111 | // images_train and face_boxes_train. But for convenience dlib comes with |
| 112 | // tools for creating and loading XML image datasets. Here you see how to |
| 113 | // load the data. To create the XML files you can use the imglab tool which |
| 114 | // can be found in the tools/imglab folder. It is a simple graphical tool |
| 115 | // for labeling objects in images with boxes. To see how to use it read the |
| 116 | // tools/imglab/README.txt file. |
| 117 | load_image_dataset(images_train, face_boxes_train, faces_directory+"/training.xml"); |
| 118 | load_image_dataset(images_test, face_boxes_test, faces_directory+"/testing.xml"); |
| 119 | |
| 120 | |
| 121 | cout << "num training images: " << images_train.size() << endl; |
| 122 | cout << "num testing images: " << images_test.size() << endl; |
| 123 | |
| 124 | |
| 125 | // The MMOD algorithm has some options you can set to control its behavior. However, |
| 126 | // you can also call the constructor with your training annotations and a "target |
| 127 | // object size" and it will automatically configure itself in a reasonable way for your |
| 128 | // problem. Here we are saying that faces are still recognizably faces when they are |
nothing calls this directly
no test coverage detected