python使用opencv进行人脸识别

环境

ubuntu 12.04 LTS
python 2.7.3
opencv 2.3.1-7

安装依赖
sudo apt-get install libopencv-*
sudo apt-get install python-opencv
sudo apt-get install python-numpy
示例代码

  1. #!/usr/bin/env python
  2. #coding=utf-8
  3. import os
  4. from PIL import Image, ImageDraw
  5. import cv
  6. def detect_object(image):
  7. '''检测图片,获取人脸在图片中的坐标'''
  8. grayscale = cv.CreateImage((image.width, image.height), 8, 1)
  9. cv.CvtColor(image, grayscale, cv.CV_BGR2GRAY)
  10. cascade = cv.Load("/usr/share/opencv/haarcascades/haarcascade_frontalface_alt_tree.xml")
  11. rect = cv.HaarDetectObjects(grayscale, cascade, cv.CreateMemStorage(), 1.1, 2,
  12. cv.CV_HAAR_DO_CANNY_PRUNING, (20,20))
  13. result = []
  14. for r in rect:
  15. result.append((r[0][0], r[0][1], r[0][0]+r[0][2], r[0][1]+r[0][3]))
  16. return result
  17. def process(infile):
  18. '''在原图上框出头像并且截取每个头像到单独文件夹'''
  19. image = cv.LoadImage(infile);
  20. if image:
  21. faces = detect_object(image)
  22. im = Image.open(infile)
  23. path = os.path.abspath(infile)
  24. save_path = os.path.splitext(path)[0]+"_face"
  25. try:
  26. os.mkdir(save_path)
  27. except:
  28. pass
  29. if faces:
  30. draw = ImageDraw.Draw(im)
  31. count = 0
  32. for f in faces:
  33. count += 1
  34. draw.rectangle(f, outline=(255, 0, 0))
  35. a = im.crop(f)
  36. file_name = os.path.join(save_path,str(count)+".jpg")
  37. # print file_name
  38. a.save(file_name)
  39. drow_save_path = os.path.join(save_path,"out.jpg")
  40. im.save(drow_save_path, "JPEG", quality=80)
  41. else:
  42. print "Error: cannot detect faces on %s" % infile
  43. if __name__ == "__main__":
  44. process("./opencv_in.jpg")

转换效果

原图:

转换后

使用感受

对于大部分图像来说,只要是头像是正面的,没有被阻挡,识别基本没问题,准确性还是很高的。

识别效率有点低,有时候一张图片能处理七八秒才能处理完,当然这个和机器配置有关。 如果想加速的话可以使用C语言重写,经测试,C语言版的所花时间大约是python的一半

另外,官方提供了几个库可一选择,这里使用的是haarcascade_frontalface_alt_tree.xml, 除此之外, /usr/share/opencv/haarcascades/文件夹下还有几个库:
~~/usr/share/opencv/haarcascades>> ll -h
总用量 19M
drwxr-xr-x 2 root root 4.0K 3月 22 17:14 ./
drwxr-xr-x 4 root root 4.0K 3月 22 17:14 ../
-rw-r—r— 1 root root 1.1M 4月 28 2011 haarcascade_eye_tree_eyeglasses.xml
-rw-r—r— 1 root root 495K 4月 28 2011 haarcascade_eye.xml
-rw-r—r— 1 root root 818K 4月 28 2011 haarcascade_frontalface_alt2.xml
-rw-r—r— 1 root root 3.5M 4月 28 2011 haarcascade_frontalface_alt_tree.xml
-rw-r—r— 1 root root 899K 4月 28 2011 haarcascade_frontalface_alt.xml
-rw-r—r— 1 root root 1.2M 4月 28 2011 haarcascade_frontalface_default.xml
-rw-r—r— 1 root root 622K 4月 28 2011 haarcascade_fullbody.xml
-rw-r—r— 1 root root 316K 4月 28 2011 haarcascade_lefteye_2splits.xml
-rw-r—r— 1 root root 520K 4月 28 2011 haarcascade_lowerbody.xml
-rw-r—r— 1 root root 350K 4月 28 2011 haarcascade_mcs_eyepair_big.xml
-rw-r—r— 1 root root 401K 4月 28 2011 haarcascade_mcs_eyepair_small.xml
-rw-r—r— 1 root root 306K 8月 2 2011 haarcascade_mcs_leftear.xml
-rw-r—r— 1 root root 760K 4月 28 2011 haarcascade_mcs_lefteye.xml
-rw-r—r— 1 root root 703K 4月 28 2011 haarcascade_mcs_mouth.xml
-rw-r—r— 1 root root 1.6M 4月 28 2011 haarcascade_mcs_nose.xml
-rw-r—r— 1 root root 318K 8月 2 2011 haarcascade_mcs_rightear.xml
-rw-r—r— 1 root root 1.4M 4月 28 2011 haarcascade_mcs_righteye.xml
-rw-r—r— 1 root root 1.5M 4月 28 2011 haarcascade_mcs_upperbody.xml
-rw-r—r— 1 root root 1.1M 4月 28 2011 haarcascade_profileface.xml
-rw-r—r— 1 root root 317K 4月 28 2011 haarcascade_righteye_2splits.xml
-rw-r—r— 1 root root 1022K 4月 28 2011 haarcascade_upperbody.xml
~/usr/share/opencv/haarcascades>>
根据文件名大家应该能知道是识别什么的。值得一提的是,这里面有四个关于人脸(frontalface)的识别库, 根据我的使用体验,default这个xml识别的最多,这就意味着本来不是头像的也识别成头像了。 alt_tree这个库虽然是最大的,但并不意味着这个库是最好的,应该说,用这个库,识别是最严格的, 这就意味着,有些头像不能被识别,因为根据他的算法,他认为这不是头像。 其余两个和alt_tree差不多。具体识别细节大家可以打开相应的xml看一下。

上面的代码只是识别面部,并不包括头发,如果大家想抓一个完整的头像的话, 可以将识别出来的矩形框的上边缘增加一定的比例,比如增加20%头像的高度。

附:C++语言人脸识别代码

网上找的,亲测可用,效率比python高一点。

  1. #include "cv.h"
  2. #include "highgui.h"
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <assert.h>
  7. #include <math.h>
  8. #include <float.h>
  9. #include <limits.h>
  10. #include <time.h>
  11. #include <ctype.h>
  12. #ifdef _EiC
  13. #define WIN32
  14. #endif
  15. static CvMemStorage* storage = 0;
  16. static CvHaarClassifierCascade* cascade = 0;
  17. void detect_and_draw( IplImage* image );
  18. const char* cascade_name =
  19. "haarcascade_frontalface_alt.xml";
  20. /* "haarcascade_profileface.xml";*/
  21. int main( int argc, char** argv )
  22. {
  23. CvCapture* capture = 0;
  24. IplImage *frame, *frame_copy = 0;
  25. int optlen = strlen("--cascade=");
  26. const char* input_name;
  27. if( argc > 1 && strncmp( argv[1], "--cascade=", optlen ) == 0 )
  28. {
  29. cascade_name = argv[1] + optlen;
  30. input_name = argc > 2 ? argv[2] : 0;
  31. }
  32. else
  33. {
  34. cascade_name = "/usr/share/opencv/haarcascades/haarcascade_frontalface_default.xml";
  35. //opencv装好后haarcascade_frontalface_alt2.xml的路径,
  36. //也可以把这个文件拷到你的工程文件夹下然后不用写路径名cascade_name= "haarcascade_frontalface_alt2.xml";
  37. //或者cascade_name ="C:\\Program Files\\OpenCV\\data\\haarcascades\\haarcascade_frontalface_alt2.xml"
  38. input_name = argc > 1 ? argv[1] : 0;
  39. }
  40. cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
  41. if( !cascade )
  42. {
  43. fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
  44. fprintf( stderr,
  45. "Usage: facedetect --cascade=\"<cascade_path>\" [filename|camera_index]\n" );
  46. return -1;
  47. }
  48. storage = cvCreateMemStorage(0);
  49. if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
  50. capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
  51. else
  52. capture = cvCaptureFromAVI( input_name );
  53. cvNamedWindow( "result", 1 );
  54. if( capture )
  55. {
  56. for(;;)
  57. {
  58. if( !cvGrabFrame( capture ))
  59. break;
  60. frame = cvRetrieveFrame( capture );
  61. if( !frame )
  62. break;
  63. if( !frame_copy )
  64. frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
  65. IPL_DEPTH_8U, frame->nChannels );
  66. if( frame->origin == IPL_ORIGIN_TL )
  67. cvCopy( frame, frame_copy, 0 );
  68. else
  69. cvFlip( frame, frame_copy, 0 );
  70. detect_and_draw( frame_copy );
  71. if( cvWaitKey( 10 ) >= 0 )
  72. break;
  73. }
  74. cvReleaseImage( &frame_copy );
  75. cvReleaseCapture( &capture );
  76. }
  77. else
  78. {
  79. const char* filename = input_name ? input_name : (char*)"lena.jpg";
  80. IplImage* image = cvLoadImage( filename, 1 );
  81. if( image )
  82. {
  83. detect_and_draw( image );
  84. cvWaitKey(0);
  85. cvReleaseImage( &image );
  86. }
  87. else
  88. {
  89. /* assume it is a text file containing the
  90. list of the image filenames to be processed - one per line */
  91. FILE* f = fopen( filename, "rt" );
  92. if( f )
  93. {
  94. char buf[1000+1];
  95. while( fgets( buf, 1000, f ) )
  96. {
  97. int len = (int)strlen(buf);
  98. while( len > 0 && isspace(buf[len-1]) )
  99. len--;
  100. buf[len] = '\0';
  101. image = cvLoadImage( buf, 1 );
  102. if( image )
  103. {
  104. detect_and_draw( image );
  105. cvWaitKey(0);
  106. cvReleaseImage( &image );
  107. }
  108. }
  109. fclose(f);
  110. }
  111. }
  112. }
  113. // getchar();
  114. cvDestroyWindow("result");
  115. return 0;
  116. }
  117. void detect_and_draw( IplImage* img )
  118. {
  119. static CvScalar colors[] =
  120. {
  121. {{0,0,255}},
  122. {{0,128,255}},
  123. {{0,255,255}},
  124. {{0,255,0}},
  125. {{255,128,0}},
  126. {{255,255,0}},
  127. {{255,0,0}},
  128. {{255,0,255}}
  129. };
  130. double scale = 1.3;
  131. IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
  132. IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
  133. cvRound (img->height/scale)),
  134. 8, 1 );
  135. int i;
  136. cvCvtColor( img, gray, CV_BGR2GRAY );
  137. cvResize( gray, small_img, CV_INTER_LINEAR );
  138. cvEqualizeHist( small_img, small_img );
  139. cvClearMemStorage( storage );
  140. if( cascade )
  141. {
  142. double t = (double)cvGetTickCount();
  143. CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
  144. 1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/,
  145. cvSize(30, 30) );
  146. t = (double)cvGetTickCount() - t;
  147. printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
  148. for( i = 0; i < (faces ? faces->total : 0); i++ )
  149. {
  150. CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
  151. CvPoint center;
  152. int radius;
  153. center.x = cvRound((r->x + r->width*0.5)*scale);
  154. center.y = cvRound((r->y + r->height*0.5)*scale);
  155. radius = cvRound((r->width + r->height)*0.25*scale);
  156. cvCircle( img, center, radius, colors[i%8], 3, 8, 0 );
  157. }
  158. }
  159. cvShowImage( "result", img );
  160. cvReleaseImage( &gray );
  161. cvReleaseImage( &small_img );
  162. }

更多相关文章

  1. Android(安卓)语音识别学习小记--暑期大学生博客分享大赛 - 2011
  2. Android8.1以及5.1版本识别sdcard和U盘并创建文件解决办法
  3. Androidの通过查询电话号码或ID获取联系人头像
  4. Android(安卓)手势识别向左,右,上,下,滑动的方向
  5. android 开源 OCR 项目 及手写识别
  6. android 圆形头像—— android开源系列:CircleImageView自定义圆
  7. Android使用科大讯飞实现语音播报、语音识别功能
  8. Android设备的识别
  9. Android(安卓)语音识别示例

随机推荐

  1. Android面试系列文章2018之Android部分事
  2. Android(安卓)apk的安装、卸载
  3. Android中使用事件总线的优缺点
  4. Smack和Asmack
  5. Android开发都需要使用什么语言?
  6. Android imageView 实现小红点(动画呼吸效
  7. Android—TextView的XML属性和方法
  8. Android(安卓)学习资料大集合
  9. Fragment的添加方法总结
  10. MIUI 音乐播放器[Android] | 小众软件 >