john987

livefacedetect

Apr 29th, 2011
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.62 KB | None | 0 0
  1. #include <opencv2/objdetect/objdetect.hpp>
  2. #include <opencv2/highgui/highgui.hpp>
  3. #include <opencv2/imgproc/imgproc.hpp>
  4.  
  5. #include <iostream>
  6. #include <stdio.h>
  7.  
  8. using namespace std;
  9. using namespace cv;
  10.  
  11. void help()
  12. {
  13. cout << "\nThis program demonstrates the haar cascade recognizer\n"
  14. "this classifier can recognize many ~rigid objects, it's most known use is for faces.\n"
  15. "Usage:\n"
  16. "./facedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]\n"
  17. " [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]\n"
  18. " [--scale=<image scale greater or equal to 1, try 1.3 for example>\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.xml\" --scale=1.3 \n"
  22. "Hit any key to quit.\n"
  23. "Using OpenCV version %s\n" << CV_VERSION << "\n"
  24. << endl;
  25. }
  26.  
  27. void detectAndDraw( Mat& img,
  28. CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
  29. double scale);
  30.  
  31. String cascadeName =
  32. "../../data/haarcascades/haarcascade_frontalface_alt.xml";
  33. String nestedCascadeName =
  34. "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
  35.  
  36. int main( int argc, const char** argv )
  37. {
  38. CvCapture* capture = 0;
  39. Mat frame, frameCopy, image;
  40. const String scaleOpt = "--scale=";
  41. size_t scaleOptLen = scaleOpt.length();
  42. const String cascadeOpt = "--cascade=";
  43. size_t cascadeOptLen = cascadeOpt.length();
  44. const String nestedCascadeOpt = "--nested-cascade";
  45. size_t nestedCascadeOptLen = nestedCascadeOpt.length();
  46. String inputName;
  47.  
  48. help();
  49. CascadeClassifier cascade, nestedCascade;
  50. double scale = 1;
  51.  
  52. for( int i = 1; i < argc; i++ )
  53. {
  54. cout << "Processing " << i << " " << argv[i] << endl;
  55. if( cascadeOpt.compare( 0, cascadeOptLen, argv[i], cascadeOptLen ) == 0 )
  56. {
  57. cascadeName.assign( argv[i] + cascadeOptLen );
  58. cout << " from which we have cascadeName= " << cascadeName << endl;
  59. }
  60. else if( nestedCascadeOpt.compare( 0, nestedCascadeOptLen, argv[i], nestedCascadeOptLen ) == 0 )
  61. {
  62. if( argv[i][nestedCascadeOpt.length()] == '=' )
  63. nestedCascadeName.assign( argv[i] + nestedCascadeOpt.length() + 1 );
  64. if( !nestedCascade.load( nestedCascadeName ) )
  65. cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
  66. }
  67. else if( scaleOpt.compare( 0, scaleOptLen, argv[i], scaleOptLen ) == 0 )
  68. {
  69. if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) || scale < 1 )
  70. scale = 1;
  71. cout << " from which we read scale = " << scale << endl;
  72. }
  73. else if( argv[i][0] == '-' )
  74. {
  75. cerr << "WARNING: Unknown option %s" << argv[i] << endl;
  76. }
  77. else
  78. inputName.assign( argv[i] );
  79. }
  80.  
  81. if( !cascade.load( cascadeName ) )
  82. {
  83. cerr << "ERROR: Could not load classifier cascade" << endl;
  84. cerr << "Usage: facedetect [--cascade=<cascade_path>]\n"
  85. " [--nested-cascade[=nested_cascade_path]]\n"
  86. " [--scale[=<image scale>\n"
  87. " [filename|camera_index]\n" << endl ;
  88. return -1;
  89. }
  90.  
  91. if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') )
  92. {
  93. capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' );
  94. int c = inputName.empty() ? 0 : inputName.c_str()[0] - '0' ;
  95. if(!capture) cout << "Capture from CAM " << c << " didn't work" << endl;
  96. }
  97. else if( inputName.size() )
  98. {
  99. image = imread( inputName, 1 );
  100. if( image.empty() )
  101. {
  102. capture = cvCaptureFromAVI( inputName.c_str() );
  103. if(!capture) cout << "Capture from AVI didn't work" << endl;
  104. }
  105. }
  106. else
  107. {
  108. image = imread( "lena.jpg", 1 );
  109. if(image.empty()) cout << "Couldn't read lena.jpg" << endl;
  110. }
  111.  
  112. cvNamedWindow( "result", 1 );
  113.  
  114. if( capture )
  115. {
  116. cout << "In capture ..." << endl;
  117. for(;;)
  118. {
  119. IplImage* iplImg = cvQueryFrame( capture );
  120. frame = iplImg;
  121. if( frame.empty() )
  122. break;
  123. if( iplImg->origin == IPL_ORIGIN_TL )
  124. frame.copyTo( frameCopy );
  125. else
  126. flip( frame, frameCopy, 0 );
  127.  
  128. detectAndDraw( frameCopy, cascade, nestedCascade, scale );
  129.  
  130. if( waitKey( 10 ) >= 0 )
  131. goto _cleanup_;
  132. }
  133.  
  134. waitKey(0);
  135. _cleanup_:
  136. cvReleaseCapture( &capture );
  137. }
  138. else
  139. {
  140. cout << "In image read" << endl;
  141. if( !image.empty() )
  142. {
  143. detectAndDraw( image, cascade, nestedCascade, scale );
  144. waitKey(0);
  145. }
  146. else if( !inputName.empty() )
  147. {
  148. /* assume it is a text file containing the
  149. list of the image filenames to be processed - one per line */
  150. FILE* f = fopen( inputName.c_str(), "rt" );
  151. if( f )
  152. {
  153. char buf[1000+1];
  154. while( fgets( buf, 1000, f ) )
  155. {
  156. int len = (int)strlen(buf), c;
  157. while( len > 0 && isspace(buf[len-1]) )
  158. len--;
  159. buf[len] = '\0';
  160. cout << "file " << buf << endl;
  161. image = imread( buf, 1 );
  162. if( !image.empty() )
  163. {
  164. detectAndDraw( image, cascade, nestedCascade, scale );
  165. c = waitKey(0);
  166. if( c == 27 || c == 'q' || c == 'Q' )
  167. break;
  168. }
  169. else
  170. {
  171. cerr << "Aw snap, couldn't read image " << buf << endl;
  172. }
  173. }
  174. fclose(f);
  175. }
  176. }
  177. }
  178.  
  179. cvDestroyWindow("result");
  180.  
  181. return 0;
  182. }
  183.  
  184. void detectAndDraw( Mat& img,
  185. CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
  186. double scale)
  187. {
  188. int i = 0;
  189. double t = 0;
  190. vector<Rect> faces;
  191. const static Scalar colors[] = { CV_RGB(0,0,255),
  192. CV_RGB(0,128,255),
  193. CV_RGB(0,255,255),
  194. CV_RGB(0,255,0),
  195. CV_RGB(255,128,0),
  196. CV_RGB(255,255,0),
  197. CV_RGB(255,0,0),
  198. CV_RGB(255,0,255)} ;
  199. Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );
  200.  
  201. cvtColor( img, gray, CV_BGR2GRAY );
  202. resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
  203. equalizeHist( smallImg, smallImg );
  204.  
  205. t = (double)cvGetTickCount();
  206. cascade.detectMultiScale( smallImg, faces,
  207. 1.1, 2, 0
  208. //|CV_HAAR_FIND_BIGGEST_OBJECT
  209. //|CV_HAAR_DO_ROUGH_SEARCH
  210. |CV_HAAR_SCALE_IMAGE
  211. ,
  212. Size(30, 30) );
  213. t = (double)cvGetTickCount() - t;
  214. printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );
  215. for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
  216. {
  217. Mat smallImgROI;
  218. vector<Rect> nestedObjects;
  219. Point center;
  220. Scalar color = colors[i%8];
  221. int radius;
  222. center.x = cvRound((r->x + r->width*0.5)*scale);
  223. center.y = cvRound((r->y + r->height*0.5)*scale);
  224. radius = cvRound((r->width + r->height)*0.25*scale);
  225. circle( img, center, radius, color, 3, 8, 0 );
  226. if( nestedCascade.empty() )
  227. continue;
  228. smallImgROI = smallImg(*r);
  229. nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
  230. 1.1, 2, 0
  231. //|CV_HAAR_FIND_BIGGEST_OBJECT
  232. //|CV_HAAR_DO_ROUGH_SEARCH
  233. //|CV_HAAR_DO_CANNY_PRUNING
  234. |CV_HAAR_SCALE_IMAGE
  235. ,
  236. Size(30, 30) );
  237. for( vector<Rect>::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ )
  238. {
  239. center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
  240. center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
  241. radius = cvRound((nr->width + nr->height)*0.25*scale);
  242. circle( img, center, radius, color, 3, 8, 0 );
  243. }
  244. }
  245. cv::imshow( "result", img );
  246. }
Add Comment
Please, Sign In to add comment