python使用opencv进行人脸识别


Posted in Python onApril 07, 2017

环境

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

示例代码

#!/usr/bin/env python
#coding=utf-8
import os
from PIL import Image, ImageDraw
import cv

def detect_object(image):
 '''检测图片,获取人脸在图片中的坐标'''
 grayscale = cv.CreateImage((image.width, image.height), 8, 1)
 cv.CvtColor(image, grayscale, cv.CV_BGR2GRAY)

 cascade = cv.Load("/usr/share/opencv/haarcascades/haarcascade_frontalface_alt_tree.xml")
 rect = cv.HaarDetectObjects(grayscale, cascade, cv.CreateMemStorage(), 1.1, 2,
  cv.CV_HAAR_DO_CANNY_PRUNING, (20,20))

 result = []
 for r in rect:
  result.append((r[0][0], r[0][1], r[0][0]+r[0][2], r[0][1]+r[0][3]))

 return result

def process(infile):
 '''在原图上框出头像并且截取每个头像到单独文件夹'''
 image = cv.LoadImage(infile);
 if image:
  faces = detect_object(image)

 im = Image.open(infile)
 path = os.path.abspath(infile)
 save_path = os.path.splitext(path)[0]+"_face"
 try:
  os.mkdir(save_path)
 except:
  pass
 if faces:
  draw = ImageDraw.Draw(im)
  count = 0
  for f in faces:
   count += 1
   draw.rectangle(f, outline=(255, 0, 0))
   a = im.crop(f)
   file_name = os.path.join(save_path,str(count)+".jpg")
  #  print file_name
   a.save(file_name)

  drow_save_path = os.path.join(save_path,"out.jpg")
  im.save(drow_save_path, "JPEG", quality=80)
 else:
  print "Error: cannot detect faces on %s" % infile
if __name__ == "__main__":
 process("./opencv_in.jpg")

转换效果

原图:

python使用opencv进行人脸识别

转换后

python使用opencv进行人脸识别

使用感受

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

识别效率有点低,有时候一张图片能处理七八秒才能处理完,当然这个和机器配置有关。 如果想加速的话可以使用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高一点。

#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>
#ifdef _EiC
#define WIN32
#endif
static CvMemStorage* storage = 0;
static CvHaarClassifierCascade* cascade = 0;
void detect_and_draw( IplImage* image );
const char* cascade_name =
"haarcascade_frontalface_alt.xml";
/* "haarcascade_profileface.xml";*/
int main( int argc, char** argv )
{
 CvCapture* capture = 0;
 IplImage *frame, *frame_copy = 0;
 int optlen = strlen("--cascade=");
 const char* input_name;
 if( argc > 1 && strncmp( argv[1], "--cascade=", optlen ) == 0 )
 {
  cascade_name = argv[1] + optlen;
  input_name = argc > 2 ? argv[2] : 0;
 }
 else
 {
  cascade_name = "/usr/share/opencv/haarcascades/haarcascade_frontalface_default.xml";
  //opencv装好后haarcascade_frontalface_alt2.xml的路径,
  //也可以把这个文件拷到你的工程文件夹下然后不用写路径名cascade_name= "haarcascade_frontalface_alt2.xml"; 
  //或者cascade_name ="C:\\Program Files\\OpenCV\\data\\haarcascades\\haarcascade_frontalface_alt2.xml"
  input_name = argc > 1 ? argv[1] : 0;
 }
 cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
 if( !cascade )
 {
  fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
  fprintf( stderr,
    "Usage: facedetect --cascade=\"<cascade_path>\" [filename|camera_index]\n" );
  return -1;
 }
 storage = cvCreateMemStorage(0);
 if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
 capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
 else
 capture = cvCaptureFromAVI( input_name ); 
 cvNamedWindow( "result", 1 );
 if( capture )
 {
  for(;;)
  {
   if( !cvGrabFrame( capture ))
   break;
   frame = cvRetrieveFrame( capture );
   if( !frame )
   break;
   if( !frame_copy )
   frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
          IPL_DEPTH_8U, frame->nChannels );
   if( frame->origin == IPL_ORIGIN_TL )
   cvCopy( frame, frame_copy, 0 );
   else
   cvFlip( frame, frame_copy, 0 );
   detect_and_draw( frame_copy );
   if( cvWaitKey( 10 ) >= 0 )
   break;
  }
  cvReleaseImage( &frame_copy );
  cvReleaseCapture( &capture );
 }
 else
 {
  const char* filename = input_name ? input_name : (char*)"lena.jpg";
  IplImage* image = cvLoadImage( filename, 1 );
  if( image )
  {
   detect_and_draw( image );
   cvWaitKey(0);
   cvReleaseImage( &image );
  }
  else
  {
   /* assume it is a text file containing the
   list of the image filenames to be processed - one per line */
   FILE* f = fopen( filename, "rt" );
   if( f )
   {
    char buf[1000+1];
    while( fgets( buf, 1000, f ) )
    {
     int len = (int)strlen(buf);
     while( len > 0 && isspace(buf[len-1]) )
     len--;
     buf[len] = '\0';
     image = cvLoadImage( buf, 1 );
     if( image )
     {
      detect_and_draw( image );
      cvWaitKey(0);
      cvReleaseImage( &image );
     }
    }
    fclose(f);
   }
  }
 }
 // getchar();
 cvDestroyWindow("result");
 return 0;
}
void detect_and_draw( IplImage* img )
{
 static CvScalar colors[] = 
 {
  {{0,0,255}},
  {{0,128,255}},
  {{0,255,255}},
  {{0,255,0}},
  {{255,128,0}},
  {{255,255,0}},
  {{255,0,0}},
  {{255,0,255}}
 };
 double scale = 1.3;
 IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
 IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
            cvRound (img->height/scale)),
          8, 1 );
 int i;
 cvCvtColor( img, gray, CV_BGR2GRAY );
 cvResize( gray, small_img, CV_INTER_LINEAR );
 cvEqualizeHist( small_img, small_img );
 cvClearMemStorage( storage );
 if( cascade )
 {
  double t = (double)cvGetTickCount();
  CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
           1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/,
           cvSize(30, 30) );
  t = (double)cvGetTickCount() - t;
  printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
  for( i = 0; i < (faces ? faces->total : 0); i++ )
  {
   CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
   CvPoint center;
   int radius;
   center.x = cvRound((r->x + r->width*0.5)*scale);
   center.y = cvRound((r->y + r->height*0.5)*scale);
   radius = cvRound((r->width + r->height)*0.25*scale);
   cvCircle( img, center, radius, colors[i%8], 3, 8, 0 );
  }
 }
 cvShowImage( "result", img );
 cvReleaseImage( &gray );
 cvReleaseImage( &small_img );
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Python 相关文章推荐
python通过zabbix api获取主机
Sep 17 Python
解决python3 安装完Pycurl在import pycurl时报错的问题
Oct 15 Python
Python之两种模式的生产者消费者模型详解
Oct 26 Python
解决pyinstaller打包pyqt5的问题
Jan 08 Python
使用Python批量修改文件名的代码实例
Jan 24 Python
Python获取数据库数据并保存在excel表格中的方法
Jun 12 Python
Pandas中Series和DataFrame的索引实现
Jun 27 Python
python爬虫 urllib模块反爬虫机制UA详解
Aug 20 Python
如何在pycharm中安装第三方包
Oct 27 Python
如何基于Python和Flask编写Prometheus监控
Nov 25 Python
Django用内置方法实现简单搜索功能的方法
Dec 18 Python
Python使用protobuf序列化和反序列化的实现
May 19 Python
Python 实现链表实例代码
Apr 07 #Python
python中如何使用朴素贝叶斯算法
Apr 06 #Python
python获取当前运行函数名称的方法实例代码
Apr 06 #Python
python爬取w3shcool的JQuery课程并且保存到本地
Apr 06 #Python
使用Python对SQLite数据库操作
Apr 06 #Python
使用Python对MySQL数据操作
Apr 06 #Python
windows 10下安装搭建django1.10.3和Apache2.4的方法
Apr 05 #Python
You might like
php面向对象的方法重载两种版本比较
2008/09/08 PHP
php提示Failed to write session data错误的解决方法
2014/12/17 PHP
php为字符串前后添加指定数量字符的方法
2015/05/04 PHP
PHP连接SQL Server的方法分析【基于thinkPHP5.1框架】
2019/05/06 PHP
laravel执行php artisan migrate报错的解决方法
2019/10/09 PHP
Jquery 获取表单text,areatext,radio,checkbox,select值的代码
2009/11/12 Javascript
学习从实践开始之jQuery插件开发 菜单插件开发
2012/05/03 Javascript
JS清空多文本框、文本域示例代码
2014/02/24 Javascript
jquery实现两边飘浮可关闭的对联广告
2015/11/27 Javascript
JS IOS/iPhone的Safari浏览器不兼容Javascript中的Date()问题如何解决
2016/11/11 Javascript
weUI应用之JS常用信息提示弹层的封装
2016/11/21 Javascript
详解为Angular.js内置$http服务添加拦截器的方法
2016/12/20 Javascript
详解Javascript百度地图接口开发文档中的类和方法
2017/02/07 Javascript
bootstrap为水平排列的表单和内联表单设置可选的图标
2017/02/15 Javascript
关于JavaScript中的this指向问题总结篇
2017/07/23 Javascript
Mint UI 基于 Vue.js 移动端组件库
2017/11/07 Javascript
webpack打包并将文件加载到指定的位置方法
2018/02/22 Javascript
为什么要使用Vuex的介绍
2019/01/19 Javascript
javascript实现贪吃蛇小游戏
2020/07/28 Javascript
[53:15]2018DOTA2亚洲邀请赛3月29日 小组赛A组 KG VS OG
2018/03/30 DOTA
Python检测一个对象是否为字符串类的方法
2015/05/21 Python
Python简单删除列表中相同元素的方法示例
2017/06/12 Python
Python的mysql数据库的更新如何实现
2017/07/31 Python
对python中 math模块下 atan 和 atan2的区别详解
2020/01/17 Python
django之导入并执行自定义的函数模块图解
2020/04/01 Python
联想西班牙官网:Lenovo西班牙
2018/08/28 全球购物
HSRP的含义以及如何工作
2014/09/10 面试题
土木工程专业自荐信
2013/10/04 职场文书
质量承诺书范文
2014/03/27 职场文书
《分一分》教学反思
2014/04/13 职场文书
厨房领班竞聘演讲稿
2014/04/23 职场文书
模具专业自荐信
2014/05/29 职场文书
2014年煤矿工作总结
2014/11/24 职场文书
西游记读书笔记
2015/06/25 职场文书
go web 预防跨站脚本的实现方式
2021/06/11 Golang
React自定义hook的方法
2022/06/25 Javascript