Ptr model = FisherFaceRecognizer::create();
#include
#include
#include
using namespace std;
using namespace cv;
using namespace cv::face;
//OpenCV人脸识别https://www.cnblogs.com/guoming0000/archive/2012/09/27/2706019.html
int main(int argc, char** argv)
{
String filename = string("face_image.txt");//标签Label_Text文件
//从硬盘到内存
ifstream file(filename.c_str(), ifstream::in);////c_str()函数可用可不用,无需返回一个标准C类型的字符串
if (!file)//打开标签文件失败
{
cout << "could not load label_file" << endl;
return -1;
}
string line, path, classlabel;
vector images;//存放图像数据
vector labels;//存放图像标签
char separator = ';';//分号
while (getline(file, line)) //getline(cin,inputLine)//cin 是正在读取的输入流,而 inputLine 是接收输入字符串的 string 变量的名称
{
stringstream liness(line);//这里采用stringstream主要作用是做字符串的分割
getline(liness, path, separator);//遇到分号就结束
getline(liness, classlabel);//继续从分号后面开始,遇到换行结束
if (!path.empty() && !classlabel.empty())
{
images.push_back(imread(path, 0));//imread(path,0)//0不能去
labels.push_back(atoi(classlabel.c_str()));//atoi字符串转换成整型数
}
}
if (images.size() <= 1 || labels.size() <= 1)//如果没有读到足够多的图片
{
cout << "读取图片数据失败..." << endl;
}
int height = images[0].rows; //得到第一张图片的高度,在下面对图像变形得到他们原始大小时需要
int width = images[0].cols;
cout << "读取的图片高度为:" << height << endl << "读取的图片宽度为:" << width << endl;
//从数据集 中移除最后一张图片,用于做测试,需要根据自己的需要进行修改
Mat testSample = images[images.size() - 1];//获取最后一张照片
int testLabel = labels[labels.size() - 1];//获取最后一个标签
images.pop_back();//移除最后一张图片
labels.pop_back();//移除最后一个标签
//特征脸Fisherfaces
Ptr model = FisherFaceRecognizer::create();
model->train(images, labels);
//对测试图像进行预测,predictedLabel是预测标签结果
int predictedLabel = model->predict(testSample);
cout << "actual label: " << testLabel << endl;
cout << "predict label: " << predictedLabel <getEigenVectors();//获得特征向量
Mat eigenvalue = model->getEigenValues();//获得特征值
Mat mean = model->getMean();//获得均值向量
//显示平均脸
Mat meanvector = mean.reshape(1, height);
Mat meanface;//平均脸
if (meanvector.channels() == 1)
{
normalize(meanvector, meanface, 0, 255, NORM_MINMAX, CV_8UC1);
}
else if (meanvector.channels() == 3)
{
normalize(meanvector, meanface, 0, 255, NORM_MINMAX, CV_8UC3);
}
imshow("Mean Face", meanface);
//显示特征脸
Mat color_fisherface;//使用伪彩色来显示结果,为了更好的观察
for (int i = 0; i < min(16, eigenvector.cols); i++)//最多16 Fisherfaces
{
Mat temp_eigenvector = eigenvector.col(i).clone();//得到第i个特征向量
Mat eigenFace = temp_eigenvector.reshape(1, height);//特征脸
if (eigenFace.channels() == 1)
{
normalize(eigenFace, eigenFace, 0, 255, NORM_MINMAX, CV_8UC1);
}
else if (eigenFace.channels() == 3)
{
normalize(eigenFace, eigenFace, 0, 255, NORM_MINMAX, CV_8UC3);
}
applyColorMap(eigenFace, color_fisherface, COLORMAP_BONE);
//char* winTitle = new char[128];//创建一个用来存 窗口名的buff
//sprintf(winTitle, "eigenface_%d", i);//创建 i+1 个窗口,分别命名为eigenface_i
//imshow(winTitle, color_eigenface);//显示 i+1 个窗口
}
imshow("Eigen Face", color_fisherface);
//重建人脸
Mat rebuildFace;
for (int num = 0; num < min(eigenvector.cols,16 ); num ++)
{
Mat temp_eigenmodel = eigenvector.col(num);
//投影样本到LDA子空间//把第images[i]幅图像放到LDA子空间
Mat projection = LDA::subspaceProject(temp_eigenmodel, mean, images[0].reshape(1, 1));
//重构来自于LDA子空间的投影//backProject()逆映射//重建第images[i]幅图像(放在projection里)
Mat reconstruction = LDA::subspaceReconstruct(temp_eigenmodel, mean, projection);
rebuildFace = reconstruction.reshape(1, height);
if (rebuildFace.channels() == 1)
{
normalize(rebuildFace, rebuildFace, 0, 255, NORM_MINMAX, CV_8UC1);
}
else if (rebuildFace.channels() == 3)
{
normalize(rebuildFace, rebuildFace, 0, 255, NORM_MINMAX, CV_8UC3);
}
//char* winTitle = new char[128];
//sprintf(winTitle, "rebuild_face_%d", num);
//imshow(winTitle, rebuildFace);
}
imshow("Rebuild Face", rebuildFace);
waitKey(0);
return 0;
}
输出结果: