臉部識別實現(xiàn)(vs2013+opencv3.0)
第一種實現(xiàn)
這種是通過研究源碼 更改而來,第二種是第一種的簡化,代碼少了很多,而且邏輯比較清楚;具體的實現(xiàn)在代碼里面有注釋,雖然是英文的,還是比較簡單,需要注意的一個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文件,用于聯(lián)合檢測人臉,opencv自帶了多個xml文件,在opencv安裝目錄下的/source/data/haarcascades/ 文件夾內(nèi) 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; } //以下部分為實現(xiàn)加載圖片然后檢測 //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); }
第二種實現(xiàn)形式
#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);
}