OpenCV人脸训练分类器
【转载】opencv实现人脸检测

【转载】opencv实现⼈脸检测全⽂转载⾃CSDN的博客(不知道怎么将CSDN的博客转到博客园,应该没这功能吧,所以直接复制全⽂了),转载地址如下本篇⽂章主要介绍了如何使⽤OpenCV实现⼈脸检测。
本⽂不具体讲解⼈脸检测的原理,直接使⽤OpenCV实现。
OpenCV版本:2.4.10;VS开发版本:VS2012。
⼀、OpenCV⼈脸检测要实现⼈脸识别功能,⾸先要进⾏⼈脸检测,判断出图⽚中⼈脸的位置,才能进⾏下⼀步的操作。
1、OpenCV⼈脸检测的⽅法在OpenCV中主要使⽤了两种特征(即两种⽅法)进⾏⼈脸检测,Haar特征和LBP特征。
在OpenCV中,使⽤已经训练好的XML格式的分类器进⾏⼈脸检测。
在OpenCV的安装⽬录下的sources⽂件夹⾥的data⽂件夹⾥可以看到下图所⽰的内容:上图中⽂件夹的名字“haarcascades”、“hogcascades”和“lbpcascades”分别表⽰通过“haar”、“hog”和“lbp”三种不同的特征⽽训练出的分类器:即各⽂件夹⾥的⽂件。
"haar"特征主要⽤于⼈脸检测,“hog”特征主要⽤于⾏⼈检测,“lbp”特征主要⽤于⼈脸识别。
打开“haarcascades”⽂件夹,如下图所⽰图中的XML⽂件即是我们⼈脸检测所需要的分类器⽂件。
在实际使⽤中,推荐使⽤上图中被标记的“haarcascade_frontalface_alt2.xml”分类器⽂件,准确率和速度都⽐较好。
2、OpenCV中的⼈脸检测的类在OpenCV中,使⽤类“CascadeClassifier”进⾏⼈脸检测CascadeClassifier faceCascade; //实例化对象所需要使⽤的函数:faceCascade.load("../data/haarcascade_frontalface_alt2"); //加载分类器faceCascade.detectMultiScale(imgGray, faces, 1.2, 6, 0, Size(0, 0)); //多尺⼨检测⼈脸实现⼈脸检测主要依赖于detectMultiScale()函数,下⾯简单说⼀下函数参数的含义,先看函数原型:1. CV_WRAP virtual void detectMultiScale( const Mat& image,2. CV_OUT vector<Rect>& objects,3. double scaleFactor=1.1,4. int minNeighbors=3, int flags=0,5. Size minSize=Size(),6. Size maxSize=Size() );各参数含义:const Mat& image: 需要被检测的图像(灰度图)vector<Rect>& objects: 保存被检测出的⼈脸位置坐标序列double scaleFactor: 每次图⽚缩放的⽐例int minNeighbors: 每⼀个⼈脸⾄少要检测到多少次才算是真的⼈脸int flags:决定是缩放分类器来检测,还是缩放图像Size(): 表⽰⼈脸的最⼤最⼩尺⼨⼆、代码实现1、检测图⽚中的⼈脸#include<opencv2/objdetect/objdetect.hpp>#include<opencv2/highgui/highgui.hpp>#include<opencv2/imgproc/imgproc.hpp>using namespace cv;//⼈脸检测的类CascadeClassifier faceCascade;int main(){faceCascade.load("../data/haarcascade_frontalface_alt2.xml"); //加载分类器,注意⽂件路径Mat img = imread("../data/PrettyGirl.jpg");Mat imgGray;vector<Rect> faces;if(img.empty()){return1;}if(img.channels() ==3){cvtColor(img, imgGray, CV_RGB2GRAY);}else{imgGray = img;}faceCascade.detectMultiScale(imgGray, faces, 1.2, 6, 0, Size(0, 0)); //检测⼈脸if(faces.size()>0){for(int i =0; i<faces.size(); i++){rectangle(img, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height), Scalar(0, 255, 0), 1, 8); //框出⼈脸位置}}imshow("FacesOfPrettyGirl", img);waitKey(0);return0;}结果如下图:2、检测视频中的⼈脸//头⽂件#include<opencv2/objdetect/objdetect.hpp>#include<opencv2/highgui/highgui.hpp>#include<opencv2/imgproc/imgproc.hpp>using namespace cv;//⼈脸检测的类CascadeClassifier faceCascade;int main(){faceCascade.load("../data/haarcascade_frontalface_alt2.xml"); //加载分类器,注意⽂件路径VideoCapture cap;cap.open(0); //打开摄像头//cap.open("../data/test.avi"); //打开视频Mat img, imgGray;vector<Rect> faces;int c = 0;if(!cap.isOpened()){return1;}while(c!=27)cap>>img;if(img.channels() ==3){cvtColor(img, imgGray, CV_RGB2GRAY);}else{imgGray = img;}faceCascade.detectMultiScale(imgGray, faces, 1.2, 6, 0, Size(0, 0)); //检测⼈脸if(faces.size()>0){for(int i =0; i<faces.size(); i++){rectangle(img, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height),Scalar(0, 255, 0), 1, 8); //框出⼈脸位置}}imshow("Camera", img);c = waitKey(1);}return0;}在视频实时检测时,可能会出现卡顿,是因为检测⼈脸花费了过多的时间,这⾥代码只实现基本功能,并未优化。
Opencv之人脸检测

Opencv之人脸检测如之前所说的,运动物体检测的工作已经告一段落了,目前正式进入无所事事的阶段。
也罢,索性就Opencv进一步学习。
这里,就不得不说一下,百度确实是一个强大的工具。
我自学Opencv的资料都来自于网上,图书馆借来的书基本上都是冷宫状态。
为什么呢?用户体验感呗。
不得不喷一下,书上的理论公式啥的,哪对得上我这急性子的胃口啊!这里,推荐几个人的博客给大家,这些资料对于要从Opencv的角度学习图像处理的童鞋应该还是很有帮助的。
1、/index.php/%e9%a6%96%e9%a1%b52、/blog/morewindows/82257833、/column/details/opencv-tutorial.html这三个网站上有部分内容将会重复出现,但只要仔细观察,会发现每位博主的重点都不一样,毕竟每个人编程过程中遇到的问题都不同。
好了,讲讲人脸识别吧,我其实对于这项新起的技术没有多学术化的认识。
结合这次项目中的进度:检测出了运动物体,把它提取出来,再进行人脸检测判断是否为人类,如果是,进行跟踪判断其行为是否异常。
所以我也有必要了解它。
刚开始对于这项功能的实现还是很期待的,总觉得人的属性那么复杂,要想这么立竿见影的对它进行技术约束,应该很不容易。
结果,强大的opencv让这项功能的实现难度指数将至负。
且不说这个,他检测的结果也真是让人哭笑不得。
这里附上一图吧。
1.蓝色圆圈示意出的区域即为系统检测到的“人脸”,我初看到这个结果也甚是惊讶,难道这项技术就是把人脸的五官做成相对坐标进行备份,设置一系列阈值即可。
虽然,我的猜测有点剑走偏锋,但并不是没有依据。
因为之前我用“奶茶妹”卖萌的一张照片做检测,因为其脸是横着地,就是那种依偎在东哥肩膀上的姿势,可能这种脸的姿势违背了Opencv对于人脸五官相对坐标的分布,所以,可怜的奶茶妹没有被人脸检测出来。
(虽然事先我一直以为是长的太萌就,,,技术失效),看来是我想多了。
基于opencv的人脸识别程序-代码详解

#include "cv.h"#include "highgui.h"#include <stdio.h>#ifdef _EiC#define WIN32#endifstatic CvMemStorage* storage = 0;static CvHaarClassifierCascade* cascade = 0;void detect_and_draw( IplImage* image );const char* cascade_name ="haarcascade_frontalface_alt.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 = "E:\毕业设计\智能机器人动态人脸识别系统\陈建州程序.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);capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );//读取摄像头if(!capture)//如果没有摄像头读取视频文件capture = cvCaptureFromA VI("检测.avi");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 );elsecvFlip( frame, frame_copy, 0 );detect_and_draw( frame_copy );if( cvWaitKey( 10 ) >= 0 )break;}cvReleaseImage( &frame_copy );cvReleaseCapture( &capture );}else//没检测到视频文件或者摄像头{const char* filename = (char*)"检测.jpg";//读图片IplImage* image = cvLoadImage( filename, 1 );if( image ){detect_and_draw( image );cvWaitKey(0);cvReleaseImage( &image );}else{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);}}}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 );}OpenCV的人脸检测主要是调用训练好的cascade(Haar分类器)来进行模式匹配。
opencv adaboost人脸检测训练程序阅读笔记(LBP特征)

1、训练程序整体流程(1)读输入参数并打印相关信息(2)进入训练程序最外层入口classifier.train1)读正负样本,将正负样本放入imgLiast中,先读正样本,后读负样本2)load( dirName )判断之前是否有已训练好的xml文件,若有,不在重新训练该stage的xml文件,没有返回false,初始化参数3)计算requiredLeafFARate = pow(maxFalseAlarm,numStages)/max_depth,该参数是stage停止条件(利用训练样本集来计算tempLeafFARate,若tempLeafFARate小于这一参数,则退出stage训练循环);4)Stage训练循环5)更新训练样本集,计算tempLeafFARate(负样本被预测为正样本的个数除以读取负样本的次数,第一次没有训练之前,这个比值为1,因为没训练之前,所有负样本都被预测成了正样本,当第一层训练好以后,负样本采集时会先用第一层的分类器预测一次,若能分类,则不选用,选用负样本的数目是固定的,但选用这么多负样本总共要选的次数会随着层数的增多而加大,因为层数越大,分类器的分类能力也要求越大,说需要的样本就是前面分类器所不恩呢该识别的,故在采集时也比较困难。
)6)判断stage是否退出训练,若tempLeafFARate<requiredLeafFARate则退出stage训练,否则继续;7)强训练器训练入口tempStage->train()a.建立训练数据data = new CvCascadeBoostTrainData(主要是一些参数的设置,还有特征值的计算)b.初始化样本权重update_weights( 0 );c.弱分类器训练循环i)tree->train—》do_trainai) 根节点的初始root = data->subsample_data( _subsample_idx );(主要是对根节点的一些参数进行初始化,parent 0,count 1,split 0,value 0,class_idx 0,maxlr 0,left = right = 0,等等)bi) CV_CALL( try_split_node(root)),根据根节点计算整颗数的各节点的参数配置aii) calc_node_value( node );计算节点的回归值,类似于分类投票值sum(w*class_lable),正样本的class_lable取,负样本的class_lable取-1;计算节点的风险值node_risk,noderisk is the sum of squared errors: sum_i((Y_i -<node_value>)^2)bii) 判断节点是否可以分裂(判断依据:样本值和设计的节点最大深度);再利用node_risk与regression_accuracy,如果这个节点的所有训练样本的节点估计值的绝对差小于这个参数,节点不再进行分裂cii) 找出最佳分裂best_split = find_best_split(node);aiii) 定义DTreeBestSplitFinder finder( this, node );biii) parallel_reduce(cv::BlockedRange(0, data->var_count), finder);此时调用DTreeBestSplitFinder类的操作符DTreeBestSplitFinder::operator()(constBlockedRange& range)aiv) 遍历所有特征vi = vi1; vi< vi2; vi++biv) res = tree->find_split_cat_reg()得到特征为split->var_idx = vi的最佳分裂的质量split->quality(split->quality越大越好)av) 将特征为vi所有样本的特征值返回到cat_labelsbv) 计算每个特征值取值不权值和和响应和,例如特征值为,则将所有特征值列表中特征值为的样本权值相加,LBP的特征值范围是0~255,故有256个categorycv) 计算每个category的平均响应值,即将每个category的响应和除以每个category的样本权值和dv) icvSortDblPtr( sum_ptr, mi, 0 );把256个值进行升序排序,注意sum_ptr里存的是sum[i]的地址,这里排序的依据是特征值还是按照每个特征值的平均响应来排序???个人感觉是按特征值的平均响应来排序fv) 将每个特征值的平均响应值乘以该特征值的总权值得到每个特征值的总响应gv) 遍历subset_i = 0; subset_i< mi-1; subset_i++avi) 计算索引是subset_i在排序前的idxbvi) 获取索引idx对应的样本总权重cvi) 获取索引idx对应的样本总响应dvi) 以subset_i为分裂点,计算分裂质量(sumL*sumL)/ weightL +(sumR*sumR)/ weightRfvi) 若最佳分裂质量小于这个质量,则更新最佳分裂质量hv) 经过训练得到最佳分裂点和最佳分裂质量,将遍历得到的值更新到split结构体各参数。
python基于opencv实现人脸识别

python基于opencv实现⼈脸识别将opencv中haarcascade_frontalface_default.xml⽂件下载到本地,我们调⽤它辅助进⾏⼈脸识别。
识别图像中的⼈脸#coding:utf-8import cv2 as cv# 读取原始图像img = cv.imread('face.png')# 调⽤熟悉的⼈脸分类器识别特征类型# ⼈脸 - haarcascade_frontalface_default.xml# ⼈眼 - haarcascade_eye.xml# 微笑 - haarcascade_smile.xmlface_detect = cv.CascadeClassifier('haarcascade_frontalface_default.xml')gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)# 检查⼈脸按照1.1倍放到周围最⼩像素为5face_zone = face_detect.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)print ('识别⼈脸的信息:',face_zone)# 绘制矩形和圆形检测⼈脸for x, y, w, h in face_zone:# 绘制矩形⼈脸区域 thickness表⽰线的粗细cv.rectangle(img, pt1=(x, y), pt2=(x+w, y+h),color=[0,0,255], thickness=2)# 绘制圆形⼈脸区域 radius表⽰半径cv.circle(img, center=(x+w//2, y+h//2), radius=w//2, color=[0,255,0], thickness=2)# 设置图⽚可以⼿动调节⼤⼩dWindow("Easmount-CSDN", 0)# 显⽰图⽚cv.imshow("Easmount-CSDN", img)# 等待显⽰设置任意键退出程序cv.waitKey(0)cv.destroyAllWindows()注意,此算法只能检测正脸,并且任何算法都有⼀定的准确率。
android opencv facedetectyn 用法

android opencv facedetectyn 用法全文共四篇示例,供读者参考第一篇示例:Android中使用OpenCV进行人脸检测的方法是通过使用OpenCV库中的人脸检测算法来识别图像中的人脸。
OpenCV是一个开源的计算机视觉库,它提供了很多强大的图像处理和计算机视觉算法,包括人脸检测。
人脸检测是计算机视觉领域中的一个基础问题,它通常包括在一张图像中检测出所有的人脸,并标记出它们的位置。
人脸检测在很多应用中都被广泛使用,比如人脸识别、人脸表情识别、人脸跟踪等。
在Android应用中使用OpenCV进行人脸检测首先需要在项目中引入OpenCV库。
可以通过gradle添加依赖来引入OpenCV库,如下所示:implementation 'org.opencv:opencv-android:3.4.1'然后在代码中进行初始化OpenCV库,在Activity的onCreate 方法中调用OpenCVLoader.initDebug()方法进行初始化,如下所示:if (!OpenCVLoader.initDebug()) {Log.e("OpenCV", "初始化失败");} else {Log.d("OpenCV", "初始化成功");}}初始化成功后就可以使用OpenCV库中的人脸检测算法来进行人脸检测了。
OpenCV提供了CascadeClassifier类来实现人脸检测,它可以加载已经训练好的人脸检测器,如haarcascade_frontalface_default.xml。
在使用CascadeClassifier进行人脸检测时,首先需要创建一个CascadeClassifier对象并加载人脸检测器,如下所示:CascadeClassifier faceCascade = new CascadeClassifier();faceCascade.load(context.getResources().openRawResource(R.ra w.haarcascade_frontalface_default));然后可以使用CascadeClassifier的detectMultiScale方法来进行人脸检测,它会返回检测到的人脸的矩形区域。
基于OpenCV的人脸识别系统

基于OpenCV的人脸识别系统本文针对课题要求,将Visual C++作为开发工具,在开源计算机视觉平台OpenCV上进行大量的研究和测试,所涉及的内容有:视频图像的采集、人脸图像的预处理、数学形态学图像处理、人脸定位和经典的AdaBoosting算法等。
进而为研究人脸识别技术提供参考依据。
标签:识别系统视频识别OpenCV1 研究背景近年来,在安全入口控制、金融贸易等方面,随着应用需求的增长,生物统计识别技术受到社会的普遍关注。
目前,微电子和视觉系统有了新的进展,在一定程度上使得高性能自动识别技术的实现代价不断降低。
而人脸检测是所有的生物识别方法中应用最广泛的技术之一,人脸检测最初来源于人脸识别。
人脸检测的目的是检测一张图像是否有人脸,如果有人脸,就把它从图像背景中分离出来,然后对特征进行人脸识别。
而在视频中的人脸检测在信息处理中,已经成为一项相当难突破的技术,越来越受到计算机视觉界的广泛关注,作为一个有价值课题,已经渗透到各不同领域中。
2 视频识别功能详细设计2.1 本系统的人脸检测算法2.1.1 基于Haar特征的人脸检测算法。
本系统开发过程中使用的人脸检测算法为基于Haar特征的人脸检测算法,Haar特征定义:HAAR 算法是一种基于特征(feature)的算法,而不是基于像素的算法。
利用Haar特征分类器实现人脸识别,其特点主要表现为检测速度快,性能好,实现流程如图1所示:对于每个特定分类器来说,通常情况下用形状、感兴趣区域中的位置以及比例系数来定义其特征。
在浏览了几种经典的人脸检测算法后,回到本系统中使用的人脸检测算法上。
基于Haar特征的人脸检测算法是最近几年被引用较多,较典型的人脸检测算法。
2.1.2 积分图像。
积分图是Haar分类器能够实时检测人脸的保证。
积分图像是数字图像的一种表示方法,对(x,y)点处的像素值,代表所有左上角像素的总和。
其中g(i,j)是原始的图像,i(x,y)是积分图像。
基础学习笔记之opencv(1):opencv中facedetect例子浅析

基础学习笔记之opencv(1):opencv中facedetect例⼦浅析⼈脸检测⼀种主流的⽅法就是类haar+adaboosting,opencv中也是⽤的这种⽅法。
这种⽅法可以推⼴到刚性物体的检测,前提是要训练好级联分类器(⽐如说⽤类haar特征),⼀旦训练数据弄好了,直接调⽤opencv中的类CascadeClassifier,⽤它的⼏个简单的成员函数就可以完成检测功能。
所以说⽤起来还是很简单的。
下⾯就是⽤的opencv中⾃带的samples中的facedetect例⼦。
当然,源例⼦考虑到了摄像头,视频,图⽚多种情况,还有很多出错处理的表达。
这⾥我讲其代码都省略了,因为看起来不是特别简洁。
否则还需要⽤命令⾏输⼊,⽐如说如下图:要输⼊的东西⽐较多,如果⼀旦输⼊出错了,就会有如下显⽰:所以为了⽅便,还是把代码简洁了下,改后的代码和注释如下:1// face_detect.cpp : 定义控制台应⽤程序的⼊⼝点。
2//34 #include "stdafx.h"56 #include "opencv2/objdetect/objdetect.hpp"7 #include "opencv2/highgui/highgui.hpp"8 #include "opencv2/imgproc/imgproc.hpp"9 #include "opencv2/ml/ml.hpp"1011 #include <iostream>12 #include <stdio.h>1314using namespace std;15using namespace cv;1617void detectAndDraw( Mat& img,18 CascadeClassifier& cascade, CascadeClassifier& nestedCascade,19double scale);2021 String cascadeName = "./haarcascade_frontalface_alt2.xml";//⼈脸的训练数据22//String nestedCascadeName = "./haarcascade_eye_tree_eyeglasses.xml";//⼈眼的训练数据23 String nestedCascadeName = "./haarcascade_eye.xml";//⼈眼的训练数据2425int main( int argc, const char** argv )26 {27 Mat image;28 CascadeClassifier cascade, nestedCascade;//创建级联分类器对象29double scale = 1.3;3031//image = imread( "lena.jpg", 1 );//读⼊lena图⽚32 image = imread("people_with_hands.png",1);33 namedWindow( "result", 1 );//opencv2.0以后⽤namedWindow函数会⾃动销毁窗⼝3435if( !cascade.load( cascadeName ) )//从指定的⽂件⽬录中加载级联分类器36 {37 cerr << "ERROR: Could not load classifier cascade" << endl;38return0;39 }4041if( !nestedCascade.load( nestedCascadeName ) )42 {43 cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;44return0;45 }4647if( !image.empty() )//读取图⽚数据不能为空48 {49 detectAndDraw( image, cascade, nestedCascade, scale );50 waitKey(0);51 }5253return0;54 }5556void detectAndDraw( Mat& img,57 CascadeClassifier& cascade, CascadeClassifier& nestedCascade,58double scale)59 {60int i = 0;61double t = 0;62 vector<Rect> faces;63const static Scalar colors[] = { CV_RGB(0,0,255),64 CV_RGB(0,128,255),65 CV_RGB(0,255,255),66 CV_RGB(0,255,0),67 CV_RGB(255,128,0),68 CV_RGB(255,255,0),69 CV_RGB(255,0,0),70 CV_RGB(255,0,255)} ;//⽤不同的颜⾊表⽰不同的⼈脸7172 Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );//将图⽚缩⼩,加快检测速度7374 cvtColor( img, gray, CV_BGR2GRAY );//因为⽤的是类haar特征,所以都是基于灰度图像的,这⾥要转换成灰度图像75 resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );//将尺⼨缩⼩到1/scale,⽤线性插值76 equalizeHist( smallImg, smallImg );//直⽅图均衡7778 t = (double)cvGetTickCount();//⽤来计算算法执⾏时间79//检测⼈脸//detectMultiScale函数中smallImg表⽰的是要检测的输⼊图像为smallImg,faces表⽰检测到的⼈脸⽬标序列,1.1表⽰ //每次图像尺⼨减⼩的⽐例为1.1,2表⽰每⼀个⽬标⾄少要被检测到3次才算是真的⽬标(因为周围的像素和不同的窗⼝⼤ //⼩都可以检测到⼈脸),CV_HAAR_SCALE_IMAGE表⽰不是缩放分类器来检测,⽽是缩放图像,Size(30, 30)为⽬标的 //最⼩最⼤尺⼨84 cascade.detectMultiScale( smallImg, faces,85 1.1, 2, 086//|CV_HAAR_FIND_BIGGEST_OBJECT87//|CV_HAAR_DO_ROUGH_SEARCH88 |CV_HAAR_SCALE_IMAGE89 ,90 Size(30, 30) );9192 t = (double)cvGetTickCount() - t;//相减为算法执⾏的时间93 printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );94for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )95 {96 Mat smallImgROI;97 vector<Rect> nestedObjects;98 Point center;99 Scalar color = colors[i%8];100int radius;101 center.x = cvRound((r->x + r->width*0.5)*scale);//还原成原来的⼤⼩102 center.y = cvRound((r->y + r->height*0.5)*scale);103 radius = cvRound((r->width + r->height)*0.25*scale);104 circle( img, center, radius, color, 3, 8, 0 );105106//检测⼈眼,在每幅⼈脸图上画出⼈眼107if( nestedCascade.empty() )108continue;109 smallImgROI = smallImg(*r);110111//和上⾯的函数功能⼀样112 nestedCascade.detectMultiScale( smallImgROI, nestedObjects,113 1.1, 2, 0114//|CV_HAAR_FIND_BIGGEST_OBJECT115//|CV_HAAR_DO_ROUGH_SEARCH116//|CV_HAAR_DO_CANNY_PRUNING117 |CV_HAAR_SCALE_IMAGE118 ,119 Size(30, 30) );120for( vector<Rect>::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ )121 {122 center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);123 center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);124 radius = cvRound((nr->width + nr->height)*0.25*scale);125 circle( img, center, radius, color, 3, 8, 0 );//将眼睛也画出来,和对应⼈脸的图形是⼀样的126 }127 }128 cv::imshow( "result", img );129 }运⾏lena图的效果如下:运⾏有多个⼈图的效果图如下:可以看出,在多⼈图中,并不是每个⼈脸都能检测出来。
OpenCV训练分类器制作xml

OpenCV训练分类器制作xml文档2009年12月19日星期六 21:032009-12-19考了CET英语,心情很差,估计又不过的,哎!英文差!于是看看书,看看自己感兴趣的书今天下午,研究了整个下午的小难题,在8点40分终于搞定了!肚子饿,还没吃饭,还没洗澡,克服了一个不懂的小难题,心理有点体会,想在这里留点纪念,方便别人以后学习。
于是乎,我写了:(那些开训练器的相关介绍我就不再详细谈了,进入正题)我的问题:有了opencv自带的那些xml人脸检测文档,我们就可以用cvLoad ()这个函数加载他们,让他们对我们的人脸进行检测,但是,现在生活中的计算机视觉并不远远是检测人脸,还有很多物品需要识别,所以,能不能自己做个xml的检测文档,用它来检测自己需要的东西呢?例如,检测一个可乐瓶!问题解决:首先了解下,目标检测分为三个步骤:1、样本的创建2、训练分类器3、利用训练好的分类器进行目标检测。
一,样本的创建:训练样本分为正例样本和反例样本,其中正例样本是指待检目标样本(例如可乐瓶,人脸等),反例样本指其它任意图片,所有的样本图片都被归一化为同样的尺寸大小(例如,20x20)。
1 负样本(反例样本)可以来自于任意的图片,但这些图片不能包含目标特征。
负样本由背景描述文件来描述。
背景描述文件是一个文本文件,每一行包含了一个负样本图片的文件名(基于描述文件的相对路径)。
该文件必须手工创建。
例如,假定目录下有 bg1.bmp bg2.bmp 这2个负样本的图片,这2个图片放在img 目录下,所以其背景描述文件 bg.txt 的内容为_img/bg1.bmp 1 0 0 24 28_ing/bg2.bmp 1 0 0 24 28_img/bg3.bmp 1 0 0 24 28_ing/bg4.bmp 1 0 0 24 28_img/bg5.bmp 1 0 0 24 28_ing/bg6.bmp 1 0 0 24 28_img/bg7.bmp 1 0 0 24 28_ing/bg8.bmp 1 0 0 24 28_img/bg9.bmp 1 0 0 24 28_ing/bg10.bmp 1 0 0 24 28这样负样本建立完毕,先保存!等会用!2,正样本现在,我们来看正样本的创建步骤:正样本由程序createsample 程序来创建。
python中使用Opencv进行人脸识别

python中使⽤Opencv进⾏⼈脸识别上⼀节讲到⼈脸检测,现在讲⼀下⼈脸识别。
具体是通过程序采集图像并进⾏训练,并且基于这些训练的图像对⼈脸进⾏动态识别。
⼈脸识别前所需要的⼈脸库可以通过两种⽅式获得:1.⾃⼰从视频获取图像 2.从⼈脸数据库免费获得可⽤⼈脸图像,如ORL⼈脸库(包含40个⼈每⼈10张⼈脸,总共400张⼈脸),ORL⼈脸库中的每⼀张图像⼤⼩为92x112。
若要对这些样本进⾏⼈脸识别必须要在包含⼈脸的样本图像上进⾏⼈脸识别。
这⾥提供⾃⼰准备图像识别出⾃⼰的⽅法。
1.采集⼈脸信息:通过摄像头采集⼈脸信息,10张以上即可,把图像⼤⼩调整为92x112,保存在⼀个指定的⽂件夹,⽂件名后缀为.pngdef generator(data):'''打开摄像头,读取帧,检测该帧图像中的⼈脸,并进⾏剪切、缩放⽣成图⽚满⾜以下格式:1.灰度图,后缀为 .png2.图像⼤⼩相同params:data:指定⽣成的⼈脸数据的保存路径'''name=input('my name:')#如果路径存在则删除路径path=os.path.join(data,name)if os.path.isdir(path):shutil.rmtree(path)#创建⽂件夹os.mkdir(path)#创建⼀个级联分类器face_casecade=cv2.CascadeClassifier('../haarcascades/haarcascade_frontalface_default.xml')#打开摄像头camera=cv2.VideoCapture(0)dWindow('Dynamic')#计数count=1while(True):#读取⼀帧图像ret,frame=camera.read()if ret:#转换为灰度图gray_img=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)#⼈脸检测face=face_casecade.detectMultiScale(gray_img,1.3,5)for (x,y,w,h) in face:#在原图上绘制矩形cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2)#调整图像⼤⼩new_frame=cv2.resize(frame[y:y+h,x:x+w],(92,112))#保存⼈脸cv2.imwrite('%s/%s.png'%(path,str(count)),new_frame)count+=1cv2.imshow('Dynamic',frame)#按下q键退出if cv2.waitKey(100) & 0xff==ord('q'):breakcamera.release()cv2.destroyAllWindows()该程序运⾏后会在指定的data路径下创建⼀个你输⼊的⼈名的⽂件夹⽤于存放采集到的图像,在这⾥我输⼊了wjy,结果如图2.⼈脸识别OpenCV有3中⼈脸识别⽅法,分别基于三个不同算法,分别为Eigenfaces,Fisherfaces和Local Binary Pattern Histogram这些⽅法都有类似的⼀个过程,即先对数据集进⾏训练,对图像或视频中的⼈脸进⾏分析,并且从两个⽅⾯确定:1.是否识别到对应的⽬标,2.识别到的⽬标的置信度,在实际中通过阈值进⾏筛选,置信度⾼于阈值的⼈脸将被丢弃这⾥介绍⼀下利⽤特征脸即Eigenfaces进⾏⼈脸识别算法,特征脸法本质上就是PCA降维,基本思路是先把图像灰度化,转化为单通道,再将它⾸位相接转换为列向量,假设图像的⼤⼩是20*20的,那么这个向量就是400维,但是维度太⾼算法复杂度也会升⾼,所以需要降维,再使⽤简单排序即可#载⼊图像读取ORL⼈脸数据库,准备训练数据def LoadImages(data):'''加载图⽚数据⽤于训练params:data:训练数据所在的⽬录,要求图⽚尺⼨⼀样ret:images:[m,height,width] m为样本数,height为⾼,width为宽names:名字的集合labels:标签'''images=[]names=[]labels=[]label=0#遍历所有⽂件夹for subdir in os.listdir(data):subpath=os.path.join(data,subdir)#print('path',subpath)#判断⽂件夹是否存在if os.path.isdir(subpath):#在每⼀个⽂件夹中存放着⼀个⼈的许多照⽚names.append(subdir)#遍历⽂件夹中的图⽚⽂件for filename in os.listdir(subpath):imgpath=os.path.join(subpath,filename)img=cv2.imread(imgpath,cv2.IMREAD_COLOR)gray_img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#cv2.imshow('1',img)#cv2.waitKey(0)images.append(gray_img)labels.append(label)label+=1images=np.asarray(images)#names=np.asarray(names)labels=np.asarray(labels)return images,labels,names#检验训练结果def FaceRec(data):#加载训练的数据X,y,names=LoadImages(data)#print('x',X)model=cv2.face.EigenFaceRecognizer_create()model.train(X,y)#打开摄像头camera=cv2.VideoCapture(0)dWindow('Dynamic')#创建级联分类器face_casecade=cv2.CascadeClassifier('../haarcascades/haarcascade_frontalface_default.xml')while(True):#读取⼀帧图像#ret:图像是否读取成功#frame:该帧图像ret,frame=camera.read()#判断图像是否读取成功#print('ret',ret)if ret:#转换为灰度图gray_img=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)#利⽤级联分类器鉴别⼈脸faces=face_casecade.detectMultiScale(gray_img,1.3,5)#遍历每⼀帧图像,画出矩形for (x,y,w,h) in faces:frame=cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2) #蓝⾊roi_gray=gray_img[y:y+h,x:x+w]try:#将图像转换为宽92 ⾼112的图像#resize(原图像,⽬标⼤⼩,(插值⽅法)interpolation=,)roi_gray=cv2.resize(roi_gray,(92,112),interpolation=cv2.INTER_LINEAR)params=model.predict(roi_gray)print('Label:%s,confidence:%.2f'%(params[0],params[1]))'''putText:给照⽚添加⽂字putText(输⼊图像,'所需添加的⽂字',左上⾓的坐标,字体,字体⼤⼩,颜⾊,字体粗细)'''cv2.putText(frame,names[params[0]],(x,y-20),cv2.FONT_HERSHEY_SIMPLEX,1,255,2)except:continuecv2.imshow('Dynamic',frame)#按下q键退出if cv2.waitKey(100) & 0xff==ord('q'):breakcamera.release()cv2.destroyAllWindows()在程序中,我们⽤cv2.face.EigenFaceRecognizer_create()创建⼈脸识别的模型,通过图像数组和对应标签数组来训练模型,该函数有两个重要的参数,1.保留主成分的数⽬,2.指定的置信度阈值,为⼀个浮点型。
人脸识别训练实验报告

一、实验背景随着人工智能技术的飞速发展,人脸识别技术作为生物识别领域的重要分支,已广泛应用于安防监控、智能门禁、手机解锁等领域。
本实验旨在通过人脸识别技术,实现对人脸图像的自动识别与分类,并验证所采用算法的有效性。
二、实验目的1. 熟悉人脸识别技术的基本原理和流程。
2. 掌握人脸图像预处理、特征提取和分类的方法。
3. 评估不同人脸识别算法的性能,并选择最优算法。
4. 实现人脸识别系统的搭建和测试。
三、实验环境1. 操作系统:Windows 102. 编程语言:Python3. 依赖库:OpenCV、dlib、scikit-learn4. 数据集:LFW(Labeled Faces in the Wild)人脸数据集四、实验步骤1. 数据集准备从LFW数据集中选取一定数量的人脸图像,并将其分为训练集和测试集。
其中,训练集用于训练人脸识别模型,测试集用于评估模型性能。
2. 人脸图像预处理对人脸图像进行预处理,包括人脸检测、图像归一化、特征点定位等步骤。
具体操作如下:- 使用OpenCV库中的Haar特征分类器进行人脸检测,提取人脸图像。
- 将检测到的人脸图像进行归一化处理,使图像尺寸统一。
- 使用dlib库进行特征点定位,提取人脸关键点信息。
3. 特征提取采用多种特征提取方法,包括HOG(Histogram of Oriented Gradients)、LBP(Local Binary Patterns)、Eigenfaces等。
将提取到的特征向量存储到训练集中。
4. 分类器选择与训练选择支持向量机(SVM)作为分类器,利用训练集对SVM进行训练。
通过调整参数,优化模型性能。
5. 模型评估使用测试集对训练好的模型进行评估,计算识别准确率、召回率、F1值等指标。
6. 实验结果分析分析不同特征提取方法和分类器的性能,找出最优方案。
五、实验结果1. 特征提取方法比较通过对比HOG、LBP和Eigenfaces三种特征提取方法的性能,发现HOG和LBP在人脸识别任务中表现较好。
树莓派上使用OpenCV和Python实现实时人脸检测

树莓派上使用OpenCV和Python实现实时人脸检测本文介绍了如何在树莓派上,使用 OpenCV 和 Python 完成人脸检测项目。
该项目不仅描述了识别人脸所需要的具体步骤,同时还提供了很多扩展知识。
此外,该项目并不需要读者了解详细的人脸识别理论知识,因此初学者也能轻松跟着步骤实现。
项目所需设备硬件:树莓派 3 Model B;树莓派摄像头模块(PiCam)。
语言和库:OpenCVPython 3步骤本文主要讲述如何使用 PiCam 实现实时人脸识别,如下图所示:本教程使用 OpenCV 完成,一个神奇的「开源计算机视觉库」,并主要关注树莓派(因此,操作系统是树莓派系统)和 Python,但是我也在 Mac 电脑上测试了代码,同样运行很好。
OpenCV 具备很强的计算效率,且专门用于实时应用。
因此,它非常适合使用摄像头的实时人脸识别。
要创建完整的人脸识别项目,我们必须完成3个阶段:1)人脸检测和数据收集;2)训练识别器;3)人脸识别。
如下图所示:第1步:材料清单主件:树莓派 V3:283 RMB(淘宝)500 万像素1080p 传感器OV5647 迷你摄像头模块:83 RMB (淘宝)第2步:安装OpenCV 3包我使用的是更新了最新版树莓派系统(Stretch)的树莓派V3,因此安装 OpenCV 的最佳方式是按照 Adrian Rosebrock 写的教程来进行:《Raspbian Stretch: Install OpenCV 3 + Python on your Raspberry Pi》。
经过几次尝试后,我觉得Adrian的教程最好,建议按照该教程一步步来安装。
完成上述教程之后,你应该安装好了 OpenCV 虚拟环境,可用于在树莓派设备上运行本次实验。
我们来到虚拟环境,确认 OpenCV 3 已经正确安装。
Adrian 推荐在每次打开新的终端时都运行命令行「source」,以确保系统变量都得到正确设置。
opencv人脸识别中train()函数训练数据的原理

opencv人脸识别中train()函数训练数据的原理OpenCV是一种通用计算机视觉库,可以用于各种用途,例如人脸识别。
该技术利用机器学习算法从图像中提取数据并识别人脸。
train()函数是OpenCV库中用于训练人脸识别数据的关键函数。
以下是train()函数训练数据的原理:1. 准备训练样本数据train()函数需要一组训练图像来训练分类器。
这些图像必须包含不同人的正面面部照片。
对于每个图像,需要确定哪个区域包含人脸区域。
可以通过手动标记或使用其他算法进行自动检测。
2. 准备标签为了训练分类器,每个训练图像都需要一个与之对应的标签。
标签是具有唯一标识符的方式,以便将其与训练图像相关联。
标识符可以是数字或字符串,应对每个类分别进行指定。
3. 训练分类器一旦准备完毕,可以使用train()函数将训练数据提供给分类器进行学习。
在这个过程中,算法将分析训练数据并学习如何将它们分类。
这一过程可能需要一段时间,并且具体时间会受到训练数据集的大小和复杂度的影响。
4. 存储分类器学习完成后,分类器可以用于识别新图像中的人脸。
为了确保在之后有效地使用分类器,需要将其保存在硬盘上。
可以使用OpenCV提供的其他函数,例如 save(),将分类器保存在指定位置。
总结:train()函数是OpenCV中的一个重要函数,用于训练人脸识别数据。
在这个过程中,需要准备训练图像、标识标签,并使用train()函数将它们提供给分类器进行学习。
分类器通过分析训练集中的数据模式来学习如何将它们分类。
最后,保存分类器以备后用。
这个过程可以直观地理解为人脑中的“学习”过程,大量的样本数据被提供到大脑神经元中,神经元进行分析训练数据,学习数据模式,识别人脸的过程便是一个类似于人脑学习的过程。
Python基于OpenCV库Adaboost实现人脸识别功能详解

Python基于OpenCV库Adaboost实现⼈脸识别功能详解本⽂实例讲述了Python基于OpenCV库Adaboost实现⼈脸识别功能。
分享给⼤家供⼤家参考,具体如下:以前⽤Matlab写神经⽹络的⾯部眼镜识别算法,研究算法逻辑,采集⼤量训练数据,迭代,计算各感知器的系数。
相当之⿇烦~⽽现在运⽤调⽤pythonOpenCV库Adaboost算法,⽆需知道算法逻辑,⽆需进⾏模型训练,⼈脸识别变得相当之简单了。
需要⽤到的库是opencv(open source computer vision),下载安装⽅式如下:使⽤pip install numpy语句安装numpy(如果出现错误:Microsoft Visual C++ 9.0 is required <unable to find vcvarsall.bat>,使⽤管理员⾝份安装Microsoft Visual C++ 9.0,重新启动计算机,再使⽤使⽤pip install numpy语句安装numpyopencv2.4.10下载之后解压(随便解压到哪⾥),将解压⽬录opencv⽂件夹中,build->python->2.7->x86下的⽂件cv2.pyd 复制到python2.7\Lib\site-packages 中测试是否安装成功,执⾏解压⽬录下的sources\samples\python\drawing.py或者进⼊python环境,使⽤import cv2⾸先讲讲需要⽤到的新函数:CascadeClassifier()函数,导⼊分类器cv2.CascadeClassifier('xxxxx.xml')#haarcascade_frontalface_alt.xml脸部识别⽂件#haarcascade_eye.xml眼部识别⽂件函数的参数是xml完整路径(具体看你的opencv安装在哪⾥的,在opencv\sources\data\haarcascades下⾯),xml⽂件中是封装好的算法detectMultiScale()函数,进⾏识别detectMultiScale(image,scaleFactor,minNeighbors,flags,minSize,maxSize)最终返回值为识别出的矩阵框[x, y, w, h],(x,y)左上⾓起始坐标,w宽,h⾼image:⽤于检测的图像scaleFactor:前后两次相继的扫描中,搜索窗⼝的⽐例系数.例如1.1指将搜索窗⼝依次扩⼤10%。
使用OpenCV和Python进行人脸识别

使⽤OpenCV和Python进⾏⼈脸识别介绍 ⼈脸识别是什么?或识别是什么?当你看到⼀个苹果时,你的⼤脑会⽴刻告诉你这是⼀个苹果。
在这个过程中,你的⼤脑告诉你这是⼀个苹果⽔果,⽤简单的语⾔来说就是识别。
那么什么是⼈脸识别呢?我肯定你猜对了。
当你看着你的朋友⾛在街上或他的照⽚时,你会认出他是你的朋友保罗。
有趣的是,当你看你的朋友或他的照⽚时,你⾸先要看他的脸,然后再看其他东西。
你想过为什么要这么做吗?这是为了让你看他的脸就能认出他来。
好吧,这是你的⾯部识别。
但真正的问题是⼈脸识别是如何⼯作的?它⾮常简单和直观。
举⼀个现实⽣活中的例⼦,当你在⽣活中第⼀次遇见⼀个⼈,你不认识他,对吧?当他和你说话或握⼿时,你看着他的脸、眼睛、⿐⼦、嘴巴、颜⾊和整体的表情。
这是你通过收集⾯部数据来学习或训练那个⼈的⾯部识别。
然后他告诉你他叫保罗。
此时,你的⼤脑知道它刚刚学到的⾯部数据属于保罗。
现在你的头脑已经训练好了,准备在保罗的脸上做⾯部识别。
下次当你在照⽚中看到保罗或他的脸时,你会⽴刻认出他。
这就是⼈脸识别的⼯作原理。
你遇到保罗的次数越多,你的⼤脑就会收集到更多关于他的信息,尤其是他的脸,你就越能识别他。
下⼀个问题是如何⽤OpenCV编码⼈脸识别,毕竟这是你阅读这篇⽂章的唯⼀原因,对吧?那么,好吧。
你可能会说我们的⼤脑可以很容易地做这些事情,但是把它们编码到电脑⾥是很困难的吗?别担⼼,不是的。
多亏了OpenCV,编码⼈脸识别变得越来越容易。
⼈脸识别的编码步骤与我们在上⾯的实际⽰例中讨论的⼀样。
·训练数据收集:收集您想要识别的⼈的⾯部数据(本例中为⾯部图像) ·识别器的训练:将⼈脸数据(以及每个⼈脸的相应名称)输⼊⼈脸识别器,使其能够学习。
·识别:输⼊这些⼈的新⾯孔,看看你刚训练过的⼈脸识别器是否识别他们OpenCV带有内置的⼈脸识别器,你所要做的就是给它输⼊⼈脸数据。
这很简单,⼀旦我们完成了编码,它就会看起来很简单。
使用OpenCV内置深度学习人脸模块,几行代码轻松完成人脸检测和识别

使⽤OpenCV内置深度学习⼈脸模块,⼏⾏代码轻松完成⼈脸检测和识别作者:冯远滔(OpenCV China),王成瑞(北京邮电⼤学),钟瑶瑶(北京邮电⼤学)最新发布的OpenCV 4.5.4版本收录了⼀个基于深度学习神经⽹络的⼈脸模块(以下称“OpenCV DNN Face”),包括⼈脸检测(使⽤模型YuNet,由OpenCV China团队贡献)和⼈脸识别(使⽤模型SFace,由北京邮电⼤学邓伟洪教授课题组贡献)。
使⽤OpenCV DNN Face的API,只需⼏⾏代码便可以完成整个⼈脸检测和⼈脸识别处理,极⼤的⽅便了开发。
# ⼈脸检测img = cv.imread('path/to/image')faceDetector = cv.FaceDetectorYN.create('/path/to/model', '', img.shape[:2])faces = faceDetector.detect(image)# ⼈脸识别recognizer = cv.FaceRecognizerSF.create(recog_model_path, '' )aligned_face = recognizer.alignCrop(img, faces[1][0])feature = recognizer.feature(aligned_face)cosine_score = recognizer.match(feature1, feature2, 0)在相应的数据集上对OpenCV DNN Face的两个模型分别进⾏测试:⼈脸检测模型YuNet在WIDER Face数据集的验证集中达到了0.856(AP_easy),0.842(AP_medium),0.727(AP_hard);⼈脸识别模型SFace在LFW数据集上达到了99.60%的准确率(https:///master/d0/dd4/tutorial_dnn_face.html中有更详细的测试结果,以及此⼈脸模块的⼀些使⽤说明)。
Opencv摄像头实时人脸识别

Opencv摄像头实时人脸识别Introduction网上存在很多人脸识别的文章,这篇文章是我的一个作业,重在通过摄像头实时采集人脸信息,进行人脸检测和人脸识别,并将识别结果显示在左上角。
利用OpenCV 实现一个实时的人脸识别系统,人脸库采用ORL FaceDatabase (网上下载) ,另外在数据库中增加了作业中自带的20张照片和自己利用摄像头采集到的10张照片,系统利用摄像头实时的采集到场景图像,从中检测出人脸用方框标出,并利用提供的数据库进行人脸识别,并在图像左上角显示相匹配的数据库图片。
Method算法流程分两步,分别是人脸检测和人脸识别。
人脸检测使用的是ViolaJones 人脸检测方法,利用样本的Haar-like 特征进行分类器训练,得到级联boosted 分类器,加载训练好的人脸分类器,利用分类器在视频帧中查找人脸区域;人脸识别利用了局部二进制模式直方图。
Haar-like 特征Haar-like 特征如下图所示图1 Haar-like 特征LBPH人脸识别常用的方法有三种,Eigenfaces、Fisherfaces 和LBPH;对于高维的图像空间,我们首先应该进行降维操作。
LBP 不把图像看做高维的矢量,而是通过物体的局部特征来描述。
将每个像素和其相邻像素对比形成局部的结构,把该像素看做中心,并以该值对邻接像素做阈值处理,如果临界像素的亮度大于该像素则为1 否则为0,这样每个像素点都可以用一个二进制数来表示,比如一个使用3*3 临界点的LBP 操作如下图所示:图2 LBPImplementation识别训练利用准备好的数据库进行识别训练:首先我们利用Opencv 安装文件中的python脚本create_csv.py建立CSV文件,文件中每条记录如:orl/s13/2.pgm;12,分号之前是图片所存路径,而分号之后是图片的标签号,每一组图片对应着唯一的标签号;之后利用代码中的train_data和read_csv函数对数据集进行训练。
OpenCV人脸检测(级联分类器)

OpenCV⼈脸检测(级联分类器)运⾏环境visual studio 2017(2019也可)opencv3.4(410也可)xml⽂件从OpenCV⽬录⾥找C:\OpenCV4.0\opencv\sources\data\haarcascades这⾥也有其它⽬标检测的xml⽂件,有空可以⼀试为⽅便拷贝出来放在代码⼯程的debug⽬录代码代码从OpenCV提供的sample提取,稍微改⼀改C:\OpenCV4.0\opencv\sources\samples\cpp\facedetect.cpp这⾥⾯其它sample也值得⼀学#include "opencv2/objdetect.hpp"#include "opencv2/highgui.hpp"#include "opencv2/imgproc.hpp"#include <iostream>using namespace std;using namespace cv;static void help(){cout << "\nThis program demonstrates the use of cv::CascadeClassifier class to detect objects (Face + eyes). You can use Haar or LBP features.\n""This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained.\n""It's most known use is for faces.\n""Usage:\n""./facedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]\n"" [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]\n"" [--scale=<image scale greater or equal to 1, try 1.3 for example>]\n"" [--try-flip]\n"" [filename|camera_index]\n\n""see facedetect.cmd for one call:\n""./facedetect --cascade=\"data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"data/haarcascades/haarcascade_eye_tree_eyeglasses.xml\" --scale=1.3\n\n" "During execution:\n\tHit any key to quit.\n""\tUsing OpenCV version " << CV_VERSION << "\n" << endl;}void detectAndDraw(Mat& img, CascadeClassifier& cascade,CascadeClassifier& nestedCascade,double scale, bool tryflip);string cascadeName;string nestedCascadeName;int main(int argc, const char** argv){VideoCapture capture;Mat frame, image;string inputName;bool tryflip;CascadeClassifier cascade, nestedCascade;double scale;cv::CommandLineParser parser(argc, argv,"{help h||}""{cascade|data/haarcascades/haarcascade_frontalface_alt.xml|}""{nested-cascade|data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|}""{scale|1|}{try-flip||}{@filename||}");if (parser.has("help")){help();return 0;}cascadeName = parser.get<string>("cascade");nestedCascadeName = parser.get<string>("nested-cascade");scale = parser.get<double>("scale");scale = 1;tryflip = parser.has("try-flip");inputName = parser.get<string>("@filename");if (!parser.check()){parser.printErrors();return 0;}if (!nestedCascade.load(samples::findFileOrKeep(nestedCascadeName)))cerr << "WARNING: Could not load classifier cascade for nested objects" << endl; if (!cascade.load(samples::findFile(cascadeName))){cerr << "ERROR: Could not load classifier cascade" << endl;help();return -1;}if (inputName.empty() || (isdigit(inputName[0]) && inputName.size() == 1)){int camera = inputName.empty() ? 0 : inputName[0] - '0';if (!capture.open(camera)){cout << "Capture from camera #" << camera << " didn't work" << endl;return 1;}}else if (!inputName.empty()){image = imread(samples::findFileOrKeep(inputName), IMREAD_COLOR);if (image.empty()){if (!capture.open(samples::findFileOrKeep(inputName))){cout << "Could not read " << inputName << endl;return 1;}}}else{image = imread(samples::findFile("lena.jpg"), IMREAD_COLOR);if (image.empty()){cout << "Couldn't read lena.jpg" << endl;return 1;}}if (capture.isOpened()){cout << "Video capturing has been started ..." << endl;for (;;){capture >> frame;if (frame.empty())break;Mat frame1 = frame.clone();detectAndDraw(frame1, cascade, nestedCascade, scale, tryflip);char c = (char)waitKey(10);if (c == 27 || c == 'q' || c == 'Q')break;}}else{cout << "Detecting face(s) in " << inputName << endl;if (!image.empty()){detectAndDraw(image, cascade, nestedCascade, scale, tryflip);waitKey(0);}else if (!inputName.empty()){/* assume it is a text file containing thelist of the image filenames to be processed - one per line */FILE* f;fopen_s(&f, inputName.c_str(), "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--;cout << "file " << buf << endl;image = imread(buf, 1);if (!image.empty()){detectAndDraw(image, cascade, nestedCascade, scale, tryflip);char c = (char)waitKey(0);if (c == 27 || c == 'q' || c == 'Q')break;}else{cerr << "Aw snap, couldn't read image " << buf << endl;}}fclose(f);}}}return 0;}void detectAndDraw(Mat& img, CascadeClassifier& cascade,CascadeClassifier& nestedCascade,double scale, bool tryflip){double t = 0;vector<Rect> faces, faces2;const static Scalar colors[] ={Scalar(255,0,0),Scalar(255,128,0),Scalar(255,255,0),Scalar(0,255,0),Scalar(0,128,255),Scalar(0,255,255),Scalar(0,0,255),Scalar(255,0,255)};Mat gray, smallImg;cvtColor(img, gray, COLOR_BGR2GRAY);double fx = 1 / scale;resize(gray, smallImg, Size(), fx, fx, INTER_LINEAR_EXACT);equalizeHist(smallImg, smallImg);t = (double)getTickCount();cascade.detectMultiScale(smallImg, faces,1.1, 2, 0//|CASCADE_FIND_BIGGEST_OBJECT//|CASCADE_DO_ROUGH_SEARCH| CASCADE_SCALE_IMAGE,Size(30, 30));if (tryflip){flip(smallImg, smallImg, 1);cascade.detectMultiScale(smallImg, faces2,1.1, 2, 0//|CASCADE_FIND_BIGGEST_OBJECT//|CASCADE_DO_ROUGH_SEARCH| CASCADE_SCALE_IMAGE,Size(30, 30));for (vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); ++r){faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height)); }}t = (double)getTickCount() - t;printf("detection time = %g ms\n", t * 1000 / getTickFrequency());for (size_t i = 0; i < faces.size(); i++){Rect r = faces[i];Mat smallImgROI;vector<Rect> nestedObjects;Point center;Scalar color = colors[i % 8];int radius;double aspect_ratio = (double)r.width / r.height;//if (0.75 < aspect_ratio && aspect_ratio < 1.3)//{// 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);// circle(img, center, radius, color, 3, 8, 0);//}//elserectangle(img, Point(cvRound(r.x*scale), cvRound(r.y*scale)),Point(cvRound((r.x + r.width - 1)*scale), cvRound((r.y + r.height - 1)*scale)),color, 3, 8, 0);if (nestedCascade.empty())continue;smallImgROI = smallImg(r);nestedCascade.detectMultiScale(smallImgROI, nestedObjects,1.1, 2, 0//|CASCADE_FIND_BIGGEST_OBJECT//|CASCADE_DO_ROUGH_SEARCH//|CASCADE_DO_CANNY_PRUNING| CASCADE_SCALE_IMAGE,Size(30, 30));for (size_t j = 0; j < nestedObjects.size(); j++){Rect nr = nestedObjects[j];center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale);center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale);radius = cvRound((nr.width + nr.height)*0.25*scale);circle(img, center, radius, color, 3, 8, 0);}}imshow("result", img);}代码编译成功后编辑⼀个bat⽂件即可,例如:XML_object_detect --cascade=./data/haarcascades/haarcascade_frontalface_alt.xml --scale=1.3 --try-flip ./img/261068.jpg pause。
利用OpenCV实现人脸检测

人脸检测程序主要完成 3 部分功能, 即加载分类器、 加载 待 检 测 图 像 以 及 检 测 并 标 示 。 本 程 序 使 用 OpenCV 中 提 供 的 “haarcascade_frontalface_alt.xml” 文件存储的目标检测分类, 用 cvLoad 函 数 载 入 后 , 进 行 强 制 类 型 转 换 。 OpenCV 中 提 供 的 用 于 检 测 图 像 中 目 标 的 函 数 是 cvHaarDetectObjects, 该 函 数 使 用 指针对某目标物体 (如人脸) 训练的级联分类器在图像中找到 包含目标物体的矩形区域, 并将这些区域作为一序列的矩形框 返回。 分类器在使用后需要被显式释放, 所用的函数为 cvReleaseHaarClassifierCascade, 这 些 函 数 原 型 请 参 看 有 关 OpenCV 手册。 2.2 程序实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
info.dat
bg.txt
正样本描述文件info.dat的内容如下:
Positive/imag1.bmp 1 0 0 24 28
……
Positive/imag5.bmp 1 0 0 24 28
图片img1.bmp包含了单个目标对象实体,矩形为(0,0,24,28)。
负样本
负样本可以来自于任意的图片,但这些图片不能包含目标特征。负样本由背景描述文件来描述。背景描述文件是一个文本文件,每一行包含了一个负样本图片的文件名(基于描述文件的相对路径)。该文件必须手工创建。
e.g: 负样本描述文件的一个例子:
假定目录结构如下:
* !!DONE!! 3. Expand the width or height of the window by a constant number of pixels
* !!DONE!! 4. Expand the dimension (both width and height) of window by a constant scale (e.g. 0.1)
用来训练每一个分类器阶段的正/负样本。合理的值是:nPos = 7000;nNeg = 3000
-nstages<number_of_stages>
训练的阶段数。
-nsplits<number_of_splits>
决定用于阶段分类器的弱分类器。如果1,则一个简单的stump classifier被使用。如果是2或者更多,则带有number_of_splits个内部节点的CART分类器被使用。
* !!DONE!! 5. Move the window to left, right, up, and down
*/
#include "stdafx.h"
#ifdef WIN32
//#include "stdafx.h"
#include <io.h>
#else
#include <sys/types.h>
cd e:\face\bin
CreateSamples -vec e:\face\a.vec
-info e:\face\info.dat
-bg e:\face\bg.txt
-num 5
-show
-w 24
-h 28
其中e:\face\bin目录包含了createsamples可执行程序,生成的正样本文件a.vec在e:\face目录下。
-maxangle<max_y_rotation_angle>,
-maxzangle<max_x_rotation_angle>
最大旋转角度,以弧度为单位。
-show
如果指定,每个样本会被显示出来,按下"esc"会关闭这一开关,即不显示样本图片,而创建过程继续。这是个有用的debug选项。
/img
img1.jpg
img2.jpg
bg.txt
则背景描述文件bg.txt的内容为:
img/img1.jpg
img/img2.jpg
正样本
正样本由程序craatesample程序来创建。该程序的源代码由OpenCV给出,并且在bin目录下包含了这个可执行的程序。
-w《sample_width》
-h《sample_height》
训练样本的尺寸,(以像素为单位)。必须和训练样本创建的尺寸相同。
一个训练分类器的例子:
同上例,分类器训练的过程用一个批处理文件run2.bat来完成:
cd e:\face\bin
haartraining -data e:\face\data
-mem<memory_in_MB>
预先计算的以MB为单位的可用内存。内存越大则训练的速度越快。
-sym(default)
-nonsym
指定训练的目标对象是否垂直对称。垂直对称提高目标的训练速度。例如,正面部是垂直对称的。
-minhitrate《min_hit_rate》
源目标图片(例如:一个公司图标)
-bg<background_file_name>
背景描述文件。
-num<number_of_samples>
要产生的正样本的数量,和正样本图片数目相同。
-bgcolor<background_color>
注意:要从图片集中创建正样本,要用-info参数name>
标记特征的图片集合的描述文件。
背景(负样本)描述文件的内容如下:
nagative/bg1.bmp
nagative/bg2.bmp
我们用一个批处理文件run.bat来进行正样本的创建:该文件的内容如下:
正样本可以由单个的目标图片或者一系列的事先标记好的图片来创建。
Createsamples程序的命令行参数:
命令行参数:
-vec <vec_file_name>
训练好的正样本的输出文件名。
-img<image_file_name>
三、训练分类器
样本创建之后,接下来要训练分类器,这个过程是由haartraining程序来实现的。该程序源码由OpenCV自带,且可执行程序在OpenCV安装目录的bin目录下。
Haartraining的命令行参数如下:
-data<dir_name>
存放训练好的分类器的路径名。
-vec e:\face\a.vec
-bg e:\face\bg.txt
-npos 5
-nneg 2
-w 24
-h 28
训练结束后,会在目录data下生成一些子目录,即为训练好的分类器。
注:OpenCv 的某些版本可以将这些目录中的分类器直接转换成xml文件。但在实际的操作中,haartraining程序却好像永远不会停止,而且没有生成xml文件,后来在OpenCV的yahoo论坛上找到一个haarconv的程序,才将分类器转换为xml文件,其中的原因尚待研究。
-w<sample_width>
输出样本的宽度(以像素为单位)
-h《sample_height》
输出样本的高度,以像素为单位。
注:正样本也可以从一个预先标记好的图像集合中获取。这个集合由一个文本文件来描述,类似于背景描述文件。每一个文本行对应一个图片。每行的第一个元素是图片文件名,第二个元素是对象实体的个数。后面紧跟着的是与之匹配的矩形框(x, y, 宽度,高度)。
-weighttrimming<weight_trimming>
指定是否使用权修正和使用多大的权修正。一个基本的选择是0.9
-eqw
-mode<basic(default)|core|all>
选择用来训练的haar特征集的种类。basic仅仅使用垂直特征。all使用垂直和45度角旋转特征。
每个阶段分类器需要的最小的命中率。总的命中率为min_hit_rate的number_of_stages次方。
-maxfalsealarm<max_false_alarm_rate>
没有阶段分类器的最大错误报警率。总的错误警告率为max_false_alarm_rate的number_of_stages次方。
OpenCV训练分类器
一、简介
目标检测方法最初由Paul Viola [Viola01]提出,并由Rainer Lienhart [Lienhart02]对这一方法进行了改善。该方法的基本步骤为: 首先,利用样本(大约几百幅样本图片)的 harr 特征进行分类器训练,得到一个级联的boosted分类器。
下面是一个创建样本的例子:
假定我们要进行人脸的检测,有5个正样本图片文件img1.bmp,…img5.bmp;有2个背景图片文件:bg1.bmp,bg2.bmp,文件目录结构如下:
positive
img1.bmp
……
Img5.bmp
negative
bg1.bmp
分类器中的"级联"是指最终的分类器是由几个简单分类器级联组成。在图像检测中,被检窗口依次通过每一级分类器, 这样在前面几层的检测中大部分的候选区域就被排除了,全部通过每一级分类器检测的区域即为目标区域。
分类器训练完以后,就可以应用于输入图像中的感兴趣区域(与训练样本相同的尺寸)的检测。检测到目标区域(汽车或人脸)分类器输出为1,否则输出为0。为了检测整副图像,可以在图像中移动搜索窗口,检测每一个位置来确定可能的目标。为了搜索不同大小的目标物体,分类器被设计为可以进行尺寸改变,这样比改变待检图像的尺寸大小更为有效。所以,为了在图像中检测未知大小的目标物体,扫描程序通常需要用不同比例大小的搜索窗口对图片进行几次扫描。
根据上面的分析,目标检测分为三个步骤:
1、 样本的创建
2、 训练分类器
3、 利用训练好的分类器进行目标检测。
二、样本创建
训练样本分为正例样本和反例样本,其中正例样本是指待检目标样本(例如人脸或汽车等),反例样本指其它任意图片,所有的样本图片都被归一化为同样的尺寸大小(例如,20x20)。
-vec<vec_file_name>
正样本文件名(由trainingssamples程序或者由其他的方法创建的)
-bg<background_file_name>
背景描述文件。