脸部识别实现(vs2013+opencv3.0)
第一种实现
这种是通过研究源码 更改而来,第二种是第一种的简化,代码少了很多,而且逻辑比较清楚;具体的实现在代码里面有注释,虽然是英文的,还是比较简单,需要注意的一个api就是:cascade.detectMultiScale()
-
cascade.detectMultiScale()理解:
#include "opencv2/objdetect.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/core/utility.hpp" #include "opencv2/videoio/videoio_c.h" #include "opencv2/highgui/highgui_c.h" #include <cctype> #include <iostream> #include <iterator> #include <stdio.h> using namespace std; using namespace cv; void detectAndDraw(Mat& img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale, bool tryflip); //要使用到的两个cascade文件,用于联合检测人脸,opencv自带了多个xml文件,在opencv安装目录下的/source/data/haarcascades/ 文件夹内 string cascadeName = "D:\\opencv\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml"; //D:\opencv\opencv\sources\data\haarcascades string nestedCascadeName = "D:\\opencv\\opencv\\sources\\data\\haarcascades\\haarcascade_eye_tree_eyeglasses.xml";//检测眼睛 int main() { CvCapture* capture = 0; Mat frame, frameCopy, image; CascadeClassifier cascade, nestedCascade;//D:\\code\\opencv\\face\\face\\face\\2.jpg char *srcImageFile = "D:\\code\\opencv\\face\\face\\face\\2.jpg";//测试图片 double scale = 1.3; if (!cascade.load(cascadeName))//载入cascade文件 { cerr << "ERROR: Could not load classifier cascade" << endl; return -1; } cv::VideoCapture camera(CV_CAP_ANY); if (!camera.isOpened()) return -1; // 得到帧率 double rate = camera.get(CV_CAP_PROP_FPS); cvNamedWindow("result", 1); while (true) { if (!camera.read(image)) break; detectAndDraw(image, cascade, nestedCascade, scale, 0);//检测人脸 int c = waitKey(20); if ((char)c == 27)break; } //以下部分为实现加载图片然后检测 //image = imread(srcImageFile); //cout << "In image read" << endl; //if (!image.empty()) //{ // detectAndDraw(image, cascade, nestedCascade, scale, 0);//检测人脸 // waitKey(0); //} cvDestroyWindow("result"); camera.release(); return 0; } void detectAndDraw(Mat& img, CascadeClassifier& cascade,CascadeClassifier& nestedCascade,double scale, bool tryflip) { int i = 0; double t = 0; vector<Rect> faces, faces2; const static Scalar colors[] = { CV_RGB(0, 0, 255), CV_RGB(0, 128, 255), CV_RGB(0, 255, 255), CV_RGB(0, 255, 0), CV_RGB(255, 128, 0), CV_RGB(255, 255, 0), CV_RGB(255, 0, 0), CV_RGB(255, 0, 255) };//用于画线 Mat gray, smallImg(cvRound(img.rows / scale), cvRound(img.cols / scale), CV_8UC1); cvtColor(img, gray, COLOR_BGR2GRAY); resize(gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR); equalizeHist(smallImg, smallImg); t = (double)cvGetTickCount(); 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)cvGetTickCount() - t; printf("detection time = %g ms\n", t / ((double)cvGetTickFrequency()*1000.)); for (vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, 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); } else rectangle(img, cvPoint(cvRound(r->x*scale), cvRound(r->y*scale)), cvPoint(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_PRUNIN | CASCADE_SCALE_IMAGE , Size(30, 30)); for (vector<Rect>::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++) { 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); } } cv::imshow("result", img); }
第二种实现形式
#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
void detectAndDisplay(Mat frame);
String face_cascade_name = "D://opencv//opencv//sources//data//haarcascades//haarcascade_frontalface_alt.xml";
String eyes_cascade_name = "D://opencv//opencv//sources//data//haarcascades//haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
String window_name = "Capture - Face detection";
int main(void)
{
VideoCapture capture;
Mat frame;
if (!face_cascade.load(face_cascade_name)){ printf("--(!) Error loading face casecade\n"); return -1; }
if (!eyes_cascade.load(eyes_cascade_name)){ printf("--(!) Error loading eyes cascade\n"); return -1;}
//cv::VideoCapture camera(CV_CAP_ANY);
//if (!camera.isOpened())
// return -1;
//open the capture ;and pay attation the CV_CAP_ANY,when you input 0.it' failed ,it appears the device parm is not 0,it convient input CV_CAP_ANY;
capture.open(CV_CAP_ANY);
if (!capture.isOpened()){printf("-- Error opening video capture \n");return -1;}
//capture read the frame;
while (capture.read(frame))
{
if (frame.empty()){printf(" -- (!)Error No Capture frame --break"); break;}
detectAndDisplay(frame);
int c = waitKey(20);
if ((char)c == 27){ break; }
}
return 0;
}
void detectAndDisplay(Mat frame)
{
std::vector<Rect> faces;
Mat frame_gray;
//convert to gray image,and equailzehist
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
//detect face
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
for (size_t i = 0; i < faces.size(); i++)
{
//gain the face center coordinate
Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
ellipse(frame, center, Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, Scalar(255, 0, 255), 2, 8, 0);
Mat faceROI = frame_gray(faces[i]);
std::vector<Rect> eyes;
eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
for (size_t j = 0; j < eyes.size(); j++)
{
Point eye_center(faces[i].x + eyes[j].x + eyes[j].width / 2, faces[i].y + eyes[j].y + eyes[j].height / 2);
int radius = cvRound((eyes[j].width + eyes[j].height)*0.25);
circle(frame, eye_center, radius, Scalar(255, 0, 0), 4, 8, 0);
}
}
imshow(window_name, frame);
}