Easy-PR学习笔记(四):学习收获

一个好的框架对应于一个完整的工程,学习Easy-PR框架现阶段收获如下:

1、如何读取一个文件路径下所有图片的路径

这里使用的是<io.h>中的_finddata_t 结构体,可以参考麒麟川的博客:_finddata_t用法

_finddata_t 结构体如下:

struct _finddata_t
{
	// 文件属性的存储位置:_A_ARCH(存档)、 _A_HIDDEN(隐藏)、
	// _A_NORMAL(正常)、_A_RDONLY(只读)、_A_SUBDIR(文件夹)、
	// _A_SYSTEM(系统) 
	unsigned attrib;  
	// 文件创建时间
	time_t time_create;
	// 文件最后一次访问时间
	time_t time_access;
	// 文件最后一次被修改的时间
	time_t time_write;
	// 文件大小
	_fsize_t size;
	// 文件名
	char name[_MAX_FNAME];
};

主要用到_findfirst()、_findnext()和_fineclose()三个接口,三个接口如下:

_findfirst()函数:

long _findfirst( char *filespec, struct _finddata_t *fileinfo );

_findfirst 查找文件,如果查找成功,返还一个唯一编号,反之,返还-1

_findnext()函数:

int _findnext( long handle, struct _finddata_t *fileinfo );

查找handle对应路径下文件,文件信息存入fileinfo中,若查找成功返回0,反之返回-1。

_findclose()函数:

int _findclose( long handle );

查找结束后,关闭文件句柄。

测试程序如下:

#include <opencv2/opencv.hpp>
#include <string>
#include <vector>
#include <io.h>	   // read file 

using namespace cv;
using namespace cv::ml;
using namespace std;

vector<string> getFiles(const string & folder,
	const bool all = true)
{
	vector<string> files;
	list<string> subfolders;
	subfolders.push_back(folder);
	while (!subfolders.empty())
	{
		string current_folder(subfolders.back());
		if (*(current_folder.end() - 1) != '/')
		{
			current_folder.append("/*");
		}
		else
		{
			current_folder.append("*");
		}

		subfolders.pop_back();

		struct _finddata_t file_info;
		// _findfirst 查找文件,如果查找成功,返还一个唯一编号,反之,返还-1
		auto file_handler = _findfirst(current_folder.c_str(), &file_info);

		while (file_handler != -1)
		{
			if (all && (!strcmp(file_info.name, ".") || !strcmp(file_info.name, "..")))
			{
				if (_findnext(file_handler, &file_info) != 0)break;
				continue;
			}

			// 如果是一个文件夹
			if (file_info.attrib & _A_SUBDIR)
			{
				if (all)
				{
					// 获取子文件夹名
					string folder_t(current_folder);
					folder_t.pop_back();
					folder_t.append(file_info.name);

					subfolders.push_back(folder_t.c_str());
				}
			}
			else
			{
				string file_path;
				// assign:将原字符串清空,然后赋予新的值
				// pop_back:删除字符串最后一个字符
				file_path.assign(current_folder.c_str()).pop_back();
				file_path.append(file_info.name);

				files.push_back(file_path);

			}

			if (_findnext(file_handler, &file_info) != 0) break;

		}  // end while

		_findclose(file_handler);

	}

	return files;

}

int main()
{

	vector<string> names;
	string folder = "has/test";
	names = getFiles(folder);

	for (int i = 0; i < names.size(); i++)
	{
		cout << i << "-th  picture is: " << names[i] << endl;
	}

	
	system("pause");
	return 0;


}

效果如下:


这样就可以在windows系统下指定文件路径下的所有文件的绝对路径。

2、训练SVM+HOG的分类器

HOG特征提取代码为:

void getHOGFeature(const Mat& image, Mat& features)
{
	HOGDescriptor hog(cvSize(128, 64), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 3); //these parameters work well
	vector<float> descriptor;

	// resize input image to (128,64) for compute
	Size dsize = Size(128, 64);
	Mat trainImg = Mat(dsize, CV_32S);
	resize(image, trainImg, dsize);

	// compute descripter
	hog.compute(trainImg, descriptor, Size(8, 8));

	// copy the result
	Mat mat_feature(descriptor);
	mat_feature.copyTo(features);
	//mat_feature.reshape(1, 1);
	//mat_feature.convertTo(features, CV_32FC1);
}

读入训练集图片后,分别提取每个样本的HOG特征,然后转换成训练SVM所需要的数据格式:CV_32FC1

int main()
{
	string folder_has_train = "has/train";
	auto has_file_train_list = getFiles(folder_has_train);
	random_shuffle(has_file_train_list.begin(), has_file_train_list.end());

	string folder_has_test = "has/test";
	auto has_file_test_list = getFiles(folder_has_test);
	random_shuffle(has_file_test_list.begin(), has_file_test_list.end());

	string folder_no_train = "no/train";
	auto no_file_train_list = getFiles(folder_no_train);
	random_shuffle(no_file_train_list.begin(), no_file_train_list.end());

	string folder_no_test = "no/test";
	auto no_file_test_list = getFiles(folder_no_test);
	random_shuffle(no_file_test_list.begin(), no_file_test_list.end());

	vector<TrainItem> train_file_list_;


	fprintf(stdout, ">> Collecting train data...\n");

	for (auto file : has_file_train_list)
		train_file_list_.push_back({ file, 1 });

	for (auto file : no_file_train_list)
		train_file_list_.push_back({ file, 0 });

	auto train_data = convertData(train_file_list_);   // 转换成opencv需要的SVM数据格式

	// create SVM classifier
	Ptr<SVM> _svm = SVM::create();
	_svm->setType(SVM::C_SVC);
	_svm->setKernel(SVM::CHI2);
	_svm->setDegree(0.1);
	_svm->setGamma(0.1);
	_svm->setCoef0(0.1);
	_svm->setC(1);
	_svm->setNu(0.1);
	_svm->setTermCriteria(cvTermCriteria(CV_TERMCRIT_ITER, 20000, 0.0001));

	auto start_time = static_cast<long>(cv::getTickCount());

	_svm->trainAuto(train_data, 10, SVM::getDefaultGrid(SVM::C),
		SVM::getDefaultGrid(SVM::GAMMA), SVM::getDefaultGrid(SVM::P),
		SVM::getDefaultGrid(SVM::NU), SVM::getDefaultGrid(SVM::COEF),
		SVM::getDefaultGrid(SVM::DEGREE), true);

	auto end_time = static_cast<long>(cv::getTickCount());

	cout << "VarCount: " << _svm->getVarCount() << endl;

	fprintf(stdout, ">> Training done. Time elapse: %ldms\n", end_time - start_time);
	fprintf(stdout, ">> Saving model file...\n");

	_svm->save("model/svm.xml");

	fprintf(stdout, ">> Your SVM Model was saved to model/svm.xml\n");
}
训练完毕后,会在model路径下生成模型文件:svm.xml

猜你喜欢

转载自blog.csdn.net/sinat_31425585/article/details/80627048
今日推荐