sampleDetectLandmarks.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #include "opencv2/face.hpp"
  2. #include "opencv2/videoio.hpp"
  3. #include "opencv2/highgui.hpp"
  4. #include "opencv2/imgcodecs.hpp"
  5. #include "opencv2/objdetect.hpp"
  6. #include "opencv2/imgproc.hpp"
  7. #include <iostream>
  8. #include <vector>
  9. #include <string>
  10. using namespace std;
  11. using namespace cv;
  12. using namespace cv::face;
  13. static bool myDetector(InputArray image, OutputArray faces, CascadeClassifier *face_cascade)
  14. {
  15. Mat gray;
  16. if (image.channels() > 1)
  17. cvtColor(image, gray, COLOR_BGR2GRAY);
  18. else
  19. gray = image.getMat().clone();
  20. equalizeHist(gray, gray);
  21. std::vector<Rect> faces_;
  22. face_cascade->detectMultiScale(gray, faces_, 1.4, 2, CASCADE_SCALE_IMAGE, Size(30, 30));
  23. Mat(faces_).copyTo(faces);
  24. return true;
  25. }
  26. int main(int argc,char** argv){
  27. //Give the path to the directory containing all the files containing data
  28. CommandLineParser parser(argc, argv,
  29. "{ help h usage ? | | give the following arguments in following format }"
  30. "{ model_filename f | | (required) path to binary file storing the trained model which is to be loaded [example - /data/file.dat]}"
  31. "{ image i | | (required) path to image in which face landmarks have to be detected.[example - /data/image.jpg] }"
  32. "{ face_cascade c | | Path to the face cascade xml file which you want to use as a detector}"
  33. );
  34. // Read in the input arguments
  35. if (parser.has("help")){
  36. parser.printMessage();
  37. cerr << "TIP: Use absolute paths to avoid any problems with the software!" << endl;
  38. return 0;
  39. }
  40. string filename(parser.get<string>("model_filename"));
  41. if (filename.empty()){
  42. parser.printMessage();
  43. cerr << "The name of the model file to be loaded for detecting landmarks is not found" << endl;
  44. return -1;
  45. }
  46. string image(parser.get<string>("image"));
  47. if (image.empty()){
  48. parser.printMessage();
  49. cerr << "The name of the image file in which landmarks have to be detected is not found" << endl;
  50. return -1;
  51. }
  52. string cascade_name(parser.get<string>("face_cascade"));
  53. if (cascade_name.empty()){
  54. parser.printMessage();
  55. cerr << "The name of the cascade classifier to be loaded to detect faces is not found" << endl;
  56. return -1;
  57. }
  58. Mat img = imread(image);
  59. //pass the face cascade xml file which you want to pass as a detector
  60. CascadeClassifier face_cascade;
  61. face_cascade.load(cascade_name);
  62. FacemarkKazemi::Params params;
  63. Ptr<FacemarkKazemi> facemark = FacemarkKazemi::create(params);
  64. facemark->setFaceDetector((FN_FaceDetector)myDetector, &face_cascade);
  65. facemark->loadModel(filename);
  66. cout<<"Loaded model"<<endl;
  67. vector<Rect> faces;
  68. resize(img,img,Size(460,460), 0, 0, INTER_LINEAR_EXACT);
  69. facemark->getFaces(img,faces);
  70. vector< vector<Point2f> > shapes;
  71. // Check if faces detected or not
  72. // Helps in proper exception handling when writing images to the directories.
  73. if(faces.size() != 0) {
  74. if(facemark->fit(img,faces,shapes))
  75. {
  76. for( size_t i = 0; i < faces.size(); i++ )
  77. {
  78. cv::rectangle(img,faces[i],Scalar( 255, 0, 0 ));
  79. }
  80. for(unsigned long i=0;i<faces.size();i++){
  81. for(unsigned long k=0;k<shapes[i].size();k++)
  82. cv::circle(img,shapes[i][k],5,cv::Scalar(0,0,255),FILLED);
  83. }
  84. namedWindow("Detected_shape");
  85. imshow("Detected_shape",img);
  86. waitKey(0);
  87. }
  88. } else {
  89. cout << "Faces not detected." << endl;
  90. }
  91. return 0;
  92. }