facemark_demo_lbf.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. This file was part of GSoC Project: Facemark API for OpenCV
  3. Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc
  4. Student: Laksono Kurnianggoro
  5. Mentor: Delia Passalacqua
  6. */
  7. /*----------------------------------------------
  8. * Usage:
  9. * facemark_demo_lbf <face_cascade_model> <saved_model_filename> <training_images> <annotation_files> [test_files]
  10. *
  11. * Example:
  12. * facemark_demo_lbf ../face_cascade.xml ../LBF.model ../images_train.txt ../points_train.txt ../test.txt
  13. *
  14. * Notes:
  15. * the user should provides the list of training images_train
  16. * accompanied by their corresponding landmarks location in separated files.
  17. * example of contents for images_train.txt:
  18. * ../trainset/image_0001.png
  19. * ../trainset/image_0002.png
  20. * example of contents for points_train.txt:
  21. * ../trainset/image_0001.pts
  22. * ../trainset/image_0002.pts
  23. * where the image_xxxx.pts contains the position of each face landmark.
  24. * example of the contents:
  25. * version: 1
  26. * n_points: 68
  27. * {
  28. * 115.167660 220.807529
  29. * 116.164839 245.721357
  30. * 120.208690 270.389841
  31. * ...
  32. * }
  33. * example of the dataset is available at https://ibug.doc.ic.ac.uk/download/annotations/ibug.zip
  34. *--------------------------------------------------*/
  35. #include <stdio.h>
  36. #include <fstream>
  37. #include <sstream>
  38. #include <iostream>
  39. #include "opencv2/core.hpp"
  40. #include "opencv2/highgui.hpp"
  41. #include "opencv2/imgproc.hpp"
  42. #include "opencv2/face.hpp"
  43. using namespace std;
  44. using namespace cv;
  45. using namespace cv::face;
  46. static bool myDetector( InputArray image, OutputArray roi, CascadeClassifier *face_detector);
  47. static bool parseArguments(int argc, char** argv, String & cascade,
  48. String & model, String & images, String & annotations, String & testImages
  49. );
  50. int main(int argc, char** argv)
  51. {
  52. String cascade_path,model_path,images_path, annotations_path, test_images_path;
  53. if(!parseArguments(argc, argv, cascade_path,model_path,images_path, annotations_path, test_images_path))
  54. return -1;
  55. /*create the facemark instance*/
  56. FacemarkLBF::Params params;
  57. params.model_filename = model_path;
  58. params.cascade_face = cascade_path;
  59. Ptr<FacemarkLBF> facemark = FacemarkLBF::create(params);
  60. CascadeClassifier face_cascade;
  61. face_cascade.load(params.cascade_face.c_str());
  62. facemark->setFaceDetector((FN_FaceDetector)myDetector, &face_cascade);
  63. /*Loads the dataset*/
  64. std::vector<String> images_train;
  65. std::vector<String> landmarks_train;
  66. loadDatasetList(images_path,annotations_path,images_train,landmarks_train);
  67. Mat image;
  68. std::vector<Point2f> facial_points;
  69. for(size_t i=0;i<images_train.size();i++){
  70. printf("%i/%i :: %s\n", (int)(i+1), (int)images_train.size(),images_train[i].c_str());
  71. image = imread(images_train[i].c_str());
  72. loadFacePoints(landmarks_train[i],facial_points);
  73. facemark->addTrainingSample(image, facial_points);
  74. }
  75. /*train the Algorithm*/
  76. facemark->training();
  77. /*test using some images*/
  78. String testFiles(images_path), testPts(annotations_path);
  79. if(!test_images_path.empty()){
  80. testFiles = test_images_path;
  81. testPts = test_images_path; //unused
  82. }
  83. std::vector<String> images;
  84. std::vector<String> facePoints;
  85. loadDatasetList(testFiles, testPts, images, facePoints);
  86. std::vector<Rect> rects;
  87. CascadeClassifier cc(params.cascade_face.c_str());
  88. for(size_t i=0;i<images.size();i++){
  89. std::vector<std::vector<Point2f> > landmarks;
  90. cout<<images[i];
  91. Mat img = imread(images[i]);
  92. facemark->getFaces(img, rects);
  93. facemark->fit(img, rects, landmarks);
  94. for(size_t j=0;j<rects.size();j++){
  95. drawFacemarks(img, landmarks[j], Scalar(0,0,255));
  96. rectangle(img, rects[j], Scalar(255,0,255));
  97. }
  98. if(rects.size()>0){
  99. cout<<endl;
  100. imshow("result", img);
  101. waitKey(0);
  102. }else{
  103. cout<<"face not found"<<endl;
  104. }
  105. }
  106. }
  107. bool myDetector(InputArray image, OutputArray faces, CascadeClassifier *face_cascade)
  108. {
  109. Mat gray;
  110. if (image.channels() > 1)
  111. cvtColor(image, gray, COLOR_BGR2GRAY);
  112. else
  113. gray = image.getMat().clone();
  114. equalizeHist(gray, gray);
  115. std::vector<Rect> faces_;
  116. face_cascade->detectMultiScale(gray, faces_, 1.4, 2, CASCADE_SCALE_IMAGE, Size(30, 30));
  117. Mat(faces_).copyTo(faces);
  118. return true;
  119. }
  120. bool parseArguments(int argc, char** argv,
  121. String & cascade,
  122. String & model,
  123. String & images,
  124. String & annotations,
  125. String & test_images
  126. ){
  127. const String keys =
  128. "{ @c cascade | | (required) path to the face cascade xml file fo the face detector }"
  129. "{ @i images | | (required) path of a text file contains the list of paths to all training images}"
  130. "{ @a annotations | | (required) Path of a text file contains the list of paths to all annotations files}"
  131. "{ @m model | | (required) path to save the trained model }"
  132. "{ t test-images | | Path of a text file contains the list of paths to the test images}"
  133. "{ help h usage ? | | facemark_demo_lbf -cascade -images -annotations -model [-t] \n"
  134. " example: facemark_demo_lbf ../face_cascade.xml ../images_train.txt ../points_train.txt ../lbf.model}"
  135. ;
  136. CommandLineParser parser(argc, argv,keys);
  137. parser.about("hello");
  138. if (parser.has("help")){
  139. parser.printMessage();
  140. return false;
  141. }
  142. cascade = String(parser.get<String>("cascade"));
  143. model = String(parser.get<string>("model"));
  144. images = String(parser.get<string>("images"));
  145. annotations = String(parser.get<string>("annotations"));
  146. test_images = String(parser.get<string>("t"));
  147. cout<<"cascade : "<<cascade.c_str()<<endl;
  148. cout<<"model : "<<model.c_str()<<endl;
  149. cout<<"images : "<<images.c_str()<<endl;
  150. cout<<"annotations : "<<annotations.c_str()<<endl;
  151. if(cascade.empty() || model.empty() || images.empty() || annotations.empty()){
  152. std::cerr << "one or more required arguments are not found" << '\n';
  153. parser.printMessage();
  154. return false;
  155. }
  156. return true;
  157. }