概述
1.准备训练数据
网络上下载(训练数据量大时,通过爬虫获取)目标的图片:
![](https://file2.kaopuke.com:8081/files_image/20230507/202305071452263280267.png)
运用以下代码将原图中的
人脸头像识别、提取、调整大小(这里是150*200),并分别保存。
运行环境:win7 64+VS2013+openCV3.1。
(PS:抱怨下vs和opencv的版本密切相关,注意安装配置)
![](https://file2.kaopuke.com:8081/files_image/20230507/202305071452267752456.jpg)
![](https://file2.kaopuke.com:8081/files_image/20230507/202305071452263591580.jpg)
#include <opencv2opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>
#include <opencv2/videoio/videoio_c.h>
#include <opencv2/highgui/highgui_c.h>
using namespace std;
using namespace cv;
/** Function Headers */
void detectAndDisplay(Mat frame);
/** Global variables */
String face_cascade_name = "F:\Downloads\opencv_build\install\etc\haarcascades\haarcascade_frontalface_default.xml";
String eyes_cascade_name = "F:\Downloads\opencv_build\install\etc\haarcascades\haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade; //定义人脸分类器
CascadeClassifier eyes_cascade; //定义人眼分类器
String window_name = "Capture - Face detection";
/** @function main */
int main(void)
{
//-- 1. Load the cascades
if (!face_cascade.load(face_cascade_name)){ printf("--(!)Error loading face cascaden"); return -1; };
if (!eyes_cascade.load(eyes_cascade_name)){ printf("--(!)Error loading eyes cascaden"); return -1; };
//-- 2. 遍历原图像文件夹
vector<String> files;
glob("D:\training\liudh_before\*.jpg", files, true);
//-- 3. 识别、提取,并保存头像至新文件夹。图片均调整为150x200像素
for (int i = 0; i < files.size(); i++)
{
//Image processing
Mat img = imread(files[i]); //读取文件
cout << files[i] << 'n';
detectAndDisplay(img); //提取头像
waitKey(1000);
}
}
/** @function detectAndDisplay */
void detectAndDisplay(Mat frame)
{
static int count = 0;
std::vector<Rect> faces;
Mat frame_gray;
Mat MyFace;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
//equalizeHist(frame_gray, frame_gray);
//imshow("2", frame_gray);
//-- Detect faces
face_cascade.detectMultiScale(frame_gray, faces, 1.1);
for (size_t i = 0; i < faces.size(); i++) //人脸数目
{
Mat faceROI = frame_gray(faces[i]);
rectangle(frame, faces[i], Scalar(255, 0, 0), 2, 8, 0);
if (faceROI.cols > 80){
resize(faceROI, MyFace, Size(150, 200));
string str = format("D:\training\liudh\MyFcae%d.jpg", count);
cout << " 保存图片" << count<<endl;
imwrite(str, MyFace);
imshow("ii", MyFace);
}
count++;
}
//-- Show what you got
namedWindow(window_name, 2);
imshow(window_name, frame);
}
2.制作标签文件CSV
进入命令行,输入命令 di /b/s *.pgm *jpg >at.txt
![](https://file2.kaopuke.com:8081/files_image/20230507/202305071452261570165.png)
会在训练数据文件夹下生成一个at.txt文件,但这文件内只有数据,没有标签。(笨办法是将数据拷贝到execl表格中生成标签)
最终生成文件内容如下所示:
![](https://file2.kaopuke.com:8081/files_image/20230507/202305071452263518347.png)
也可以通过create_csv.py制作标签(注意修改文件中的目录路径)
#!/usr/bin/env python
import sys
import os.path
# This is a tiny script to help you creating a CSV file from a face
# database with a similar hierarchie:
#
# philipp@mango:~/facerec/data/at$ tree
# .
# |-- README
# |-- s1
# | |-- 1.pgm
# | |-- ...
# | |-- 10.pgm
# |-- s2
# | |-- 1.pgm
# | |-- ...
# | |-- 10.pgm
# ...
# |-- s40
# | |-- 1.pgm
# | |-- ...
# | |-- 10.pgm
#
if __name__ == "__main__":
#if len(sys.argv) != 2:
# print "usage: create_csv <base_path>"
# sys.exit(1)
#BASE_PATH=sys.argv[1]
BASE_PATH="D:/att_faces"
SEPARATOR=";"
fh = open("D:/att_faces/at.txt",'w')
label = 1
for dirname, dirnames, filenames in os.walk(BASE_PATH):
for subdirname in dirnames:
subject_path = os.path.join(dirname, subdirname)
for filename in os.listdir(subject_path):
abs_path = "%s/%s" % (subject_path, filename)
#print "%s%s%d" % (abs_path, SEPARATOR, label)
fh.write(abs_path)
fh.write(SEPARATOR)
fh.write(str(label))
fh.write("n")
label = label + 1
fh.close()
3. 训练模型
EigenFace和FisherFace的训练图像和测试图像都必须是灰度图,而且是经过归一化裁剪过的。
1.运用alt.txt文件,加载训练数据;提取数据和标签
2.根据FaceRecognizer三种训练模型进行训练;
3.保存训练数据及模型(xml)
//#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <fstream>
#include <sstream>
#include <math.h>
#include <opencv2/face.hpp>
#include <opencv2/face/facerec.hpp>
#include <iostream>
#include <stdio.h>
#include "opencv2/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/calib3d.hpp"
#include "opencv2/imgproc.hpp"
#include"opencv2/flann.hpp"
#include"opencv2/xfeatures2d.hpp"
#include"opencv2/ml.hpp"
#include"opencv2/face.hpp"
#include"opencv2/face/facerec.hpp"
#include"opencv2/objdetect.hpp"
using namespace cv;
using namespace std;
using namespace face;
static Mat norm_0_255(InputArray _src) {
Mat src = _src.getMat();
// 创建和返回一个归一化后的图像矩阵:
Mat dst;
switch (src.channels()) {
case1:
cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
break;
case3:
cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
break;
default:
src.copyTo(dst);
break;
}
return dst;
}
//使用CSV文件去读图像和标签,主要使用stringstream和getline方法
static void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';') {
std::ifstream file(filename.c_str(), ifstream::in);
if (!file) {
string error_message = "No valid input file was given, please check the given filename.";
CV_Error(CV_StsBadArg, error_message);
}
string line, path, classlabel;
while (getline(file, line)) {
stringstream liness(line);
getline(liness, path, separator);
getline(liness, classlabel);
if (!path.empty() && !classlabel.empty()) {
images.push_back(imread(path, 0));
labels.push_back(atoi(classlabel.c_str()));
}
}
}
int main()
{
//读取你的CSV文件路径.
//string fn_csv = string(argv[1]);
string fn_csv = "D:\training\at.txt";
// 2个容器来存放图像数据和对应的标签
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);
}
// 下面的几行代码仅仅是从你的数据集中移除最后一张图片
//[gm:自然这里需要根据自己的需要修改,他这里简化了很多问题]
Mat testSample = images[images.size() - 1];
int testLabel = labels[labels.size() - 1];
images.pop_back();
labels.pop_back();
// 下面几行创建了一个特征脸模型用于人脸识别,
// 通过CSV文件读取的图像和标签训练它。
// T这里是一个完整的PCA变换
//如果你只想保留10个主成分,使用如下代码
// cv::createEigenFaceRecognizer(10);
//
// 如果你还希望使用置信度阈值来初始化,使用以下语句:
// cv::createEigenFaceRecognizer(10, 123.0);
//
// 如果你使用所有特征并且使用一个阈值,使用以下语句:
// cv::createEigenFaceRecognizer(0, 123.0);
Ptr <FaceRecognizer> model = createEigenFaceRecognizer(10);
model->train(images, labels);
model->save("MyFacePCAModel.xml");
Ptr <FaceRecognizer> model1 = createFisherFaceRecognizer(10);
model1->train(images, labels);
model1->save("MyFaceFisherModel.xml");
Ptr <FaceRecognizer> model2 = createLBPHFaceRecognizer(10);
model2->train(images, labels);
model2->save("MyFaceLBPHModel.xml");
// 下面对测试图像进行预测,predictedLabel是预测标签结果
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;
while (1);
//waitkey只对imshow有效
//if (waitKey(10) == 17) return 0;; //
//return 0;
}
4. 预测数据
加载上述训练好的训练模型,并进行估值
#include<opencv2opencv.hpp>
#include<iostream>
#include <opencv2opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>
#include <opencv2/videoio/videoio_c.h>
#include <opencv2/highgui/highgui_c.h>
#include <opencv2/face.hpp>
#include <opencv2/face/facerec.hpp>
using namespace std;
using namespace cv;
using namespace face;
int main()
{
VideoCapture cap("D:\pics\wjd.avi"); //打开默认摄像头
if (!cap.isOpened())
{
return -1;
}
Mat frame;
Mat edges;
Mat gray;
CascadeClassifier cascade;
bool stop = false;
//训练好的文件名称,放置在可执行文件同目录下
cascade.load("D:\training\training_data\haarcascade_frontalface_default.xml");
Ptr<FaceRecognizer> modelPCA = createEigenFaceRecognizer();
modelPCA->load("D:\training\training_data\MyFacePCAModel.xml");
while (!stop)
{
cap >> frame;
//frame = imread("D:\pics\test3.jpg");
if (frame.empty()) break;
//建立用于存放人脸的向量容器
vector<Rect> faces(0);
cvtColor(frame, gray, CV_BGR2GRAY);
//改变图像大小,使用双线性差值
//resize(gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR);
//变换后的图像进行直方图均值化处理
equalizeHist(gray, gray);
cascade.detectMultiScale(gray, faces,
1.1);
//, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
//| CV_HAAR_SCALE_IMAGE,
//Size(30, 30));
Mat face;
Point text_lb;
for (size_t i = 0; i < faces.size(); i++)
{
if (faces[i].height > 0 && faces[i].width > 0)
{
face = gray(faces[i]);
text_lb = Point(faces[i].x, faces[i].y);
rectangle(frame, faces[i], Scalar(255, 0, 0), 1, 8, 0);
}
}
imshow("face1", frame);
Mat face_test;
int predictPCA = 0;
if (face.rows >= 80)
{
resize(face, face_test, Size(150, 200));
}
//Mat face_test_gray;
//cvtColor(face_test, face_test_gray, CV_BGR2GRAY);
if (!face_test.empty())
{
//测试图像应该是灰度图
predictPCA = modelPCA->predict(face_test);
}
cout << predictPCA << endl;
if (predictPCA == 1)
{
string name = "liangcw";
putText(frame, name, text_lb, FONT_HERSHEY_PLAIN, 1, Scalar(0, 0, 255));
}
else if (predictPCA == 2)
{
string name = "liudh";
putText(frame, name, text_lb, FONT_HERSHEY_PLAIN, 1, Scalar(0, 0, 255));
}
else if (predictPCA == 3)
{
string name = "zyw";
putText(frame, name, text_lb, FONT_HERSHEY_PLAIN, 1, Scalar(0, 0, 255));
}
else if (predictPCA == 4)
{
string name = "zzy";
putText(frame, name, text_lb, FONT_HERSHEY_PLAIN, 1, Scalar(0, 0, 255));
}
imshow("face2", frame);
//waitKey(0);
if (waitKey(10) >= 0)
stop = true;
}
return 0;
}
5. 测试结果
优酷下载了《演员的诞生》某片段,转成avi格式,能识别出视频中的周一围、章子怡等
![](https://file2.kaopuke.com:8081/files_image/20230507/202305071452262053073.png)
6. 结论
基于openCV人脸识别的相关结构体(CascaderClassify、FacerRecognizer),训练数据越大识别效果才越好
人脸检测相关模型,如正脸、侧脸、眼睛、鼻子都是分开的,有没有联合一起的??
最后
以上就是腼腆眼睛为你收集整理的基于openCV的视频人脸识别——<<演员的诞生>>视频人脸识别的全部内容,希望文章能够帮你解决基于openCV的视频人脸识别——<<演员的诞生>>视频人脸识别所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复