大家好,又见面了,我是你们的朋友全栈君。
一、准备
链接:代码+数据集
提取码:led1
环境:win10,vs2013,opencv3.2
注:每个代码都可以在vs中单独运行
该项目所有文件如下:
其中只需要使用的文件如下:
详细代码:
//这个是生成照片的代码
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
//cv库,哈尔检测人脸使用的配置文件
string haar_face_datapath = "E:/opencv/install/etc/haarcascades/haarcascade_frontalface_alt_tree.xml";
int main(int argc, char** argv) {
//打开摄像头
VideoCapture capture(0);
if (!capture.isOpened()) {
printf("could not open camera...\n");
return -1;
}
Size S = Size((int)capture.get(CV_CAP_PROP_FRAME_WIDTH), (int)capture.get(CV_CAP_PROP_FRAME_HEIGHT));
int fps = capture.get(CV_CAP_PROP_FPS);
//人脸检测库
CascadeClassifier faceDetector;
//人脸检测函数
faceDetector.load(haar_face_datapath);
Mat frame;
namedWindow("camera-demo", CV_WINDOW_AUTOSIZE);
vector<Rect> faces;
int count = 0;
while (capture.read(frame)) {
flip(frame, frame, 1);
faceDetector.detectMultiScale(frame, faces, 1.1, 1, 0, Size(100, 120), Size(380, 400));
for (int i = 0; i < faces.size(); i++) {
if (count % 10 == 0) {
Mat dst;
//重新把照片大小改成模板的大小
resize(frame(faces[i]), dst, Size(112, 92));
//保存照片
imwrite(format("D:/else//led/face_%d.jpg", count), dst);
}
rectangle(frame, faces[i], Scalar(0, 0, 255), 2, 8, 0);
}
imshow("camera-demo", frame);
char c = waitKey(10);
//按键退出截图
if (c == 27) {
break;
}
count++;
}
capture.release();
waitKey(0);
return 0;
}
//这个是生成csv文件的教程,直接用shell命令,不需要写代码
1. 打开cmd
2. 输入 F: (因为我的文件在F盘) 注意一定要先进入F盘才可以后续操作,不然会显示找不到文件
3. 输入cd 文件路径,点回车
4. 输入dir /b/s/p/w *.jpg>at.csv 注意,我的文件格式为.jpg
#include <opencv2/opencv.hpp>
#include <opencv2/face.hpp>
#include <iostream>
using namespace cv;
using namespace cv::face;
using namespace std;
int main(int argc, char** argv) {
//加载自己的csv文件
string filename = string("D:/else/wyz/at.csv");
ifstream file(filename.c_str(), ifstream::in);
if (!file) {
printf("could not load file correctly...\n");
return -1;
}
string line, path, classlabel;
vector<Mat> images;
vector<int> labels;
char separator = ';';
while (getline(file, line)) {
stringstream liness(line);
getline(liness, path, separator);
getline(liness, classlabel);
if (!path.empty() && !classlabel.empty()) {
//printf("path : %s\n", path.c_str());
images.push_back(imread(path, 0));
labels.push_back(atoi(classlabel.c_str()));
}
}
if (images.size() < 1 || labels.size() < 1) {
printf("invalid image path...\n");
return -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();
// train it,训练自己的模型,到这里已经完成训练操作
Ptr<BasicFaceRecognizer> model = createEigenFaceRecognizer();
model->train(images, labels);
model->save("D:/else/wyz/led_wyz.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");
*/
/* 以下内容用于检测验证自己重建的人脸模,可以直接跳过,本代码全部注释掉了
// recognition face
int predictedLabel = model->predict(testSample);
printf("actual label : %d, predict label : %d\n", testLabel, predictedLabel);
Mat eigenvalues = model->getEigenValues();
Mat W = model->getEigenVectors();
Mat mean = model->getMean();
Mat meanFace = mean.reshape(1, height);
Mat dst;
if (meanFace.channels() == 1) {
normalize(meanFace, dst, 0, 255, NORM_MINMAX, CV_8UC1);
}
else if (meanFace.channels() == 3) {
normalize(meanFace, dst, 0, 255, NORM_MINMAX, CV_8UC3);
}
imshow("Mean Face", dst);
// show eigen faces
for (int i = 0; i < min(25, W.cols); i++) {
Mat ev = W.col(i).clone();
Mat grayscale;
Mat eigenFace = ev.reshape(1, height);
if (eigenFace.channels() == 1) {
normalize(eigenFace, grayscale, 0, 255, NORM_MINMAX, CV_8UC1);
}
else if (eigenFace.channels() == 3) {
normalize(eigenFace, grayscale, 0, 255, NORM_MINMAX, CV_8UC3);
}
Mat colorface;
applyColorMap(grayscale, colorface, COLORMAP_JET);
char* winTitle = new char[128];
sprintf(winTitle, "eigenface_%d", i);
imshow(winTitle, colorface);
}
// 重建人脸
for (int num = min(25, W.cols); num < min(W.cols, 300); num += 1) {
Mat evs = Mat(W, Range::all(), Range(0, num));
Mat projection = LDA::subspaceProject(evs, mean, images[0].reshape(1, 1));
Mat reconstruction = LDA::subspaceReconstruct(evs, mean, projection);
Mat result = reconstruction.reshape(1, height);
if (result.channels() == 1) {
normalize(result, reconstruction, 0, 255, NORM_MINMAX, CV_8UC1);
}
else if (result.channels() == 3) {
normalize(result, reconstruction, 0, 255, NORM_MINMAX, CV_8UC3);
}
char* winTitle = new char[128];
sprintf(winTitle, "recon_face_%d", num);
imshow(winTitle, reconstruction);
}
*/
waitKey(0);
return 0;
}
二、原理
原理1.PCA(主成分分析)原理
通过对高维数据分析发现他们的相同与不同表达为 一个低维数据模式
主成分不变
细微损失
高维数据到低维数据
原理2.API调用
主要是使用其中的三个函数,来训练自己的数据,函数如下:
// train it
Ptr<BasicFaceRecognizer> model = createEigenFaceRecognizer();
model->train(images, labels);
model->save("D:/else/wyz/led_wyz.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");
三、步骤
1. 算法实现步骤
- 数据:ORL att_faces OpenCV的数据 10个人、每人10张照片
- 一个图像N宽*N高*N个 112*92*100个矩阵
- 平均脸 矩阵计算得到均值
- 特征脸 矩阵计算得到特征值
- 开始、读训练数据、计算平均脸、计算协方差矩阵、计算特征值、特征矩阵、 PAC降维、子空间模型、检测
- 生成CSV文件
- 生成自己的xml
- 训练
- 识别
- 识别率
- 结果分析
四、结果
结果1.方差均值作用
图像RGB矩阵
空白背景方差不为0,均值为0
结果2.PCA应用
- 灰度图像
- 描边,画出边缘
- XY表示所有轮廓,N*X*Y
- PCA处理,得到协方差矩阵,得到特征值特征向量
N行2列表示所有的点
得到轮廓中心位置
Eigen得到特征值
结果3..Eigenface算法
- 数据:ORL att_faces OpenCV的数据 10个人、每人10张照片
平均脸
2. 一个图像N宽*N高*N个 112*92*100个矩阵
3.平均脸 矩阵计算得到均值
4.特征脸 矩阵计算得到特征值
5.开始、读训练数据、计算平均脸、计算协方差矩阵、计算特征值、特征矩阵、 PAC降维、子空间模型、检测
6.生成CSV文件
7.生成自己的xml
8.训练
9.识别
10. 识别率:
11. 侧脸影响
12.暗光条件下,找不到人脸,识别率也降低
结果4.Fisher算法
- 由fisher发现,于是命名FisherFace
- 基于LDA降维,求两个对象之间的内差和外差,得到离散矩阵,求特征值特 征向量
- FishFace识别在光照上有所进步,光的明暗影响不是很大
4.识别率问题,因为这里光亮作为主要因素,光亮无法做到细微控制,这里不做详细比较
5.人脸上半部分处在黑暗环境,与EigenFace比较,差不多同一张图片,这张图能识别出来
结果5.LBPH算法
此算法和前两种的比较,主要是在光照和侧脸角度上有所加强,这里不再多做比较。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/135733.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...