还记的这篇OpenCV即时上手可学习可商用的项目
接下来准备把其中的代码公开,欢迎一起交流学习
人脸识别是个说小不小的工程,在完成这个项目之前,先把人脸检测熟悉一下。人脸检测用到的函数如下:
代码语言:javascript复制 void detectMultiScale( InputArray image,
CV_OUT std::vector<Rect>& objects,
double scaleFactor = 1.1,
int minNeighbors = 3, int flags = 0,
Size minSize = Size(),
Size maxSize = Size() );
Opencv中给出了四种人脸训练模型如下:
代码语言:javascript复制1.haarcascade_frontalface_alt.xml
2.haarcascade_frontalface_alt_tree.xml
3.haarcascade_frontalface_alt2.xml
4.haarcascade_frontalface_default.xml
图片中的人脸检测:
代码语言:javascript复制
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main(int argc,char *argv[])
{
Mat img = imread("../img/2.png");
namedWindow("display");
imshow("display", img);
/*********************************** 1.加载人脸检测器 ******************************/
// 建立级联分类器
CascadeClassifier cascade;
// 加载训练好的 人脸检测器(.xml)
//const string path = "../haarcascades/haarcascade_frontalface_alt.xml";
//还有两种模型自己检测
const string path = "../haarcascades/haarcascade_frontalface_default.xml";
//友好错误信息提示
try{
cascade.load(path);
}
catch (cv::Exception e){}
if (cascade.empty())
{
std::cerr << "脸部检测器不能加载 (";
std::cerr << path << ")!" << std::endl;
exit(1);
}
//计时
double t = 0;
t = (double)getTickCount();
/*********************************** 2.人脸检测 ******************************/
vector<Rect> faces(0);
cascade.detectMultiScale(img, faces, 1.1, 2, 0 ,Size(30,30));
cout << "detect face number is :" << faces.size() << endl;
/******************************** 3.显示人脸矩形框 ******************************/
if (faces.size() > 0)
{
for (size_t i = 0;i < faces.size();i )
{
rectangle(img, faces[i], Scalar(150, 0, 0), 3, 8, 0);
}
}
else cout << "未检测到人脸" << endl;
t = (double)getTickCount() - t; //getTickCount(): Returns the number of ticks per second.
cout << "检测人脸用时:" << t * 1000 / getTickFrequency() << "ms (不计算加载模型的时间)" << endl;
namedWindow("face_detect");
imshow("face_detect", img);
while(waitKey(0)!='k') ;
destroyWindow("display");
destroyWindow("face_detect");
return 0;
}
效果如图:
打开相机进行人脸检测:
代码语言:javascript复制#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void Pic2Gray(Mat camerFrame,Mat &gray)
{
//普通台式机3通道BGR,移动设备为4通道
if (camerFrame.channels() == 3)
{
cvtColor(camerFrame, gray, CV_BGR2GRAY);
}
else if (camerFrame.channels() == 4)
{
cvtColor(camerFrame, gray, CV_BGRA2GRAY);
}
else
gray = camerFrame;
}
int main()
{
//加载Haar或LBP对象或人脸检测器
CascadeClassifier faceDetector;
std::string faceCascadeFilename = "../haarcascades/haarcascade_frontalface_default.xml";
if ( ! faceDetector.load(faceCascadeFilename))
{
cout << "cascade load failed!n";
}
if ( ! eyes_cascade.load(faceCascadeFilename))
{
cout << "cascade load failed!n";
}
//打开摄像头
VideoCapture camera(0);
while (true)
{
Mat camerFrame;
camera >> camerFrame;
if (camerFrame.empty())
{
std::cerr << "无法获取摄像头图像" << std::endl;
getchar();
exit(1);
}
Mat displayedFrame(camerFrame.size(),CV_8UC3);
//人脸检测只试用于灰度图像
Mat gray;
Pic2Gray(camerFrame, gray);
//直方图均匀化(改善图像的对比度和亮度)
Mat equalizedImg;
equalizeHist(gray, equalizedImg);
//人脸检测用Cascade Classifier::detectMultiScale来进行人脸检测
int flags = CASCADE_FIND_BIGGEST_OBJECT|CASCADE_DO_ROUGH_SEARCH; //只检测脸最大的人
//int flags = CASCADE_SCALE_IMAGE; //检测多个人
Size minFeatureSize(30, 30);
float searchScaleFactor = 1.1f;
int minNeighbors = 4;
std::vector<Rect> faces;
faceDetector.detectMultiScale(equalizedImg, faces, searchScaleFactor, minNeighbors, flags, minFeatureSize);
//画矩形框
cv::Mat face;
cv::Point text_lb;
for (size_t i = 0; i < faces.size(); i )
{
if (faces[i].height > 0 && faces[i].width > 0)
{
cv::rectangle(equalizedImg, faces[i], cv::Scalar(255, 0, 0), 1, 8, 0);
cv::rectangle(gray, faces[i], cv::Scalar(255, 0, 0), 1, 8, 0);
cv::rectangle(camerFrame, faces[i], cv::Scalar(0, 255, 0), 1, 8, 0);
}
}
imshow("junyihua", equalizedImg);
imshow("huidu", gray);
imshow("yuantu", camerFrame);
waitKey(20);
}
getchar();
return 0;
}
效果如下:
涉及到个人隐私,还是不贴图了巴拉巴拉
另外补充人脸 眼睛检测:
代码语言:javascript复制#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <stdio.h>
using namespace std;
using namespace cv;
/** Function Headers */
void detectAndDisplay(Mat frame);
/** Global variables */
String face_cascade_name, eyes_cascade_name;
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
String window_name = "Capture - Face detection";
/** @function main */
int main(int argc, const char** argv)
{
face_cascade_name = "../haarcascades/haarcascade_frontalface_default.xml";
eyes_cascade_name = "../haarcascades/haarcascade_eye_tree_eyeglasses.xml";
VideoCapture capture;
Mat frame;
//-- 1. Load the cascades
if (!face_cascade.load(face_cascade_name)) { printf("--(!)Error loading face cascaden"); return -1; };
if (!eyes_cascade.load(eyes_cascade_name)) { printf("--(!)Error loading eyes cascaden"); return -1; };
//-- 2. Read the video stream
capture.open(0); //打开摄像头
if (!capture.isOpened()) { printf("--(!)Error opening video capturen"); return -1; }
while (capture.read(frame)) //读取帧
{
if (frame.empty())
{
printf(" --(!) No captured frame -- Break!");
break;
}
//-- 3. Apply the classifier to the frame
detectAndDisplay(frame);
if (waitKey(10) == 'k') { break; } // escape
}
return 0;
}
/** @function detectAndDisplay */
void detectAndDisplay(Mat frame)
{
std::vector<Rect> faces;
Mat frame_gray;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY); //BGR 转化为灰度图
equalizeHist(frame_gray, frame_gray); //直方图均衡化
//-- Detect faces
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(60, 60));
for (size_t i = 0; i < faces.size(); i )
{
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), 4, 8, 0); // 椭圆
Mat faceROI = frame_gray(faces[i]);
std::vector<Rect> eyes;
//-- In each face, detect 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);
}
}
//-- Show what you got
imshow(window_name, frame);
}