- 浏览: 960759 次
文章分类
最新评论
-
l67721363:
感谢分享,要是有各个函数性能比较就好了。
SQL优化 数据库优化 -
hanmiao:
此图片来自QQ空间,未经允许不可引用。
Hacking QQ空间
基于OpenCV读取摄像头进行人脸检测和人脸识别
前段时间使用OpenCV的库函数实现了人脸检测和人脸识别,笔者的实验环境为VS2010+OpenCV2.4.4,OpenCV的环境配置网上有很多,不再赘述。检测的代码网上很多,记不清楚从哪儿copy的了,识别的代码是从OpenCV官网上找到的:http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_api.html
需要注意的是,opencv的FaceRecogizer目前有三个类实现了它,特征脸和fisherface方法最少训练图像为两张,而LBP可以单张图像训练。本人的实验采用的图片是100x100大小的,所以如果要添加自己的图像进行识别的话务必调整为100x100,不然会报错。当然在recog_and_draw这个函数里,笔者也将每次检测到的人脸进行了保存,拖出来重命名就可以,路径自己找吧。使用不同的方法识别时,其阈值设置也不同,LBP大概在100,其他两种方法大概在1000。本人的代码已共享,下载链接:http://download.csdn.net/detail/u010944555/6749725
ps:有人说代码的检测率不高,其实可以归结为两方面的原因,第一人脸检测率不高,这个可以通过嵌套检测嘴角、眼睛等来降低,或者背景、光照固定的话可以通过图像差分来解决;第二是识别方法本身的问题,如果想提高识别率,可以添加多张不同姿态、光照下的人脸作为训练的样本,如果有时间的话可以在采集图像时给出一个人脸框,引导用户对齐人脸进行采集,三星手机解除锁屏就有这么一个功能。
效果图:
废话不多说,上传代码。
main:
#include "stdafx.h" #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> #include <opencv2\contrib\contrib.hpp> #include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #include <iostream> #include <fstream> #include <sstream> #include "detect_recog.h" using namespace std; using namespace cv; #ifdef _EiC #define WIN32 #endif CvMemStorage* storage = 0; CvHaarClassifierCascade* cascade = 0; CvHaarClassifierCascade* nested_cascade = 0; int use_nested_cascade = 0; const char* cascade_name = "./data/haarcascade_frontalface_alt.xml";//别人已经训练好的人脸检测xml数据 const char* nested_cascade_name = "./data/haarcascade_eye_tree_eyeglasses.xml"; CvCapture* capture = 0; IplImage *frame, *frame_copy = 0; IplImage *image = 0; const char* scale_opt = "--scale="; // 分类器选项指示符号 int scale_opt_len = (int)strlen(scale_opt); const char* cascade_opt = "--cascade="; int cascade_opt_len = (int)strlen(cascade_opt); const char* nested_cascade_opt = "--nested-cascade"; int nested_cascade_opt_len = (int)strlen(nested_cascade_opt); double scale = 1; int num_components = 9; double facethreshold = 9.0; //opencv的FaceRecogizer目前有三个类实现了他,特征脸和fisherface方法最少训练图像为两张,而LBP可以单张图像训练 //cv::Ptr<cv::FaceRecognizer> model = cv::createEigenFaceRecognizer(); //cv::Ptr<cv::FaceRecognizer> model = cv::createFisherFaceRecognizer(); cv::Ptr<cv::FaceRecognizer> model = cv::createLBPHFaceRecognizer();//LBP的这个方法在单个人脸验证方面效果最好 vector<Mat> images;//两个容器images,labels来存放图像数据和对应的标签 vector<int> labels; int main( int argc, char** argv ) { cascade = (CvHaarClassifierCascade*)cvLoad(cascade_name, 0, 0, 0); //加载分类器 if(!cascade) { fprintf( stderr, "ERROR: Could not load classifier cascade\n" ); getchar(); return -1; } model->set("threshold", 2100.0); string output_folder; output_folder = string("./einfacedata"); //读取你的CSV文件路径 string fn_csv = string("./einfacedata/at.txt"); try { //通过./einfacedata/at.txt这个文件读取里面的训练图像和类别标签 read_csv(fn_csv, images, labels); } catch(cv::Exception &e) { cerr<<"Error opening file "<<fn_csv<<". Reason: "<<e.msg<<endl; exit(1); } /* //read_img这个函数直接从einfacedata/trainingdata目录下读取图像数据并默认将图像置为0 //所以如果用这个函数只能用来单个人脸验证 if(!read_img(images, labels)) { cout<< "Error in reading images!"; images.clear(); labels.clear(); return 0; } */ cout << images.size() << ":" << labels.size()<<endl; //如果没有读到足够的图片,就退出 if(images.size() <= 2) { string error_message = "This demo needs at least 2 images to work."; CV_Error(CV_StsError, error_message); } //得到第一张照片的高度,在下面对图像变形到他们原始大小时需要 //int height = images[0].rows; //移除最后一张图片,用于做测试 //Mat testSample = images[images.size() - 1]; //cv::imshow("testSample", testSample); //int testLabel = labels[labels.size() - 1]; //images.pop_back(); //labels.pop_back(); //下面创建一个特征脸模型用于人脸识别, // 通过CSV文件读取的图像和标签训练它。 //进行训练 model->train(images, labels); storage = cvCreateMemStorage(0); // 创建内存存储器 capture = cvCaptureFromCAM(0); // 创建视频读取结构 cvNamedWindow( "result", 1 ); if( capture ) // 如过是视频或摄像头采集图像,则循环处理每一帧 { for(;;) { if( !cvGrabFrame( capture )) break; frame = cvRetrieveFrame( capture ); if( !frame ) break; if( !frame_copy ) frame_copy = cvCreateImage( cvSize(640,480),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 ); // 如果调用这个函数,只是实现人脸检测 //cout << frame_copy->width << "x" << frame_copy->height << endl; recog_and_draw( frame_copy );//该函数实现人脸检测和识别 if( cvWaitKey( 100 ) >= 0 )//esc键值好像是100 goto _cleanup_; } cvWaitKey(0); _cleanup_: // 标记使用,在汇编里用过,C语言,我还没见用过 cvReleaseImage( &frame_copy ); cvReleaseCapture( &capture ); } cvDestroyWindow("result"); return 0; }
detect_recog.cpp:
#include "stdafx.h" #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> #include "detect_recog.h" #include <opencv2\contrib\contrib.hpp> #include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #include <iostream> #include <fstream> #include <sstream> #include <stdio.h> #include <io.h> #include <direct.h> using namespace std; using namespace cv; //检测并圈出人脸,并将检测到的人脸进行判断属于训练图像中的哪一类 void recog_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}} }; IplImage *gray, *small_img; int i, j; gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 ); small_img = cvCreateImage( cvSize( cvRound (img->width/scale), cvRound (img->height/scale)), 8, 1 ); cvCvtColor( img, gray, CV_BGR2GRAY ); // 彩色RGB图像转为灰度图像 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_FIND_BIGGEST_OBJECT //|CV_HAAR_DO_ROUGH_SEARCH |CV_HAAR_DO_CANNY_PRUNING //|CV_HAAR_SCALE_IMAGE , 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 ); // 将faces数据从CvSeq转为CvRect CvMat small_img_roi; CvSeq* nested_objects; CvPoint center; CvScalar color = colors[i%8]; // 使用不同颜色绘制各个face,共八种色 int radius; center.x = cvRound((r->x + r->width*0.5)*scale); // 找出faces中心 center.y = cvRound((r->y + r->height*0.5)*scale); radius = cvRound((r->width + r->height)*0.25*scale); cvGetSubRect( small_img, &small_img_roi, *r ); //截取检测到的人脸区域作为识别的图像 IplImage *result; CvRect roi; roi = *r; result = cvCreateImage( cvSize(r->width, r->height), img->depth, img->nChannels ); cvSetImageROI(img,roi); // 创建子图像 cvCopy(img,result); cvResetImageROI(img); IplImage *resizeRes; CvSize dst_cvsize; dst_cvsize.width=(int)(100); dst_cvsize.height=(int)(100); resizeRes=cvCreateImage(dst_cvsize,result->depth,result->nChannels); //检测到的区域可能不是100x100大小,所以需要插值处理到统一大小,图像的大小可以自己指定的 cvResize(result,resizeRes,CV_INTER_NN); IplImage* img1 = cvCreateImage(cvGetSize(resizeRes), IPL_DEPTH_8U, 1);//创建目标图像 cvCvtColor(resizeRes,img1,CV_BGR2GRAY);//cvCvtColor(src,des,CV_BGR2GRAY) cvShowImage( "resize", resizeRes ); cvCircle( img, center, radius, color, 3, 8, 0 ); // 从中心位置画圆,圈出脸部区域 int predictedLabel = -1; Mat test = img1; //images[images.size() - 1] = test; model->train(images, labels); //如果调用read_img函数时 chdir将默认目录做了更改,所以output.jpg自己找一下吧 imwrite("../ouput.jpg",test); //在这里对人脸进行判别 double predicted_confidence = 0.0; model->predict(test,predictedLabel,predicted_confidence); if(predictedLabel == 0) cvText(img, "yes", r->x+r->width*0.5, r->y); else cvText(img, "no", r->x+r->width*0.5, r->y); //cout << "predict:"<<model->predict(test) << endl; cout << "predict:"<< predictedLabel << "\nconfidence:" << predicted_confidence << endl; if( !nested_cascade ) continue; nested_objects = cvHaarDetectObjects( &small_img_roi, nested_cascade, storage, 1.1, 2, 0 //|CV_HAAR_FIND_BIGGEST_OBJECT //|CV_HAAR_DO_ROUGH_SEARCH //|CV_HAAR_DO_CANNY_PRUNING //|CV_HAAR_SCALE_IMAGE , cvSize(0, 0) ); for( j = 0; j < (nested_objects ? nested_objects->total : 0); j++ ) { CvRect* nr = (CvRect*)cvGetSeqElem( nested_objects, 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); cvCircle( img, center, radius, color, 3, 8, 0 ); } } } cvShowImage( "result", img ); cvReleaseImage( &gray ); cvReleaseImage( &small_img ); } void cvText(IplImage* img, const char* text, int x, int y) { CvFont font; double hscale = 1.0; double vscale = 1.0; int linewidth = 2; cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX | CV_FONT_ITALIC,hscale,vscale,0,linewidth); CvScalar textColor =cvScalar(0,255,255); CvPoint textPos =cvPoint(x, y); cvPutText(img, text, textPos, &font,textColor); } Mat norm_0_255(cv::InputArray _src) { Mat src = _src.getMat(); Mat dst; switch(src.channels()) { case 1: cv::normalize(_src, dst, 0, 255, cv::NORM_MINMAX, CV_8UC1); break; case 3: cv::normalize(_src, dst, 0, 255, cv::NORM_MINMAX, CV_8UC3); break; default: src.copyTo(dst); break; } return dst; } //读取文件中的图像数据和类别,存入images和labels这两个容器 void read_csv(const string &filename, vector<Mat> &images, vector<int> &labels, char separator) { std::ifstream file(filename.c_str(), ifstream::in); if(!file) { string error_message = "No valid input file was given."; CV_Error(CV_StsBadArg, error_message); } string line, path, classlabel; while(getline(file, line)) { stringstream liness(line); getline(liness, path, separator); //遇到分号就结束 getline(liness, classlabel); //继续从分号后面开始,遇到换行结束 if(!path.empty() && !classlabel.empty()) { images.push_back(imread(path, 0)); labels.push_back(atoi(classlabel.c_str())); } } } bool read_img(vector<Mat> &images, vector<int> &labels) { long file; struct _finddata_t find; _chdir("./einfacedata/trainingdata/"); if((file=_findfirst("*.*", &find))==-1L) { //printf("空白!/n"); return false; } //fileNum = 0; //strcpy(fileName[fileNum], find.name); int i = 0; while(_findnext(file, &find)==0) { if(i == 0) { i++; continue; } images.push_back(imread(find.name, 0)); labels.push_back(0); cout << find.name << endl; } _findclose(file); return true; } // 只是检测人脸,并将人脸圈出 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}} }; IplImage *gray, *small_img; int i, j; gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 ); small_img = cvCreateImage( cvSize( cvRound (img->width/scale), cvRound (img->height/scale)), 8, 1 ); cvCvtColor( img, gray, CV_BGR2GRAY ); // 彩色RGB图像转为灰度图像 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_FIND_BIGGEST_OBJECT //|CV_HAAR_DO_ROUGH_SEARCH |CV_HAAR_DO_CANNY_PRUNING //|CV_HAAR_SCALE_IMAGE , 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 ); // 将faces数据从CvSeq转为CvRect CvMat small_img_roi; CvSeq* nested_objects; CvPoint center; CvScalar color = colors[i%8]; // 使用不同颜色绘制各个face,共八种色 int radius; center.x = cvRound((r->x + r->width*0.5)*scale); // 找出faces中心 center.y = cvRound((r->y + r->height*0.5)*scale); radius = cvRound((r->width + r->height)*0.25*scale); cvCircle( img, center, radius, color, 3, 8, 0 ); // 从中心位置画圆,圈出脸部区域 if( !nested_cascade ) continue; cvGetSubRect( small_img, &small_img_roi, *r ); nested_objects = cvHaarDetectObjects( &small_img_roi, nested_cascade, storage, 1.1, 2, 0 //|CV_HAAR_FIND_BIGGEST_OBJECT //|CV_HAAR_DO_ROUGH_SEARCH //|CV_HAAR_DO_CANNY_PRUNING //|CV_HAAR_SCALE_IMAGE ,cvSize(0, 0) ); for( j = 0; j < (nested_objects ? nested_objects->total : 0); j++ ) { CvRect* nr = (CvRect*)cvGetSeqElem( nested_objects, 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); cvCircle( img, center, radius, color, 3, 8, 0 ); } } } cvShowImage( "result", img ); cvReleaseImage( &gray ); cvReleaseImage( &small_img ); }
detect_recog.h:
#include "stdafx.h" #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> //////////////////////////////////s/////////////////////////////////// #include <opencv2\contrib\contrib.hpp> #include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #include <iostream> #include <fstream> #include <sstream> using namespace std; using namespace cv; #ifndef DETECT_RECOG_H #define DETECT_RECOG_H extern CvMemStorage* storage; extern CvHaarClassifierCascade* cascade; extern CvHaarClassifierCascade* nested_cascade; extern int use_nested_cascade; extern const char* cascade_name; extern const char* nested_cascade_name; extern double scale; extern cv::Ptr<cv::FaceRecognizer> model; extern vector<Mat> images; extern vector<int> labels; void detect_and_draw( IplImage* img ); // 检测和绘画 void recog_and_draw( IplImage* img ); // 检测和绘画 void read_csv(const string &filename, vector<Mat> &images, vector<int> &labels, char separator = ';'); bool read_img(vector<Mat> &images, vector<int> &labels); Mat norm_0_255(cv::InputArray _src); void cvText(IplImage* img, const char* text, int x, int y); #endif
相关推荐
基于OpenCV读取摄像头的人脸检测和识别,人脸检测使用别人训练好的数据进行检测,程序可以选择特征脸、fisherface或LBP方法来实现人脸识别。
OpenCV版本3.0.0,VS版本2013,分类器xml文件可以在OpenCV官网里面自行下载
比起网上杂乱无章的OpenCV人脸识别的代码,这个代码更加简洁明了,方便初学者学习使用。 OpenCV人脸识别- 1.模板;2读取视频或者摄像头拍摄中的人脸 1.调用已经训练好的xml文件,可作为人脸检测的模板程序。 只能...
基于Opencv的实时人脸识别 1.原理介绍: 人脸检测利用opencv进行图像处理,借用keras框架搭建卷积神经网络,对图像进行特征提取与特征训练,再利用训练好的分类模型进行预测,再将预测标签实时打在每一帧图片上,实现实时...
能够实现电脑端摄像头读取视频,实时人脸录入,人脸检测,人脸识别等功能。基于python-contrib-opencv,dlib,pyqt5。能够实现电脑端摄像头读取视频,实时人脸录入,人脸检测,人脸识别等功能。基于python-contrib-...
用opencv写的人脸识别程序,从usb摄像头读取每帧图像,并且识别出图像中的正脸,程序是照着官网上写的,代码比较规范,可以作为2次开发使用
大华、海康摄像头人脸识别、抓拍资源; 支持大华、海康摄像头多路实时抓拍。也可支持其他视频流抓拍。 适用于摄像头监控及视频监控场景 实现人脸实时抓拍后用于人脸分析及识别
首先进行图片的读取,使用opencv的haar鼻子特征分类器,如果检测到鼻子,则证明没有戴口罩。如果没有检测到鼻子,接着使用opencv的haar眼睛特征分类器,如果没有检测到眼睛,则结束。如果检测到眼睛,则把RGB颜色...
人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别人脸识别...
该项目包括两个主要的Python脚本文件:face_detection_image.py和...用户可以使用这些代码作为起点,进一步探索更高级的人脸识别和跟踪技术。该项目也可以用于构建实际的人脸识别系统,例如安防系统或生物识别系统。
该人脸识别实例是一个基于深度学习和计算机视觉技术的应用,主要利用OpenCV和Python作为开发工具。系统采用了一系列算法和技术,其中包括以下几个关键步骤: 图像预处理:首先,对输入图像进行预处理,包括读取图片...
换脸,识别人脸
opencv可通过rtmp/rtsp获取视频流人脸识别与并截图,JAVA版本
c#下使用EmguCV操作摄像头和最简单的人脸检测 http://blog.csdn.net/a582127421/article/details/77745580
它读取视频流并传递给OpenCV图像处理线程进行人脸识别和打码处理。 (3)OpenCV图像处理线程:该线程利用OpenCV库进行人脸检测和打码。它从摄像头采集线程接收到的视频帧中提取人脸区域,然后将区域绘制为马赛克...
其实就是基于对人脸特征的描述,分类器根据训练的样品数据进行训练,完成后即可感知读取到的图片上的特征,进而对图片进行人脸识别。 OpenCV已在GitHub训练结果网址...
基于OpenCV的人脸识别项目demo代码,使用C++接口读取摄像头图片,打开实时预览窗口,在OpenCV扣出人脸图片,抠出的人脸在预览窗口框出来。抠出的人脸图片用base64编码并上传到百度智能云进行人脸识别,识别的结果以...
OpenCV实现人脸识别与轮廓检测,涉及图像处理的基本知识,比如打开摄像头,图像读取,Canny算子,腐蚀与膨胀等等
人脸识别主要有三个步骤: 人脸图像采集及检测 人脸图像预处理 人脸图像特征提取以及匹配与识别 以下代码实现了读取本地图像,进行人脸检测
案例-实时人脸识别应用开发(读取录入) facerecog_07录入人脸到数据库.cpp 图片人脸检测.cpp 案例-实时人脸识别应用开发2(识别) 检测图片中的人脸(多了眼部识别).cpp 录取人脸和实时识别人脸.cpp 识别指定...