1.打开摄像头自动采集保存图片
void Autopic() {
VideoCapture capture(0);
Mat frame;
if (!capture.isOpened())
{
cout << "摄像头打开失败!" << endl;
return;
}
char key;
char filename[200];
int count = 0;
namedWindow("【视频】", 1);
namedWindow("【图片】", 1);
while (1)
{
key = waitKey(50);
capture >> frame;
imshow("【视频】", frame);
if (key == 27)
break;//按ESC键退出程序
if (key == 32)//按空格键进行拍照
{
sprintf_s(filename, "img/Picture %d.jpg", ++count);
imwrite(filename, frame);//图片保存到本工程目录中
imshow("【图片】", frame);
}
}
}
2.检测人脸调整图片大小为人脸识别做准备
void ResizeFace() {
CascadeClassifier faceCascade;
faceCascade.load("D:/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml"); //加载分类器,注意文件路径
for (int i = 1; i < 33; i++) {
stringstream ss;
ss << i;
Mat img = imread("img/Picture "+ss.str()+".jpg");
std::vector<Rect> faces;
Mat img_gray;
cvtColor(img, img_gray, COLOR_BGR2GRAY);
equalizeHist(img_gray, img_gray);
//-- Detect faces
//faceCascade.detectMultiScale(img_gray, faces, 1.1, 3, CV_HAAR_DO_ROUGH_SEARCH, Size(50, 50));
faceCascade.detectMultiScale(img_gray, faces, 1.2, 6, 0, Size(0, 0)); //检测人脸
for (size_t j = 0; j < faces.size(); j++)
{
Mat faceROI = img(faces[j]);
Mat MyFace;
if (faceROI.cols > 100)
{
resize(faceROI, MyFace, Size(92, 112));
string str = format("img/43/MyFcae%d.jpg", i);
imwrite(str, MyFace);
//imshow("ii", MyFace);
}
//waitKey(10);
}
}
}
3.训练模型
void trainmodel() {
//读取你的CSV文件路径.
//string fn_csv = string(argv[1]);
string fn_csv = "at.txt";
// 2个容器来存放图像数据和对应的标签
vector<Mat> images;
vector<int> labels;
// 读取数据. 如果文件不合法就会出错
// 输入的文件名已经有了.
try
{
read_csv(fn_csv, images, labels);
}
catch (cv::Exception& e)
{
cerr << "Error opening file \"" << fn_csv << "\". Reason: " << e.msg << endl;
// 文件有问题,我们啥也做不了了,退出了
exit(1);
}
// 如果没有读取到足够图片,也退出.
if (images.size() <= 1) {
string error_message = "This demo needs at least 2 images to work. Please add more images to your data set!";
CV_Error(CV_StsError, error_message);
}
// 下面的几行代码仅仅是从你的数据集中移除最后一张图片
//[gm:自然这里需要根据自己的需要修改,他这里简化了很多问题]
Mat testSample = images[images.size() - 1];
int testLabel = labels[labels.size() - 1];
images.pop_back();
labels.pop_back();
// 下面几行创建了一个特征脸模型用于人脸识别,
// 通过CSV文件读取的图像和标签训练它。
// T这里是一个完整的PCA变换
//如果你只想保留10个主成分,使用如下代码
// cv::createEigenFaceRecognizer(10);
//
// 如果你还希望使用置信度阈值来初始化,使用以下语句:
// cv::createEigenFaceRecognizer(10, 123.0);
//
// 如果你使用所有特征并且使用一个阈值,使用以下语句:
// cv::createEigenFaceRecognizer(0, 123.0);
Ptr<FaceRecognizer> model = createEigenFaceRecognizer();
model->train(images, labels);
model->save("MyFacePCAModel.xml");
Ptr<FaceRecognizer> model1 = createFisherFaceRecognizer();
model1->train(images, labels);
model1->save("MyFaceFisherModel.xml");
Ptr<FaceRecognizer> model2 = createLBPHFaceRecognizer();
model2->train(images, labels);
model2->save("MyFaceLBPHModel.xml");
// 下面对测试图像进行预测,predictedLabel是预测标签结果
int predictedLabel = model->predict(testSample);
int predictedLabel1 = model1->predict(testSample);
int predictedLabel2 = model2->predict(testSample);
// 还有一种调用方式,可以获取结果同时得到阈值:
// int predictedLabel = -1;
// double confidence = 0.0;
// model->predict(testSample, predictedLabel, confidence);
string result_message = format("Predicted class = %d / Actual class = %d.", predictedLabel, testLabel);
string result_message1 = format("Predicted class = %d / Actual class = %d.", predictedLabel1, testLabel);
string result_message2 = format("Predicted class = %d / Actual class = %d.", predictedLabel2, testLabel);
cout << result_message << endl;
cout << result_message1 << endl;
cout << result_message2 << endl;
waitKey(0);
}
需要注意的是
Ptr<FaceRecognizer> model = createEigenFaceRecognizer();
可能会报错,需要加载#include<opencv2\face.hpp> 如果没有face.hpp就需要
添加OpenCV_contrib库至OpenCV3.1.0中 具体参考 http://blog.csdn.net/liu798675179/article/details/51259505
at.txt是图片文件对应的标签内容格式如下:
可用Python自动生成上述文件代码如下:
#!/usr/bin/env python
import sys
import os.path
# This is a tiny script to help you creating a CSV file from a face
# database with a similar hierarchie:
#
# philipp@mango:~/facerec/data/at$ tree
# .
# |-- README
# |-- s1
# | |-- 1.pgm
# | |-- ...
# | |-- 10.pgm
# |-- s2
# | |-- 1.pgm
# | |-- ...
# | |-- 10.pgm
# ...
# |-- s40
# | |-- 1.pgm
# | |-- ...
# | |-- 10.pgm
#
if __name__ == "__main__":
#if len(sys.argv) != 2:
# print "usage: create_csv <base_path>"
# sys.exit(1)
#BASE_PATH=sys.argv[1]
BASE_PATH="F:/AIRobot/opencv/FaceRecognize/FaceRecognize/img/faceimg/orl_faces"
SEPARATOR=";"
fh = open("at.txt",'w')
label = 0
for dirname, dirnames, filenames in os.walk(BASE_PATH):
for subdirname in dirnames:
subject_path = os.path.join(dirname, subdirname)
for filename in os.listdir(subject_path):
abs_path = "%s/%s" % (subject_path, filename)
print ("%s%s%d" % (abs_path, SEPARATOR, label))
fh.write(abs_path)
fh.write(SEPARATOR)
fh.write(str(label))
fh.write("\n")
label = label + 1
fh.close()
4.进行预测
void testpre() {
VideoCapture cap(0); //打开默认摄像头
if (!cap.isOpened())
{
return;
}
Mat frame;
Mat edges;
Mat gray;
CascadeClassifier cascade;
bool stop = false;
//训练好的文件名称,放置在可执行文件同目录下
cascade.load("D:/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml");
Ptr<FaceRecognizer> modelPCA = createEigenFaceRecognizer();
modelPCA->load("MyFacePCAModel.xml");
while (!stop)
{
cap >> frame;
//建立用于存放人脸的向量容器
vector<Rect> faces(0);
cvtColor(frame, gray, CV_BGR2GRAY);
//改变图像大小,使用双线性差值
//resize(gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR);
//变换后的图像进行直方图均值化处理
equalizeHist(gray, gray);
cascade.detectMultiScale(gray, faces,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
| CV_HAAR_SCALE_IMAGE,
Size(30, 30));
Mat face;
Point text_lb;
for (size_t i = 0; i < faces.size(); i++)
{
if (faces[i].height > 0 && faces[i].width > 0)
{
face = gray(faces[i]);
text_lb = Point(faces[i].x, faces[i].y);
rectangle(frame, faces[i], Scalar(255, 0, 0), 1, 8, 0);
}
}
Mat face_test;
int predictPCA = 0;
if (face.rows >= 120)
{
resize(face, face_test, Size(92, 112));
}
//Mat face_test_gray;
//cvtColor(face_test, face_test_gray, CV_BGR2GRAY);
if (!face_test.empty())
{
//测试图像应该是灰度图
predictPCA = modelPCA->predict(face_test);
}
cout << predictPCA << endl;
if (predictPCA == 3)
{
string name = "Yang";
putText(frame, name, text_lb, FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255));
}
else if (predictPCA == 4)
{
string name = "Gu";
putText(frame, name, text_lb, FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255));
}
else if (predictPCA == 5)
{
string name = "5";
putText(frame, name, text_lb, FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255));
}
imshow("face", frame);
if (waitKey(50) >= 0)
stop = true;
}
}
参考:http://blog.csdn.net/xingchenbingbuyu/article/details/51386949