You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
3.9 KiB
110 lines
3.9 KiB
#include "opencv2/face.hpp" |
|
#include "opencv2/highgui.hpp" |
|
#include "opencv2/imgcodecs.hpp" |
|
#include "opencv2/imgproc.hpp" |
|
#include "opencv2/videoio.hpp" |
|
#include "opencv2/objdetect.hpp" |
|
#include <iostream> |
|
#include <vector> |
|
#include <string> |
|
|
|
using namespace std; |
|
using namespace cv; |
|
using namespace cv::face; |
|
|
|
static bool myDetector(InputArray image, OutputArray faces, CascadeClassifier *face_cascade) |
|
{ |
|
Mat gray; |
|
|
|
if (image.channels() > 1) |
|
cvtColor(image, gray, COLOR_BGR2GRAY); |
|
else |
|
gray = image.getMat().clone(); |
|
|
|
equalizeHist(gray, gray); |
|
|
|
std::vector<Rect> faces_; |
|
face_cascade->detectMultiScale(gray, faces_, 1.4, 2, CASCADE_SCALE_IMAGE, Size(30, 30)); |
|
Mat(faces_).copyTo(faces); |
|
return true; |
|
} |
|
|
|
int main(int argc,char** argv){ |
|
//Give the path to the directory containing all the files containing data |
|
CommandLineParser parser(argc, argv, |
|
"{ help h usage ? | | give the following arguments in following format }" |
|
"{ model_filename f | | (required) path to binary file storing the trained model which is to be loaded [example - /data/file.dat]}" |
|
"{ video v | | (required) path to video in which face landmarks have to be detected.[example - /data/video.avi] }" |
|
"{ face_cascade c | | Path to the face cascade xml file which you want to use as a detector}" |
|
); |
|
// Read in the input arguments |
|
if (parser.has("help")){ |
|
parser.printMessage(); |
|
cerr << "TIP: Use absolute paths to avoid any problems with the software!" << endl; |
|
return 0; |
|
} |
|
string filename(parser.get<string>("model_filename")); |
|
if (filename.empty()){ |
|
parser.printMessage(); |
|
cerr << "The name of the model file to be loaded for detecting landmarks is not found" << endl; |
|
return -1; |
|
} |
|
string video(parser.get<string>("video")); |
|
if (video.empty()){ |
|
parser.printMessage(); |
|
cerr << "The name of the video file in which landmarks have to be detected is not found" << endl; |
|
return -1; |
|
} |
|
string cascade_name(parser.get<string>("face_cascade")); |
|
if (cascade_name.empty()){ |
|
parser.printMessage(); |
|
cerr << "The name of the cascade classifier to be loaded to detect faces is not found" << endl; |
|
return -1; |
|
} |
|
VideoCapture cap(video); |
|
if(!cap.isOpened()){ |
|
cerr<<"Video cannot be loaded. Give correct path"<<endl; |
|
return -1; |
|
} |
|
//pass the face cascade xml file which you want to pass as a detector |
|
CascadeClassifier face_cascade; |
|
face_cascade.load(cascade_name); |
|
FacemarkKazemi::Params params; |
|
Ptr<FacemarkKazemi> facemark = FacemarkKazemi::create(params); |
|
facemark->setFaceDetector((FN_FaceDetector)myDetector, &face_cascade); |
|
facemark->loadModel(filename); |
|
cout<<"Loaded model"<<endl; |
|
//vector to store the faces detected in the image |
|
vector<Rect> faces; |
|
vector< vector<Point2f> > shapes; |
|
Mat img; |
|
while(1){ |
|
faces.clear(); |
|
shapes.clear(); |
|
cap>>img; |
|
//Detect faces in the current image |
|
resize(img,img,Size(600,600), 0, 0, INTER_LINEAR_EXACT); |
|
facemark->getFaces(img,faces); |
|
if(faces.size()==0){ |
|
cout<<"No faces found in this frame"<<endl; |
|
} |
|
else{ |
|
for( size_t i = 0; i < faces.size(); i++ ) |
|
{ |
|
cv::rectangle(img,faces[i],Scalar( 255, 0, 0 )); |
|
} |
|
//vector to store the landmarks of all the faces in the image |
|
if(facemark->fit(img,faces,shapes)) |
|
{ |
|
for(unsigned long i=0;i<faces.size();i++){ |
|
for(unsigned long k=0;k<shapes[i].size();k++) |
|
cv::circle(img,shapes[i][k],3,cv::Scalar(0,0,255),FILLED); |
|
} |
|
} |
|
} |
|
namedWindow("Detected_shape"); |
|
imshow("Detected_shape",img); |
|
if(waitKey(1) >= 0) break; |
|
} |
|
return 0; |
|
} |