模式识别数据集预处理

引言

在很多模式识别里面都有数据集的读取,需要读取文件夹下的图像。其中一种方法是先将文件夹下的图像文件路径path与类别label先写入一个.csv文件中,在训练时只需读取.csv文件即可。
  参考了一些网上的资料大致如下,但是还是比较麻烦。实则只是一个文件索引作用,不需要去遍历文件提取文件路径和文件名,自己创建一个文件索引就可以了。先放一些之前网上参考的方法。

1.DOS命令

  • win+r —> cmd;
  • cd D:\ (数据集所在盘);
  • cd 文件路径,回车;
  • 输入dir /b/s/p/w *.pgm>list.txt (文件格式看实际)

2.bat脚本

将方法一中的命令行写入TXT文档,保存后将后缀改为bat.双击即可。注:*.bat是Windows下的脚本文件,和Ubuntu下面的脚本文件*.sh一样可以批量执行命令行,很实用!
  方法1、2生成的list.txt就是train目录下所有文件和文件夹的列表;把.txt扩展名改为.csv ,使用excel打开;在文件名后面加入label。使用excel打开;在文件名后面加入label。看着这个用Excel打开手动输入标签很烦,就想着怎么将它读出来用程序自动加入标签。
 后来一想,不对啊,为啥要这么麻烦?为啥要读?直接写入txt啊!

3.CSV格式要求

逗号分隔值(Comma-SeparatedValues,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。
  CSV文件格式的通用标准并不存在,但是在RFC 4180中有基础性的描述。使用的字符编码同样没有被指定,但是7-bitASCII是最基本的通用编码。
一般情况下,CSV文件格式规则如下:

1.  开头是不留空,以行为单位。
2.  可含或不含列名,含列名则居文件第一行。
3.   一行数据不跨行,无空行。
4.  以半角逗号(即,)作分隔符,列为空也要表达其存在。
5.  列内容如存在半角逗号(即,)则用半角双引号(即"")将该字段值包含起来。
6.  列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来。
7.  文件读写时引号,逗号操作规则互逆。
8.  内码格式不限,可为 ASCII、Unicode 或者其他。
9.  不支持特殊字符

4.训练集

了解了CSV文件格式要求,就直接按照该路径格式写就是了,要什么写什么:

#include <iostream>
#include <fstream> 
#include <string.h>
using namespace std;
int main()
{
	ofstream   ofresult("D://PatternRecognition//FaceRec_vs//data//train_200.txt ", ios::app);
	int num = 1;
	for (int i = 1; i <= 200; i++)
	{
		ofresult << "D:" << "\//" << "PatternRecognition" << "\//" <<
			"FaceRec_vs" << "\//" << "data" << "\//" << "train_200" << "\//" << i << ".bmp" << " ," << num << endl;
		if (i % 5 == 0)
		{
			num++;
		}
	}
	return 0;
}

生成如图,改后缀名即可。

5.测试集

测试集要求行乱序,但是标签依然对应。路径与标签之间可以用分号可以用逗号。后面读取程序相应的作出改变就行。


#include <iostream>
#include <fstream> 
#include <string.h>
using namespace std;
int main()
{
	ofstream   ofresult("D://PatternRecognition//FaceRec_vs//data//test2_200.txt ", ios::app);
	int num = 0;
	int a[200];
	for (int i = 1; i <= 200; i++) a[i] = i;
	for (int i = 200; i >= 1; i--) swap(a[i], a[rand() % i]);
	for (int i = 1; i <= 200; i++)
	{
		if (a[i] % 5 == 0) num = a[i] / 5;
		else num = a[i] / 5 + 1;
		ofresult << "D:" << "\//" << "PatternRecognition" << "\//" <<
			"FaceRec_vs" << "\//" << "data" << "\//" << "test_200" << "\//" <<a[i]<< ".bmp" << " ," << num << endl;
	}	
	system("pause");
	return 0;
}

生成如图,改后缀名即可。

6.CSV文件读取与识别

以图片读取为例。此程序参考的opencv官方例程。

bool read_csv(const string& filename, vector<Mat>& images,
	vector<int>& labels, char separator = ',')
{
	// 以in模式(读取文件模式)打开文件 ,实际是将filename文件关联给 流file
	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(Error::StsBadArg, error_message);
	}
	string line, path, classlabel;
	//读取file文件中的一行字符串给 line
	while (getline(file, line))
	{
		//将line整行字符串读取到lines(流)中
		//区别->lines是流,读取字符时,指针会随流而动;而line是string,固定的,下文中的读取每次都是从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()));
		}
	}
	return true;
}

7.利用cmd写文件路径及名至txt

cmd命令切换到文件夹内后:
dir /b
dir /ad/s/b
dir /s/b
dir *.lib /b> List.txt   #保存*.lib的路径以及文件名

8.样本分类

#include <iostream>
#include <fstream>
#include <io.h>
#include <opencv2/opencv.hpp>

void getFile(std::string path, std::vector<std::string>& files)
{
	long hFile = 0;
	struct _finddata_t fileinfo;
	std::string p;
	if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)
	{
		do
		{
			if ((fileinfo.attrib & _A_SUBDIR))
			{
				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
					getFile(p.assign(path).append("\\").append(fileinfo.name), files);
			}
			else
			{
				files.push_back(p.assign(path).append("\\").append(fileinfo.name));
			}
		} while (_findnext(hFile, &fileinfo) == 0);
		_findclose(hFile);
	}
}

int main()
{
	std::string strFilePath = "E:\\sample\\н¨Îļþ¼Ð\\";
	std::vector<std::string> files;
	getFile(strFilePath, files);
	for (size_t i = 0; i < files.size(); i++)
	{
		cv::Mat Img = cv::imread(files.at(i));
		cv::imshow("Img", Img);
		char cKey = cv::waitKey();
		if (cKey == '1')
		{
			std::string strSaveName = "E:\\sample\\1\\" + std::to_string(i) + ".jpg";
			cv::imwrite(strSaveName, Img);
		}
		else
		{
			std::string strSaveName = "E:\\sample\\0\\" + std::to_string(i) + ".jpg";
			cv::imwrite(strSaveName, Img);
		}
	}
	return 0;
}

20220108更新

bool PointGen::readPtsFromeile(const std::string& filename, char separator = '|'){
	std::ifstream file(filename.c_str(), std::ifstream::in);
	if (!file){
		std::cout<<"open file err!"<<std::endl;
	}
	std::string line;
	while (getline(file, line)){
        std::vector<float> point;
        // stringstream 流指针,一个字符一个字符的判断
		std::stringstream line_stream(line);
        point.clear();
        for (std::array<char, 5> a; line_stream.getline(&a[0], 5, separator); ){
            std::string num_str = "";
            for(int i=0; a[i]; i++){
                num_str += a[i];
            }
            point.emplace_back(stof(num_str));
        }
        points_.emplace_back(cv::Vec3f(point[0], point[1], 0.0));
        }
	return true;
}

待读取的文件

16.8|6.6|0
17|6.6|0
17.1|6.6|0
17.2|6.6|0
17.3|6.6|0
17.4|6.6|0
17.5|6.6|0
17.6|6.6|0
17.7|6.6|0
17.8|6.6|0
17.9|6.6|0
18|6.6|0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值