当前位置:   article > 正文

Opencv人脸识别学习记录_基于opencv人脸识别系统中csv文件是怎么创建的

基于opencv人脸识别系统中csv文件是怎么创建的

Opencv人脸识别学习记录】


环境:

  1. opencv3.0.0
  2. vs2012
  3. opencv_contrib3.0.0 ------ — 编译和配置点此
  4. ORL人脸数据库,下载地址:点此进入下载
       ~~   
    【注意事项】
    !!!自己测试的图片一定要和ORL人脸数据图片的尺寸和颜色通道一模一样!!!!!!
      ~  
      ~  
    **【工程下载】完成工程下载地址,包含数据集以及测试图片等: **
    https://download.csdn.net/download/qq153471503/10370732
    这里写图片描述

1、制作csv文件

         ~~~~~~~~         一个面孔对应一个标签,在程序中一个个读取图片和标签,那么效率很低,所以将图片路径和标签制作成一个文件,在程序中直接读取文件中的路径和标签,就能将面孔和标签对应起来。
  ~  
下面一段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()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

2、人脸检测代码

#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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

效果

这里写图片描述


3、人脸识别代码

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);
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

效果

这里写图片描述

由运行结果可见,预测到的标签是0, 在我创建的csv文件at.txt文件中,s1/7.pgm这个图片的标签就是0,所以识别成功!


3、完整代码

#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;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241

ends…

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/373338?site
推荐阅读
相关标签
  

闽ICP备14008679号