/*!* file Capture.cpp * * author ranjiewen * date 十一月 2016 * * http://www.cnblogs.com/tanfy/p/5552270.html 解析opencv自带人脸识别源码(……/opencv-3.1.0/samples/cpp/facedetect.cpp) */ #include "opencv2/objdetect.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include <iostream> using namespace std; using namespace cv; static void help() { cout << " This program demonstrates the cascade recognizer. Now you can use Haar or LBP features. " "This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained. " "It's most known use is for faces. " "Usage: " "./facedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face] " " [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]] " " [--scale=<image scale greater or equal to 1, try 1.3 for example>] " " [--try-flip] " " [filename|camera_index] " "see facedetect.cmd for one call: " "./facedetect --cascade="../../data/haarcascades/haarcascade_frontalface_alt.xml" --nested-cascade="../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml" --scale=1.3 " "During execution: Hit any key to quit. " " Using OpenCV version " << CV_VERSION << " " << endl; } void detectAndDraw(Mat& img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale, bool tryflip); string cascadeName; string nestedCascadeName; int main(int argc, const char** argv) { VideoCapture capture; Mat frame, image; string inputName; bool tryflip; // CascadeClassifier是Opencv中做人脸检测的时候的一个级联分类器,现在有两种选择:一是使用老版本的CvHaarClassifierCascade函数,一是使用新版本的CascadeClassifier类。老版本的分类器只支持类Haar特征,而新版本的分类器既可以使用Haar,也可以使用LBP特征。 CascadeClassifier cascade, nestedCascade; double scale; cv::CommandLineParser parser(argc, argv, "{help h||}" "{cascade|D:/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml|}" //默认路径实在安装路径下sample,修改了路径,以便加载load成功 "{nested-cascade|D:/opencv/sources/data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|}" //修改路径 "{scale|1|}{try-flip||}{@filename||}" //文件为空时,设置摄像头,实时检测人脸 ); if (parser.has("help")) { help(); return 0; } cascadeName = parser.get<string>("cascade"); nestedCascadeName = parser.get<string>("nested-cascade"); scale = parser.get<double>("scale"); if (scale < 1) scale = 1; tryflip = parser.has("try-flip"); inputName = parser.get<string>("@filename"); std::cout << inputName << std::endl; // test if (!parser.check()) { parser.printErrors(); return 0; } // 加载模型 if (!nestedCascade.load(nestedCascadeName)) cerr << "WARNING: Could not load classifier cascade for nested objects" << endl; if (!cascade.load(cascadeName)) { cerr << "ERROR: Could not load classifier cascade" << endl; help(); return -1; } // 读取摄像头 // isdigit检测字符是否为阿拉伯数字 if (inputName.empty() || (isdigit(inputName[0]) && inputName.size() == 1)) { int c = inputName.empty() ? 0 : inputName[0] - '0'; // 此处若系统在虚拟机上,需在虚拟机中设置接管摄像头:虚拟机(M)-> 可移动设备 -> 摄像头名称 -> 连接(断开与主机连接) if (!capture.open(c)) cout << "Capture from camera #" << c << " didn't work" << endl; else { capture.set(CV_CAP_PROP_FRAME_WIDTH, 640); capture.set(CV_CAP_PROP_FRAME_HEIGHT, 480); } } else if (inputName.size()) { image = imread(inputName, 1); if (image.empty()) { if (!capture.open(inputName)) cout << "Could not read " << inputName << endl; } } else { image = imread("../data/lena.jpg", 1); if (image.empty()) cout << "Couldn't read ../data/lena.jpg" << endl; } if (capture.isOpened()) { cout << "Video capturing has been started ..." << endl; for (;;) { std::cout << "capturing..." << std::endl; // test capture >> frame; if (frame.empty()) break; Mat frame1 = frame.clone(); std::cout << "Start to detect..." << std::endl; // test detectAndDraw(frame1, cascade, nestedCascade, scale, tryflip); int c = waitKey(10); if (c == 27 || c == 'q' || c == 'Q') break; } } else { cout << "Detecting face(s) in " << inputName << endl; if (!image.empty()) { detectAndDraw(image, cascade, nestedCascade, scale, tryflip); waitKey(0); } else if (!inputName.empty()) { /* assume it is a text file containing the list of the image filenames to be processed - one per line */ FILE* f = fopen(inputName.c_str(), "rt"); if (f) { char buf[1000 + 1]; while (fgets(buf, 1000, f)) { int len = (int)strlen(buf), c; while (len > 0 && isspace(buf[len - 1])) len--; buf[len] = '