(八)OpenCV人脸识别_04_EigenFace算法

Sue ·
更新时间:2024-11-13
· 521 次阅读

读人脸数据文件 ORL/face database(https://github.com/fengbingchun/NN_Test)
创建特征脸识别与训练
识别人脸
输出中间平均脸 、特征脸、重建结果 过程:
读训练数据->计算平均脸->计算协方差矩阵->计算特征脸->特征矩阵->PCA降维->子空间模型->检测/距离 Ptr model = EigenFaceRecognizer::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() - 2];//获取最后一张照片 int testLabel = labels[labels.size() - 2];//获取最后一个标签 images.pop_back();//移除最后一张图片 labels.pop_back();//移除最后一个标签 /* 特征脸Eigenfaces 图像表示的问题是他的高维问题。 二维灰度图像p*q大小,是一个m=q*p维的向量空间,所以一个100*100像素大小的图像就是10,000维的图像空间。 但是不是所有的维数空间对我们来说都有用?我们可以做一个决定,如果数据有任何差异,我们可以通过寻找主元来知道主要信息。 主成分分析(Principal Component Analysis,PCA)是把一些可能相关的变量转换成一个更小的不相关的子集。 一个高维数据集经常被相关变量表示,因此只有一些的维上数据才是有意义的,包含最多的信息。 PCA方法寻找数据中拥有最大方差的方向,被称为主成分。 */ //创建一个特征脸模型用于人脸识别 //通过txt文件读取的图像和标签 训练它 //这里是一个完整的PCA变换 Ptr model = EigenFaceRecognizer::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_eigenface;//使用伪彩色来显示结果,为了更好的观察 for (int i = 0; i < min(10, eigenvector.cols); i++)//10可更改至(特征脸数目)(50大概是最好的) { 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_eigenface, COLORMAP_JET); //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_eigenface); //重建人脸 Mat rebuildFace; for (int num = min(10, eigenvector.cols); num < min(eigenvector.cols, 100); num += 15)//100可最大更改至样本数(400) { Mat temp_eigenmodel = Mat(eigenvector, Range::all(), Range(0, num));//提取特征向量eigenvector的前num列数据(用来重建数据) /* 把所有的训练数据投影到PCA子空间 把待识别图像投影到PCA子空间 找到训练数据投影后的向量和待识别图像投影后的向量最近的那个(逆映射) */ //投影样本到LDA子空间//把第images[i]幅图像放到LDA子空间 Mat projection = LDA::subspaceProject(temp_eigenmodel, mean, images[10].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; }

输出结果:(第一行分别为平均脸,特征脸,重建脸…)(后6张重建脸根据提取特征向量eigenvector的前num列数据重建)
在这里插入图片描述


作者:丶小早



opencv人脸识别 opencv

需要 登录 后方可回复, 如果你还没有账号请 注册新账号