上篇介绍了QT之后,我们又开始对其进行其他测试,如我们的开发板也支持外接摄像头,此次测试下一个开源项目,基于QT+OpenCV的人脸识别打卡项目。本次体验使用的是开源的代码,此代码本来跑在WIN下的,我稍微进行了修改,让其跑在我们的开发板上。
实际是分了两个工程,一个工程是作为管理员控制功能使用,添加人脸信息。同时也可以查询到打卡记录,对从机进行下发通知等等。
人脸识别我们主要需要用到opencv的人脸检测分类器
OpenCV编译完成后已经提供好了的。
因为这里还需要涉及到训练模型,有了模型后才能更好的识别,所以还是简单介绍下怎么训练的吧。
- CascadeClassifier cascada;
-
-
-
- cascada.load("F:\\video\\ccc\\haarcascade_frontalface_alt2.xml");
-
- VideoCapture cap(1);
-
- Mat frame, myFace;
-
- int pic_num = 1;
-
- while (1) {
-
-
-
- cap >> frame;
-
- vector<Rect> faces;
-
- Mat frame_gray;
-
-
-
- cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
-
-
-
- cascada.detectMultiScale(frame_gray, faces, 1.1, 4, CV_HAAR_DO_ROUGH_SEARCH, Size(70, 70), Size(1000, 1000));
-
- printf("检测到人脸个数:%d\n", faces.size());
-
-
-
-
-
- for (int i = 0; i < faces.size(); i++)
-
- {
-
- rectangle(frame, faces[i], Scalar(255, 0, 0), 2, 8, 0);
-
- }
-
-
-
- if (faces.size() == 1)
-
- {
-
- Mat faceROI = frame_gray(faces[0]);
-
-
-
- resize(faceROI, myFace, Size(92, 112));
-
- putText(frame, to_string(pic_num), faces[0].tl(), 3, 1.2, (0, 0, 225), 2, 0);
-
- string filename = format("F:\\video\\%d.jpg", pic_num);
-
- imwrite(filename, myFace);
-
- imshow(filename, myFace);
-
- waitKey(500);
-
- destroyWindow(filename);
-
- pic_num++;
-
- if (pic_num == 11)
-
- {
-
- return 0;
-
- }
-
- }
-
- int c = waitKey(10);
-
- if ((char)c == 27) { break; }
-
- imshow("frame", frame);
-
- waitKey(100);
-
- }
-
- return 0;
通过上面代码,完成图像采集。
-
-
-
-
- string fn_csv = "F:\\video\\ccc\\at.txt";
-
-
-
-
-
- vector<Mat> images;
-
- vector<int> labels;
-
-
-
-
-
- try
-
- {
-
- read_csv(fn_csv, images, labels);
-
- }
-
- 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++)
-
- {
-
-
-
- if (images[i].size() != Size(92, 112))
-
- {
-
- cout << i << endl;
-
- cout << images[i].size() << endl;
-
- }
-
-
-
- }
-
-
-
-
-
-
-
- Mat testSample = images[images.size() - 1];
-
- int testLabel = labels[labels.size() - 1];
-
- images.pop_back();
-
- labels.pop_back();
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 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");
-
-
-
-
-
-
-
-
-
- int predictedLabel = model->predict(testSample);
-
- int predictedLabel1 = model1->predict(testSample);
-
- int predictedLabel2 = model2->predict(testSample);
-
-
-
-
-
-
-
-
-
-
-
-
-
- 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();
-
-
-
- return 0;
通过上面的代码进行训练,训练使用了python。所以系统环境需要配置好。
在此文件中,把我们采集到的图像,放进去,新建一个文件夹。
之后就是把我们的at.txt也加入我们的文件。
训练好后,我们就得到了我们需要的训练文件。
在我们打卡界面,点击打卡时就是这样的。加载训练好的东西。然后启动定时器,去获取摄像头信号,然后对比,最终和数据库一致就认为打卡成功。
上面训练部分,其实提供的另一个工程全部完成了。
这是我们win端界面,圆框就是我们摄像头采集图像显示的位置。
我们需要在Ubuntu下把库全部替换,这样就能编译过了,然后拷贝到开发板上运行。如下:
进来就提示数据库打开失败了,我们这个都是基于数据库,所以还是比较尴尬的,后期的话可以尝试自己全部编译下,然后更新吧。目前就测试,看下效果吧。
使用的硬件增加了一个摄像头。
这是打开摄像头采集的样子。
这个GIF展示下我们的人脸检测情况。
由于没有数据库,只能打印一些信息。当两个数据相等时就进入下一步,判断打卡了。由于没有数据库,就展示下电脑端的效果吧。