sample_train_landmark_detector2.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*----------------------------------------------
  2. * the user should provide the list of training images_train,
  3. * accompanied by their corresponding landmarks location in separated files.
  4. * example of contents for images.txt:
  5. * ../trainset/image_0001.png
  6. * ../trainset/image_0002.png
  7. * example of contents for annotation.txt:
  8. * ../trainset/image_0001.pts
  9. * ../trainset/image_0002.pts
  10. * where the image_xxxx.pts contains the position of each face landmark.
  11. * example of the contents:
  12. * version: 1
  13. * n_points: 68
  14. * {
  15. * 115.167660 220.807529
  16. * 116.164839 245.721357
  17. * 120.208690 270.389841
  18. * ...
  19. * }
  20. * example of the dataset is available at https://ibug.doc.ic.ac.uk/resources/facial-point-annotations/
  21. *--------------------------------------------------*/
  22. #include "opencv2/face.hpp"
  23. #include "opencv2/highgui.hpp"
  24. #include "opencv2/imgproc.hpp"
  25. #include "opencv2/imgcodecs.hpp"
  26. #include "opencv2/objdetect.hpp"
  27. #include <iostream>
  28. #include <vector>
  29. #include <string>
  30. using namespace std;
  31. using namespace cv;
  32. using namespace cv::face;
  33. static bool myDetector(InputArray image, OutputArray faces, CascadeClassifier *face_cascade)
  34. {
  35. Mat gray;
  36. if (image.channels() > 1)
  37. cvtColor(image, gray, COLOR_BGR2GRAY);
  38. else
  39. gray = image.getMat().clone();
  40. equalizeHist(gray, gray);
  41. std::vector<Rect> faces_;
  42. face_cascade->detectMultiScale(gray, faces_, 1.4, 2, CASCADE_SCALE_IMAGE, Size(30, 30));
  43. Mat(faces_).copyTo(faces);
  44. return true;
  45. }
  46. int main(int argc,char** argv){
  47. //Give the path to the directory containing all the files containing data
  48. CommandLineParser parser(argc, argv,
  49. "{ help h usage ? | | give the following arguments in following format }"
  50. "{ images i | | (required) path to images txt file [example - /data/images.txt] }"
  51. "{ annotations a |. | (required) path to annotations txt file [example - /data/annotations.txt] }"
  52. "{ config c | | (required) path to configuration xml file containing parameters for training.[example - /data/config.xml] }"
  53. "{ model m | | (required) path to file containing trained model for face landmark detection[example - /data/model.dat] }"
  54. "{ width w | 460 | The width which you want all images to get to scale the annotations. large images are slow to process [default = 460] }"
  55. "{ height h | 460 | The height which you want all images to get to scale the annotations. large images are slow to process [default = 460] }"
  56. "{ face_cascade f | | Path to the face cascade xml file which you want to use as a detector}"
  57. );
  58. // Read in the input arguments
  59. if (parser.has("help")){
  60. parser.printMessage();
  61. cerr << "TIP: Use absolute paths to avoid any problems with the software!" << endl;
  62. return 0;
  63. }
  64. string annotations(parser.get<string>("annotations"));
  65. string imagesList(parser.get<string>("images"));
  66. //default initialisation
  67. Size scale(460,460);
  68. scale = Size(parser.get<int>("width"),parser.get<int>("height"));
  69. if (annotations.empty()){
  70. parser.printMessage();
  71. cerr << "Name for annotations file not found. Aborting...." << endl;
  72. return -1;
  73. }
  74. if (imagesList.empty()){
  75. parser.printMessage();
  76. cerr << "Name for file containing image list not found. Aborting....." << endl;
  77. return -1;
  78. }
  79. string configfile_name(parser.get<string>("config"));
  80. if (configfile_name.empty()){
  81. parser.printMessage();
  82. cerr << "No configuration file name found which contains the parameters for training" << endl;
  83. return -1;
  84. }
  85. string modelfile_name(parser.get<string>("model"));
  86. if (modelfile_name.empty()){
  87. parser.printMessage();
  88. cerr << "No name for the model_file found in which the trained model has to be saved" << endl;
  89. return -1;
  90. }
  91. string cascade_name(parser.get<string>("face_cascade"));
  92. if (cascade_name.empty()){
  93. parser.printMessage();
  94. cerr << "The name of the cascade classifier to be loaded to detect faces is not found" << endl;
  95. return -1;
  96. }
  97. //create a pointer to call the base class
  98. //pass the face cascade xml file which you want to pass as a detector
  99. CascadeClassifier face_cascade;
  100. face_cascade.load(cascade_name);
  101. FacemarkKazemi::Params params;
  102. params.configfile = configfile_name;
  103. Ptr<FacemarkKazemi> facemark = FacemarkKazemi::create(params);
  104. facemark->setFaceDetector((FN_FaceDetector)myDetector, &face_cascade);
  105. std::vector<String> images;
  106. std::vector<std::vector<Point2f> > facePoints;
  107. loadTrainingData(imagesList, annotations, images, facePoints, 0.0);
  108. //gets landmarks and corresponding image names in both the vectors
  109. vector<Mat> Trainimages;
  110. std::vector<std::vector<Point2f> > Trainlandmarks;
  111. //vector to store images
  112. Mat src;
  113. for(unsigned long i=0;i<images.size();i++){
  114. src = imread(images[i]);
  115. if(src.empty()){
  116. cout<<images[i]<<endl;
  117. cerr<<string("Image not found\n.Aborting...")<<endl;
  118. continue;
  119. }
  120. Trainimages.push_back(src);
  121. Trainlandmarks.push_back(facePoints[i]);
  122. }
  123. cout<<"Got data"<<endl;
  124. facemark->training(Trainimages,Trainlandmarks,configfile_name,scale,modelfile_name);
  125. cout<<"Training complete"<<endl;
  126. return 0;
  127. }