【大联大友尚安森美数字图像传感器】openCV人脸识别和考勤软件
昨天我们已经利用QT+openCV打开了摄像头传感器,接下来就是使用openCV识别人脸,进行人脸检测了。
本项目使用的是别人开源的一个历程,我在我的电脑上搭建了环境进行了测试,这里把我自己的流程先说明一下。
用QT调用openCV的库一般是先编译,主要使用的是cmake进行编译。
也可以使用别人编译好的库进行测试。CMAKE主要就是需要把自己QT中使用的mingw编译工具来进行编译。
可以看到我们是有很多的编译器的,可以自己选择,这里我用别人开源的项目,所以里面也直接有编译好的库文件。我们直接解压到D盘即可。
同时需要添加一个PATH环境变量,不然会导致程序异常,运行不起来。
在工程的pro文件中加入这个环境路径
接下来的构建和运行需要选择MinGW64,因为库是64位的,32位编译也会出现问题。
在openCV中我们需要使用各种训练模型,有了训练模型我们可以很方便的实现人脸检测。
这个是我们本次识别用到的训练文件,需要放到我们可执行程序下。
然后是人脸识别的分类器,我们不同人脸之间也需要区分。所以我们通过一个外部程序训练了三种不同分类器的人脸分类库。
- //读取你的CSV文件路径.
- //string fn_csv = string(argv[1]);
- string fn_csv = "F:\\video\\ccc\\at.txt";
- // 2个容器来存放图像数据和对应的标签
- vector<Mat> images;
- vector<int> labels;
- // 读取数据. 如果文件不合法就会出错
- // 输入的文件名已经有了.
- try
- {
- read_csv(fn_csv, images, labels); //从csv文件中批量读取训练数据
- }
- 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);
- }
- for (int i = 0; i < images.size(); i++)
- {
- //cout<<images.size();
- if (images[i].size() != Size(92, 112))
- {
- cout << i << endl;
- cout << images[i].size() << endl;
- }
- }
- // 下面的几行代码仅仅是从你的数据集中移除最后一张图片,作为测试图片
- //[gm:自然这里需要根据自己的需要修改,他这里简化了很多问题]
- Mat testSample = images[images.size() - 1];
- int testLabel = labels[labels.size() - 1];
- images.pop_back();//删除最后一张照片,此照片作为测试图片
- labels.pop_back();//删除最有一张照片的labels
- // 下面几行创建了一个特征脸模型用于人脸识别,
- // 通过CSV文件读取的图像和标签训练它。
- // T这里是一个完整的PCA变换
- //如果你只想保留10个主成分,使用如下代码
- // cv::createEigenFaceRecognizer(10);
- //
- // 如果你还希望使用置信度阈值来初始化,使用以下语句:
- // cv::createEigenFaceRecognizer(10, 123.0);
- //
- // 如果你使用所有特征并且使用一个阈值,使用以下语句:
- // cv::createEigenFaceRecognizer(0, 123.0);
- //创建一个PCA人脸分类器,暂时命名为model吧,创建完成后
- //调用其中的成员函数train()来完成分类器的训练
- Ptr<face::BasicFaceRecognizer> model = face::EigenFaceRecognizer::create();
- model->train(images, labels);
- model->save("MyFacePCAModel.xml");//保存路径可自己设置,但注意用“\\”
- Ptr<face::BasicFaceRecognizer> model1 = face::FisherFaceRecognizer::create();
- model1->train(images, labels);
- model1->save("MyFaceFisherModel.xml");
- Ptr<face::LBPHFaceRecognizer> model2 = face::LBPHFaceRecognizer::create();
- model2->train(images, labels);
- model2->save("MyFaceLBPHModel.xml");
- // 下面对测试图像进行预测,predictedLabel是预测标签结果
- //注意predict()入口参数必须为单通道灰度图像,如果图像类型不符,需要先进行转换
- //predict()函数返回一个整形变量作为识别标签
- 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;
通过最低10张人脸图片进行训练,最终得到三个
MyFacePCAModel.xml
MyFaceFisherModel.xml
MyFaceLBPHModel.xml
分类器模型。下面其实就是加载。
如下就可以进入登录界面,判断值和检测值相同时,不过有一定的误报。
软件是由两个,一个是管理界面,一个是打开界面。
但我们创建的人脸和数据库中的人脸比对上时候就会弹出已打卡的通知。准确度还是可以,不过有时候也会出现误报,后面看可不可以优化下。后期会把资料整理发出。
这是本次使用的摄像头所完成的报告。