要进行人脸的识别的训练,首先我们要对Openv中人脸识别类FaceRecognizer要有一个了解,http://www.cnblogs.com/guoming0000/archive/2012/09/27/2706019.html 可以参考这个博客对FaceRecognizer 有一个了解http://blog.csdn.net/u013088062/article/details/38588185 这个博客对人脸的训练解释的很好,具体怎么训练可以阅读这个博客。
关于人脸识别 我们有一下两个步骤
1.利用PCA变换的人脸识别,对人脸进行训练。
2.读取训练出的文件,并进行判别。
首先第一步是对人脸进行集中训练,训练成功后会生成一个xml文件。
下面是如何训练的代码:
#include
#include
#include
#include
#include
#include
#include
using namespace cv;
using namespace std;
using namespace face;
CascadeClassifier face_cascades;
void read_csv(const string& filename, vector & images, vector<int>& labels, char separator = ';')
{
std::ifstream file(filename.c_str(), ifstream::in);//c_str()函数可用可不用,无需返回一个标准C类型的字符串
if (!file)
{
string error_message = "No valid input file was given, please check the given filename.";
CV_Error(CV_StsBadArg, error_message);
}
string line, path, classlabel;
while (getline(file, line))//从文本文件中读取一行字符,未指定限定符默认限定符为“/n”
{
stringstream liness(line);//这里采用stringstream主要作用是做字符串的分割
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()));
}
}
}
int main()
{
char buffer[MAX_PATH];
_getcwd(buffer, MAX_PATH);
printf("The current directory is: %s ", buffer);
string fn_csv;
fn_csv = buffer;
fn_csv = fn_csv + "\\image\\at.txt";
//string fn_csv = "./image/at.txt";//读取你的CSV文件路径. 相对路径读取失败
vector images;// 2个容器来存放图像数据和对应的标签
vector<int> labels;
read_csv(fn_csv, images, labels);//从csv文件中批量读取训练数据
Ptr model = createEigenFaceRecognizer();
model->train(images, labels);
model->save("MyFaceRecognizer.xml");//保存路径
return 0;
}
训练好后就是对人脸进行识别
代码如下:
#include
#include
#include
#include
#include
using namespace cv;
using namespace std;
using namespace face;
CascadeClassifier g_face_cascades;
RNG g_rng(12345);
Ptr model;
int Predict(Mat src_image);
void detectAndDisplay(Mat frame);
int main()
{
VideoCapture capture(0);//读取视频并初始化
Mat edges;//定义一个edges的类
model = createEigenFaceRecognizer();
model->load("MyFaceRecognizer.xml");//加载分类器
g_face_cascades.load("haarcascade_frontalface_alt.xml");
while (1)
{
Mat frame;//定义一个frame的变量用来储存每帧的图像
capture >> frame;//读取当前帧
if (!frame.data)
{
cout << "未能读取图片\n";
return -1;
}
detectAndDisplay(frame);
}
return 0;
}
void detectAndDisplay(Mat frame)
{
std::vector faces; //存储人脸的矩形
Mat frame_gray;
if (frame.channels() == 1)
{
frame_gray = frame;
}
else
{
cvtColor(frame, frame_gray, CV_RGB2GRAY);
}
equalizeHist(frame_gray, frame_gray); //直方图均衡化
//detectMultiScale函数中frame_gray表示的是要检测的输入图像为frame_gray,faces表示检测到的人脸目标序列,1.1表示
//每次图像尺寸减小的比例为1.1,2表示每一个目标至少要被检测到3次才算是真的目标(因为周围的像素和不同的窗口大
//小都可以检测到人脸),CV_HAAR_SCALE_IMAGE表示不是缩放分类器来检测,而是缩放图像,Size(30, 30)为目标的
//最小最大尺寸
g_face_cascades.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
Mat* pImage_roi = new Mat[faces.size()]; //定以数组
string str;
for (int i = 0; i < faces.size(); i++)
{
pImage_roi[i]=frame_gray(faces[i]); //将所有的脸部保存起来
if (pImage_roi[i].empty())
continue;
switch (Predict(pImage_roi[i])) //每张图片进行识别
{
case 1:str = "Error"; break;
case 2:str = "GanHaoYu"; break;
case 3:str = "XuHaoRan"; break;
case 4:str = "HuangLuYao"; break;
default: str = "person"; break;
}
Scalar color = Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));//所取的颜色任意值
rectangle(frame, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height), color, 1, 8);//放入缓存
putText(frame, str, Point(faces[i].x, faces[i].y), FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255));//添加文字
}
delete []pImage_roi;
imshow("人脸识别", frame);
waitKey(30);
}
int Predict(Mat src_image) //识别图片
{
Mat edges;
// cvtColor(src_image, edges, COLOR_BGR2GRAY);//灰度
resize(src_image, edges, cv::Size(92, 122));//大小一致
return model->predict(edges);
}
这个是实现的效果
之后我将他封装成了一个类,代码就几行搞定了,方便快捷。
封装类的资料连接这里写链接内容