基于opencv的人脸识别程序

1. 解析opencv自带人脸识别源码(……/opencv-3.1.0/samples/cpp/facedetect.cpp)

@ 操作系统:Ubuntu 15.04

OpenCV版本:3.1.0

  1 #include "opencv2/objdetect.hpp"
  2 #include "opencv2/highgui.hpp"
  3 #include "opencv2/imgproc.hpp"
  4 #include <iostream>
  5 
  6 using namespace std;
  7 using namespace cv;
  8 
  9 static void help()
 10 {
 11     cout << "
This program demonstrates the cascade recognizer. Now you can use Haar or LBP features.
"
 12             "This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained.
"
 13             "It's most known use is for faces.
"
 14             "Usage:
"
 15             "./facedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]
"
 16                "   [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]
"
 17                "   [--scale=<image scale greater or equal to 1, try 1.3 for example>]
"
 18                "   [--try-flip]
"
 19                "   [filename|camera_index]

"
 20             "see facedetect.cmd for one call:
"
 21             "./facedetect --cascade="../../data/haarcascades/haarcascade_frontalface_alt.xml" --nested-cascade="../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml" --scale=1.3

"
 22             "During execution:
	Hit any key to quit.
"
 23             "	Using OpenCV version " << CV_VERSION << "
" << endl;
 24 }
 25 
 26 void detectAndDraw( Mat& img, CascadeClassifier& cascade,
 27                     CascadeClassifier& nestedCascade,
 28                     double scale, bool tryflip );
 29 
 30 string cascadeName;
 31 string nestedCascadeName;
 32 
 33 int main( int argc, const char** argv )
 34 {
 35     VideoCapture capture;
 36     Mat frame, image;
 37     string inputName;
 38     bool tryflip;
 39 
 40     // CascadeClassifier是Opencv中做人脸检测的时候的一个级联分类器,现在有两种选择:一是使用老版本的CvHaarClassifierCascade函数,一是使用新版本的CascadeClassifier类。老版本的分类器只支持类Haar特征,而新版本的分类器既可以使用Haar,也可以使用LBP特征。
 41     CascadeClassifier cascade, nestedCascade;
 42     double scale;
 43 
 44     cv::CommandLineParser parser(argc, argv,
 45         "{help h||}"
 46         "{cascade|../../data/haarcascades/haarcascade_frontalface_alt.xml|}"
 47         "{nested-cascade|../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|}"
 48         "{scale|1|}{try-flip||}{@filename||}"
 49     );
 50     if (parser.has("help"))
 51     {
 52         help();
 53         return 0;
 54     }
 55 
 56     // 问题1:不用定义返回类型?
 57     cascadeName = parser.get<string>("cascade");
 58     nestedCascadeName = parser.get<string>("nested-cascade");
 59     scale = parser.get<double>("scale");
 60     if (scale < 1)
 61         scale = 1;
 62     tryflip = parser.has("try-flip");
 63     inputName = parser.get<string>("@filename");
 64     std::cout << inputName << std::endl;  // test
 65     if (!parser.check())
 66     {
 67         parser.printErrors();
 68         return 0;
 69     }
 70   
 71     // 加载模型
 72     if ( !nestedCascade.load( nestedCascadeName ) )
 73         cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
 74     if( !cascade.load( cascadeName ) )
 75     {
 76         cerr << "ERROR: Could not load classifier cascade" << endl;
 77         help();
 78         return -1;
 79     }
 80     // 读取摄像头
 81     // isdigit检测字符是否为阿拉伯数字 
 82     if( inputName.empty() || (isdigit(inputName[0]) && inputName.size() == 1) )
 83     {
 84         int c = inputName.empty() ? 0 : inputName[0] - '0';
 85         // 此处若系统在虚拟机上,需在虚拟机中设置接管摄像头:虚拟机(M)-> 可移动设备 -> 摄像头名称 -> 连接(断开与主机连接)
 86         if(!capture.open(c))
 87             cout << "Capture from camera #" <<  c << " didn't work" << endl;
 88         else {
 89           capture.set(CV_CAP_PROP_FRAME_WIDTH, 640);
 90           capture.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
 91         } 
 92     } 
 93     else if( inputName.size() )
 94     {
 95         image = imread( inputName, 1 );
 96         if( image.empty() )
 97         {
 98             if(!capture.open( inputName ))
 99                 cout << "Could not read " << inputName << endl;
100         }
101     }
102     else
103     {
104         image = imread( "../data/lena.jpg", 1 );
105         if(image.empty()) cout << "Couldn't read ../data/lena.jpg" << endl;
106     }
107 
108     if( capture.isOpened() )
109     {
110         cout << "Video capturing has been started ..." << endl;
111 
112 
113         for(;;)
114         {
115             std::cout << "capturing..." << std::endl;  // test
116             capture >> frame;
117             if( frame.empty() )
118                 break;
119 
120             Mat frame1 = frame.clone();
121             std::cout << "Start to detect..." << std::endl;  // test
122             detectAndDraw( frame1, cascade, nestedCascade, scale, tryflip );
123 
124             int c = waitKey(10);
125             if( c == 27 || c == 'q' || c == 'Q' )
126                 break;
127         }
128     }
129     else
130     {
131         cout << "Detecting face(s) in " << inputName << endl;
132         if( !image.empty() )
133         {
134             detectAndDraw( image, cascade, nestedCascade, scale, tryflip );
135             waitKey(0);
136         }
137         else if( !inputName.empty() )
138         {
139             /* assume it is a text file containing the
140             list of the image filenames to be processed - one per line */
141             FILE* f = fopen( inputName.c_str(), "rt" );
142             if( f )
143             {
144                 char buf[1000+1];
145                 while( fgets( buf, 1000, f ) )
146                 {
147                     int len = (int)strlen(buf), c;
148                     while( len > 0 && isspace(buf[len-1]) )
149                         len--;
150                     buf[len] = '';
151                     cout << "file " << buf << endl;
152                     image = imread( buf, 1 );
153                     if( !image.empty() )
154                     {
155                         detectAndDraw( image, cascade, nestedCascade, scale, tryflip );
156                         c = waitKey(0);
157                         if( c == 27 || c == 'q' || c == 'Q' )
158                             break;
159                     }
160                     else
161                     {
162                         cerr << "Aw snap, couldn't read image " << buf << endl;
163                     }
164                 }
165                 fclose(f);
166             }
167         }
168     }
169 
170     return 0;
171 }
172 
173 void detectAndDraw( Mat& img, CascadeClassifier& cascade,
174                     CascadeClassifier& nestedCascade,
175                     double scale, bool tryflip )
176 {
177     double t = 0;
178     vector<Rect> faces, faces2;
179     const static Scalar colors[] =
180     {
181         Scalar(255,0,0),
182         Scalar(255,128,0),
183         Scalar(255,255,0),
184         Scalar(0,255,0),
185         Scalar(0,128,255),
186         Scalar(0,255,255),
187         Scalar(0,0,255),
188         Scalar(255,0,255)
189     };
190     Mat gray, smallImg;
191 
192     cvtColor( img, gray, COLOR_BGR2GRAY );
193     double fx = 1 / scale;
194     resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR );
195     equalizeHist( smallImg, smallImg );
196 
197     t = (double)cvGetTickCount();
198     cascade.detectMultiScale( smallImg, faces,
199         1.1, 2, 0
200         //|CASCADE_FIND_BIGGEST_OBJECT
201         //|CASCADE_DO_ROUGH_SEARCH
202         |CASCADE_SCALE_IMAGE,
203         Size(30, 30) );
204     if( tryflip )
205     {
206         flip(smallImg, smallImg, 1);
207         cascade.detectMultiScale( smallImg, faces2,
208                                  1.1, 2, 0
209                                  //|CASCADE_FIND_BIGGEST_OBJECT
210                                  //|CASCADE_DO_ROUGH_SEARCH
211                                  |CASCADE_SCALE_IMAGE,
212                                  Size(30, 30) );
213         for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); r++ )
214         {
215             faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));
216         }
217     }
218     t = (double)cvGetTickCount() - t;
219     printf( "detection time = %g ms
", t/((double)cvGetTickFrequency()*1000.) );
220     for ( size_t i = 0; i < faces.size(); i++ )
221     {
222         Rect r = faces[i];
223         Mat smallImgROI;
224         vector<Rect> nestedObjects;
225         Point center;
226         Scalar color = colors[i%8];
227         int radius;
228 
229         double aspect_ratio = (double)r.width/r.height;
230         if( 0.75 < aspect_ratio && aspect_ratio < 1.3 )
231         {
232             center.x = cvRound((r.x + r.width*0.5)*scale);
233             center.y = cvRound((r.y + r.height*0.5)*scale);
234             radius = cvRound((r.width + r.height)*0.25*scale);
235             circle( img, center, radius, color, 3, 8, 0 );
236         }
237         else
238             rectangle( img, cvPoint(cvRound(r.x*scale), cvRound(r.y*scale)),
239                        cvPoint(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)),
240                        color, 3, 8, 0);
241         if( nestedCascade.empty() )
242             continue;
243         smallImgROI = smallImg( r );
244         nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
245             1.1, 2, 0
246             //|CASCADE_FIND_BIGGEST_OBJECT
247             //|CASCADE_DO_ROUGH_SEARCH
248             //|CASCADE_DO_CANNY_PRUNING
249             |CASCADE_SCALE_IMAGE,
250             Size(30, 30) );
251         for ( size_t j = 0; j < nestedObjects.size(); j++ )
252         {
253             Rect nr = nestedObjects[j];
254             center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale);
255             center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale);
256             radius = cvRound((nr.width + nr.height)*0.25*scale);
257             circle( img, center, radius, color, 3, 8, 0 );
258         }
259     }
260     imshow( "result", img );
261 }
View Code

问题未解决:

运行到capture>>frame;时出现select timeout的错误;

@ 操作系统:windows 10

OpenCV版本:3.1.0

代码与Linux版本基本相同,未出现错误;

原文地址:https://www.cnblogs.com/tanfy/p/5552270.html