赞
踩
环境:
- opencv3.0.0
- vs2012
- opencv_contrib3.0.0 ------ — 编译和配置点此
- ORL人脸数据库,下载地址:点此进入下载
~~
【注意事项】
!!!自己测试的图片一定要和ORL人脸数据图片的尺寸和颜色通道一模一样!!!!!!
~
~
**【工程下载】完成工程下载地址,包含数据集以及测试图片等: **
https://download.csdn.net/download/qq153471503/10370732
~~~~~~~~ 一个面孔对应一个标签,在程序中一个个读取图片和标签,那么效率很低,所以将图片路径和标签制作成一个文件,在程序中直接读取文件中的路径和标签,就能将面孔和标签对应起来。
~
下面一段python代码就是生成这个csv文件,使用方法:
~~~~~~~~python [这个python文件名] [参数一:ORL文件目录] [参数二:输出的csv文件]
~
例如我在当前工程目录下打开命令行,键入:
~~~~~~~~python create_csv.py ./faces_data/ ./at.txt
效果:这个文件就是at.txt
# -*- coding: UTF-8 -*- import os import os.path import sys if __name__ == "__main__": if len(sys.argv) != 3: print print("Input error. conmond format: \n \ python %s [images path] [output file] \n \ For example: python %s ./faces_data ./at.txt ")%(sys.argv[0], sys.argv[0]) sys.exit(0) BASE_PATH = sys.argv[1] SEPARATOR = ";" fh = open(sys.argv[2], "w") label = 0 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()
#if 1 CascadeClassifier face_cascade; //载入分类器 //加载分类训练器,OpenCv官方文档提供的xml文档,可以直接调用 //xml文档路径 opencv\sources\data\haarcascades cout << "loading haarcascade_frontalface_alt.xml..." << endl; if (!face_cascade.load("haarcascade_frontalface_alt.xml")) { cout << "load haarcascade_frontalface_alt failed!" << endl; exit(-1); } cout << "OK" << endl; Mat matTestImg = imread("test.png"); // 输入测试图像 resize(matTestImg, matTestImg, matTestImg.size()); Mat showImg; matTestImg.copyTo(showImg); vector<Rect> face_rect; vector<Mat> res = FaceDetectMultiScale(face_cascade, matTestImg, face_rect); // 多尺度检测 if (res.empty()) // 如果为空说明未检测到人脸 { cout << "failed, Please try again." << endl; exit(-1); } #if 0 for (size_t i=0; i!=res.size(); i++) { // 显示检测到的人脸 imshow("", res[i]); waitKey(0); } #endif /// 将人脸框出 for (size_t i=0; i!=face_rect.size(); i++) { rectangle(showImg, face_rect[i], Scalar(0,0,255)); } imshow("", showImg); // 显示识别结果 waitKey(0); #else
Ptr<FaceRecognizer> faceR = createEigenFaceRecognizer(); // 创建人脸特征识别器 vector<Mat> images; vector<int> labels; vector<Rect> face_rect; read_csv("at.txt", images, labels); // 读取数据集 string filename = "face_model.xml"; // 保存的文件名 // 如果定义了该宏,则不进行训练 #ifdef ALREADY_TRAIN cout << "loading " << filename + "..." << endl; faceR->load(filename); cout << "OK" << endl; #else face_train(faceR, images, labels, filename); // 训练 #endif //test(faceR, images); // 测试 //resize(tmp, tmp, Size(92, 112)); // 重新调整大小,调整到和训练数据一样的尺寸 while (true) { string filename; cout << "Please input file, enter 'q' exit: " << flush; cin >> filename; if (filename == "q") { break; } if (access(filename.c_str(), 0) < 0) { cout << filename + " not exists." << endl; continue; } Mat img = imread(filename, IMREAD_GRAYSCALE); // 读入灰度图 imwrite("img.png", img); int label = face_identify(faceR, img); printf("Identify the results: label = %d \n", label); }
由运行结果可见,预测到的标签是0, 在我创建的csv文件at.txt文件中,s1/7.pgm这个图片的标签就是0,所以识别成功!
#include <opencv2\opencv.hpp> #include <opencv\ml.h> #include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <vector> #include <opencv2/face.hpp> #include <fstream> #include <opencv2/calib3d/calib3d.hpp> #include <io.h> // for access using namespace std; using namespace cv; using namespace face; // 定义了该宏,则不需要进行人脸的训练 #define ALREADY_TRAIN /** * 读取csv文件。使用CSV文件去读图像和标签,主要使用stringstream和getline方法。 * 生成csv文件可用本工程下的create_csv.py这个python文件,使用方法: * * python create_csv.py [数据图像路径] [输出的svc文件名] * * @param filename svc文件名 * @param images 用于存储测试图像 * @param labels 存储标签 * @param separator 分隔符 */ 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, IMREAD_GRAYSCALE)); labels.push_back(atoi(classlabel.c_str())); } } } /** * 人脸训练 * * @param faceR 识别器 * @param images 图像训练集 * @param labels 标签集 * @param saveName 训练结束后保存的模型文件名 */ void face_train(Ptr<FaceRecognizer>& faceR, vector<Mat> &images, vector<int> &labels, string& saveName) { cout << "start train..." << endl; faceR->train(images, labels); // 开始训练 faceR->save(saveName); //保存训练模型 cout << "train done." << endl; } /** * 人脸识别 * * @param faceR 识别器 * @param srcImg 待测图像 * @return 预测的标签值 */ int face_identify(Ptr<FaceRecognizer>& faceR, Mat& srcImg) { int label_predict = -1; double accuracy = -1; faceR->predict(srcImg, label_predict, accuracy); // 预测 return label_predict; } /** * 测试人脸识别 * * @param faceR 识别器 * @param images 测试数据集 */ void test(Ptr<FaceRecognizer>& faceR, vector<Mat>& images) { int label_predict = -1; double accuracy = -1; for (int i=0; i!=images.size(); i++) { faceR->predict(images[i], label_predict, accuracy); // 打印预测到的标签值和准确率 printf("label_predict: %d accuracy : %f \n", label_predict, 100.0-accuracy); } } /** * 人脸多尺度检测 * * @param face 分类器 * @param inputArr 带测图像 * @param face_rect 存储识别到的人脸区域框 * @return 检测到的人脸Mat图像 */ vector<Mat> FaceDetectMultiScale(CascadeClassifier& face, Mat& inputArr, vector<Rect>& face_rect) { vector<Mat> res; Mat img_src, img_equa; img_src = inputArr; if(img_src.channels() != 1) cvtColor(img_src, img_src, CV_BGR2GRAY); // 转换为灰度图 equalizeHist(img_src, img_equa); //直方图均衡化 // 人脸检测,多尺度 face.detectMultiScale( img_equa, face_rect, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30)); for (int i=0; i!=face_rect.size(); i++) { Mat tmp; inputArr(face_rect[i]).copyTo(tmp); res.push_back(tmp); } return res; } int main() { #if 0 CascadeClassifier face_cascade; //载入分类器 //加载分类训练器,OpenCv官方文档提供的xml文档,可以直接调用 //xml文档路径 opencv\sources\data\haarcascades cout << "loading haarcascade_frontalface_alt.xml..." << endl; if (!face_cascade.load("haarcascade_frontalface_alt.xml")) { cout << "load haarcascade_frontalface_alt failed!" << endl; exit(-1); } cout << "OK" << endl; Mat matTestImg = imread("test.jpg"); // 输入测试图像 resize(matTestImg, matTestImg, matTestImg.size()); Mat showImg; matTestImg.copyTo(showImg); vector<Rect> face_rect; vector<Mat> res = FaceDetectMultiScale(face_cascade, matTestImg, face_rect); // 多尺度检测 if (res.empty()) // 如果为空说明未检测到人脸 { cout << "failed, Please try again." << endl; exit(-1); } #if 0 for (size_t i=0; i!=res.size(); i++) { // 显示检测到的人脸 imshow("", res[i]); waitKey(0); } #endif /// 将人脸框出 for (size_t i=0; i!=face_rect.size(); i++) { rectangle(showImg, face_rect[i], Scalar(0,0,255)); } imshow("", showImg); // 显示识别结果 waitKey(0); #else Ptr<FaceRecognizer> faceR = createEigenFaceRecognizer(); // 创建人脸特征识别器 vector<Mat> images; vector<int> labels; vector<Rect> face_rect; read_csv("at.txt", images, labels); // 读取数据集 string filename = "face_model.xml"; // 保存的文件名 // 如果定义了该宏,则不进行训练 #ifdef ALREADY_TRAIN cout << "loading " << filename + "..." << endl; faceR->load(filename); cout << "OK" << endl; #else face_train(faceR, images, labels, filename); // 训练 #endif //test(faceR, images); // 测试 //resize(tmp, tmp, Size(92, 112)); // 重新调整大小,调整到和训练数据一样的尺寸 while (true) { string filename; cout << "Please input file, enter 'q' exit: " << flush; cin >> filename; if (filename == "q") { break; } if (access(filename.c_str(), 0) < 0) { cout << filename + " not exists." << endl; continue; } Mat img = imread(filename, IMREAD_GRAYSCALE); // 读入灰度图 imwrite("img.png", img); int label = face_identify(faceR, img); printf("Identify the results: label = %d \n", label); } #endif system("pause"); return 0; }
ends…
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。