此程序主要来源于F:\personal\data\openCV\opencv_contrib_3.4.1\modules\face\samples\facerec_eigenfaces.cpp
/*
此程序主要来源于F:\personal\data\openCV\opencv_contrib_3.4.1\modules\face\samples\facerec_eigenfaces.cpp
*/
#include
#include
//#include
//#include
using namespace std;
using namespace cv;
using namespace cv::face;
Mat normal(Mat& src, Mat& dst)
{
if (src.channels() == 1)
{
normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
}
else
{
normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
}
return dst;
}
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(Error::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()));
}
}
}
int main()
{
string filename = ".\\face_recg\\face\\at.txt";
vector images;
vector labels;
//从文件中读取图像保存到向量中
try {
read_csv(filename, images, labels);
}
catch (Exception& e)
{
cerr << "Error opening file \n" << filename << "\". Reason: " << e.msg << endl;
exit(1);
}
if (images.size() <= 1)
{
cerr << "图像太少,请至少添加两个图片!" << endl;
exit(1);
}
//从第一个图像获取高度,在后面的代码里面需要用到它来重塑原来的图片大小
int height = images[0].rows;
int width = images[0].cols;
printf("height: %d, width: %d\n", height, width);
//最后一个人为测试样本
Mat testSample = images[images.size() - 1];
int testLabel = labels[labels.size() - 1];
images.pop_back();
labels.pop_back();
//训练
Ptr model = EigenFaceRecognizer::create();
model->train(images, labels);
//识别
int predictedLabel = model->predict(testSample);
printf("actual label: %d, predict label: %d\n", testLabel, predictedLabel);
//获得特征值,特征向量,均值,平均脸
Mat eigenValues = model->getEigenValues();
Mat eigenVector = model->getEigenVectors();
Mat mean = model->getMean();
Mat meanFace = mean.reshape(1, height);
Mat dst;
dst = normal(meanFace, dst);
imshow("MeanFace", dst);
//特征脸
for (int i = 0; i < min(10, eigenVector.cols); i++)
{
Mat ev = eigenVector.col(i).clone();
Mat eigenFace = ev.reshape(1, height);
Mat grayScale;
grayScale = normal(eigenFace, grayScale);
Mat colorFace;
applyColorMap(grayScale, colorFace, COLORMAP_BONE);
imshow(format("eigenFace_%d", i), colorFace);
}
//重建人脸
for (int i = min(10, eigenVector.cols); i < min(300, eigenVector.cols); i += 15)
{
Mat evs = Mat(eigenVector, Range::all(), Range(0, i));
Mat projection = LDA::subspaceProject(evs, mean, images[0].reshape(1, 1));
Mat reconstruction = LDA::subspaceReconstruct(evs, mean, projection);
Mat result = reconstruction.reshape(1, height);
reconstruction = normal(result, reconstruction);
imshow(format("reco_face_%d", i), reconstruction);
}
waitKey(0);
destroyAllWindows();
return 0;
}