基于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 << "\nThis program demonstrates the cascade recognizer. Now you can use Haar or LBP features.\n"
 12             "This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained.\n"
 13             "It's most known use is for faces.\n"
 14             "Usage:\n"
 15             "./facedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]\n"
 16                "   [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]\n"
 17                "   [--scale=<image scale greater or equal to 1, try 1.3 for example>]\n"
 18                "   [--try-flip]\n"
 19                "   [filename|camera_index]\n\n"
 20             "see facedetect.cmd for one call:\n"
 21             "./facedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml\" --scale=1.3\n\n"
 22             "During execution:\n\tHit any key to quit.\n"
 23             "\tUsing OpenCV version " << CV_VERSION << "\n" << 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] = '\0';
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\n", 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版本基本相同,未出现错误;

 

posted on 2016-06-02 11:03  tanfy  阅读(1149)  评论(0编辑  收藏  举报

导航