感谢网络上相头的博客和资料,由于版本的原因有些api的更改使得源代码不能直接使用,所以这里放上自己基于opencv3.4做的测试。
int main()
{
VideoCapture cap(0); //打开默认摄像头
if(!cap.isOpened())
{
return -1;
}
Mat frame;
Mat edges;
CascadeClassifier cascade, nestedCascade;
bool stop = false;
//训练好的文件名称,放置在可执行文件同目录下
cascade.load("haarcascade_frontalface_default.xml");
nestedCascade.load("haarcascade_eye.xml");
frame = imread("2.jpg");
detectAndDraw(frame, cascade, nestedCascade, 2, 0);
while(!stop)
{
cap>>frame;
detectAndDraw( frame, cascade, nestedCascade,2,0 );
if(waitKey(30) >=0)
stop = true;
}
waitKey();
return 0;
}
void detectAndDraw(Mat& img, CascadeClassifier& cascade,
CascadeClassifier& nestedCascade,
double scale, bool tryflip)
{
std::vector faces;
Mat frame_gray;
cvtColor(img, frame_gray, COLOR_BGR2GRAY);
//检测人脸
//detectMultiScale函数中smallImg表示的是要检测的输入图像为smallImg,faces表示检测到的人脸目标序列,1.1表示
//每次图像尺寸减小的比例为1.1,2表示每一个目标至少要被检测到3次才算是真的目标(因为周围的像素和不同的窗口大
//小都可以检测到人脸),CV_HAAR_SCALE_IMAGE表示不是缩放分类器来检测,而是缩放图像,Size(30, 30)为目标的
//最小最大尺寸
cascade.detectMultiScale(frame_gray, faces,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
| CV_HAAR_SCALE_IMAGE
, Size(30, 30));
for (size_t i = 0; i < faces.size(); i++)
{
rectangle(img, faces[i], Scalar(255, 0, 0), 2, 8, 0);
}
if (faces.size() == 1)
{
Mat faceROI = img(faces[0]);
Mat myFace;
resize(faceROI, myFace, Size(92, 112));
putText(img, to_string(1), faces[0].tl(), 3, 1.2, (0, 0, 255), 2, LINE_AA);
string filename = format("C:\\Users\\lyy\\Desktop\\att_faces\\s41\\%d.jpg", pic_num);
imwrite(filename, myFace);
imshow(filename, myFace);
waitKey(500);
destroyWindow(filename);
pic_num++;
}
imshow("识别结果", img);
}
dir /b /s *.pgm *.jpg >at.txt
#!/usr/bin/env python
import sys
import os.path
if __name__ == "__main__":
#if len(sys.argv) != 2:
# print "usage: create_csv "
# sys.exit(1)
#BASE_PATH=sys.argv[1]
BASE_PATH="C:\\Users\\lyy\\Desktop\\att_faces"
SEPARATOR=";"
fh = open("at.txt",'w')
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):
subdirname2 = subdirname[::-1]
subdirname3 = subdirname2[:-1]
subdirname4 = subdirname3[::-1]
#print subdirname2[:-1]
label = int(subdirname4)
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()
``` c++
int main()
{
//读取你的CSV文件路径.
//string fn_csv = string(argv[1]);
string fn_csv = "at.txt";
// 2个容器来存放图像数据和对应的标签
vector images;
vector 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 model = EigenFaceRecognizer::create();
model->train(images, labels);
model->save("MyFacePCAModel.xml");
Ptr model1 = FisherFaceRecognizer::create();
model1->train(images, labels);
model1->save("MyFaceFisherModel.xml");
Ptr model2 = LBPHFaceRecognizer::create();
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;
getchar();
//waitKey(0);
return 0;
}
static Mat norm_0_255(InputArray _src) {
Mat src = _src.getMat();
// 创建和返回一个归一化后的图像矩阵:
Mat dst;
switch (src.channels()) {
case 1:
cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
break;
case 3:
cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
break;
default:
src.copyTo(dst);
break;
}
return dst;
}
//使用CSV文件去读图像和标签,主要使用stringstream和getline方法
static void read_csv(const string& filename, vector& images, vector& labels, char separator = ';') {
std::ifstream file(filename.c_str(), ifstream::in);
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)) {
stringstream liness(line);
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()));
}
}
tips :createEigenFaceRecognizer更改为了EigenFaceRecognizer::create()
** FisherFaceRecognizer::create()与LBPHFaceRecognizer::create()同样具体细节可以参看源码**
int main3()
{
VideoCapture cap(0); //打开默认摄像头
if (!cap.isOpened())
{
return -1;
}
Mat frame;
Mat edges;
Mat gray;
CascadeClassifier cascade;
bool stop = false;
//训练好的文件名称,放置在可执行文件同目录下
cascade.load("haarcascade_frontalface_alt.xml");
Ptr modelPCA = EigenFaceRecognizer::create();
modelPCA->read("MyFacePCAModel.xml");
//3.4取消了load所以这里用的read
frame = imread("3.jpg");
detectMyFace(frame, cascade, modelPCA);
while (!stop)
{
cap >> frame;
detectMyFace(frame, cascade, modelPCA);
if (waitKey(30) >= 0)
stop = true;
}
waitKey(0);
return 0;
}
void detectMyFace(Mat& img, CascadeClassifier& cascade, Ptr modelPCA)
{
std::vector faces;
Mat frame_gray;
cvtColor(img, frame_gray, COLOR_BGR2GRAY);
//改变图像大小,使用双线性差值
//resize(gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR);
//变换后的图像进行直方图均值化处理
//equalizeHist(gray, gray);
cascade.detectMultiScale(frame_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 = frame_gray(faces[i]);
text_lb = Point(faces[i].x, faces[i].y);
rectangle(img, 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 == 41)
{
string name = "liyangyang";
putText(img, name, text_lb, FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255));
}
else
{
string name = "noliyangyang";
putText(img, name, text_lb, FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255));
}
imshow("face", img);
}
源码都附上去了,其中很多都是参考网络上的文档,只有具体的细节和版本不同的函数做了更改。谢谢伟大的互联网。