1. .csv是最通用的一种文件格式,它可以非常容易地被导入各种PC表格及数据库中。此文件中,一行即为数据表的一个记录。.csv可以用记事本打开,打开后,数据之间以逗号为分隔符;.csv也可以用excel打开,显示格式与正常的excel表格数据一样,而且可以将excel文件转换为.csv文件。
2. Opencv 提供了CvMLdata类(数据类型)来读取.csv文件并进行相关的处理。由类的名字可知,该类是针对机器学习算法而提供的。
class CV_EXPORTS CvMLData
{
public:
CvMLData();
virtual ~CvMLData();
int read_csv(const char* filename); //读取 .csv文件(0–OK;-1加载失败)
const CvMat* get_values() const; //获取.csv的所有数据
const CvMat* get_responses(); //返回标签数据
const CvMat* get_missing() const; //返回缺失数据的掩膜矩阵(矩阵尺寸与get_values()相同)
void set_response_idx( int idx ); //设置标签(指定哪一列为标签)
int get_response_idx() const; //返回标签所在的列
void set_train_test_split( const CvTrainTestSplit * spl); //将读取数据集分成两个不相交的训练和测试子集.
const CvMat* get_train_sample_idx() const; //返回训练子集的样本索引矩阵
const CvMat* get_test_sample_idx() const; //返回测试子集的样本索引矩阵.
void mix_train_and_test_idx(); //该方法对训练样本(或测试样本)的索引进行置乱
const CvMat* get_var_idx();//该方法返回矩阵中使用子集(列)的索引
void chahge_var_idx( int vi, bool state ); //启用或禁用加载数据中的特定列数据(默认情况下使用读取数据集中的所有数据)但是可能只使用所有数据的一个子集,
//并使用索引vi包含/排除(取决于状态值)数据。
const CvMat* get_var_types();//返回矩阵的变量类型(CV_VAR_ORDERED or CV_VAR_CATEGORICAL)。
void set_var_types( const char* str ); //设置加载数据中的变量类型,("cat" ==categorical, //"ord"== ordered).
int get_var_type( int var_idx ) const; //返回指定变量的类型(CV_VAR_ORDERED or //CV_VAR_CATEGORICAL)
void change_var_type( int var_idx, int type); //该方法将索引为var_idx变量类型从现有类//型更改为其他类型.
void set_delimiter( char ch ); //设置用于输入数字的分隔符
char get_delimiter() const; //返回当前使用的分隔符
void set_miss_ch( char ch ); //设置用于指定缺失值的字符.
char get_miss_ch() const; //返回当前使用的缺失值字符.
const std::map<std::string, int>& get_class_labels_map() const; //返回将字符串转换为标//签的映射。该方法返回将字符串类标记转换为数值类标签的映射。它可以用来在文件中获取一个原始//类标签。
protected:
...
};
CvTrainTestSplit结构体对CvMLData读取数据的进行分裂(分为训练数据与测试数据)设置。该类提供了两种分裂形式一种是注明训练数据的个数,另一种是注明训练数据的比例。
struct CvTrainTestSplit
{
CvTrainTestSplit();
CvTrainTestSplit( int train_sample_count, bool mix = true);
CvTrainTestSplit( float train_sample_portion, bool mix = true);
union
{
int count; //训练数据的个数
float portion; //训练数据的比例
} train_sample_part;
int train_sample_part_mode;
bool mix; //是否打乱顺序
};
demo:
/*reference :http://blog.csdn.net/yeyang911/article/details/23126865*/
#include <opencv2/opencv.hpp>
#include <opencv2/opencv_modules.hpp>
#include <tchar.h>
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
CvMLData data;
int num = data.read_csv("testdata.csv"); //读取训练的数据
if(num!=0){printf("Load .csv file failed");system("pause");}
Mat a = data.get_values(); //得到全部数据
Mat miss=data.get_missing(); //返回缺失数据的掩膜矩阵
data.set_response_idx(0); //指定第一列为标签数据
Mat label = data.get_responses();//得到训练的标签
CvTrainTestSplit train(0.5f,false); //将数据分为训练数据与测试数据(0.5f为分配比例,false不置乱顺序)
data.set_train_test_split(&train); // 将数据分为训练数据与测试数据(
Mat TrainIDX = data.get_train_sample_idx(); //得到训练的样本位置,(对应第几行)
Mat TestIDX = data.get_test_sample_idx(); //得到测试的样本位置,(对应第几行)
data.change_var_idx(3, false); //禁用第三列数据
Mat VarIDX2=data.get_var_idx();//返回矩阵中使用子集(列)的索引(set_response_idx()得到训练的标签,change_var_idx())
Mat VarType=data.get_var_types(); //返回矩阵的变量类型
char Delimiter =data.get_delimiter(); //返回当前使用的分隔符
char MissChar=data.get_miss_ch(); //返回当前使用的缺失值字符.
// cout<<"得到全部数据:\n"<<a<<endl;
cout<<"-----------------------------------"<<endl;
cout<<"丢失数据:\n"<<miss<<endl;
cout<<"-----------------------------------"<<endl;
cout<<"标签:\n"<<label<<endl;
cout<<"-----------------------------------"<<endl;
cout<<"训练样本索引:\n"<<TrainIDX<<endl;
cout<<"-----------------------------------"<<endl;
cout<<"测试样本索引:\n"<<TestIDX<<endl;
cout<<"-----------------------------------"<<endl;
cout<<"使用子集(列):\n"<<VarIDX2<<endl;
cout<<"-----------------------------------"<<endl;
cout<<"分隔符:"<<Delimiter<<endl;
cout<<"-----------------------------------"<<endl;
system("pause");
return 0;
}
Opencv Mat转换为.csv文件
//Opencv Mat保存为.csv
//reference:http://blog.csdn.net/computerme/article/details/50952627
/*注:改程序将训练数据traindata.xml与标签datalabel.xml转换为.csv文件*/
#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>
#include <opencv2/ml/ml.hpp>
using namespace std;
using namespace cv;
void saveMat(cv::Mat inputMat,char* filename)
{
FILE* fpt = fopen(filename,"w");
for (int i = 0; i < inputMat.rows;i++){
for(int j = 0;j<inputMat.cols;j++){
if (j < inputMat.cols-1)
fprintf(fpt,"%f,",inputMat.at<float>(i,j));
else
fprintf(fpt,"%f\n",inputMat.at<float>(i,j));
}
}
fclose(fpt);
}
int main (){
// 读取训练数据
Mat traindata(178,13,CV_32F);
FileStorage fs("traindata.xml", FileStorage::READ);
fs["data"]>> traindata;
fs.release();
//读取标签数据
Mat Labeldata(178,1,CV_32F);
FileStorage fs2("datalabel.xml", FileStorage::READ);
if(!fs2.isOpened()){printf("Can't open file datalabel ");}
fs2["label"]>> Labeldata;
if(Labeldata.empty()){printf("Labeldata is empty");}
fs2.release();
Mat MLdata;
MLdata.push_back(Mat(Labeldata.t()));
MLdata.push_back(Mat(traindata.t()));
MLdata=MLdata.t();
saveMat(MLdata,"MLdata.csv");
system("pause");
return 0;
}
.txt文件保存为Mat
/*参考链接
*http://blog.csdn.net/eswai/article/details/53009077
*txt2mat:http://blog.csdn.net/chenyusiyuan/article/details/7974378
*.txt 文件中读入数据,保存到 cv::Mat 矩阵 */
void LoadData(string fileName, cv::Mat& matData, int matRows = 0, int matCols = 0, int matChns = 0)
{
/*----------------------------
* 功能 : 从 .txt 文件中读入数据,保存到 cv::Mat 矩阵
* - 默认按 float 格式读入数据,
* - 如果没有指定矩阵的行、列和通道数,则输出的矩阵是单通道、N 行 1 列的
*----------------------------
* 函数 : LoadData
* 访问 : public
*
* 参数 : fileName [in] 文件名
* 参数 : matData [out] 矩阵数据
* 参数 : matRows [in] 矩阵行数,默认为 0
* 参数 : matCols [in] 矩阵列数,默认为 0
* 参数 : matChns [in] 矩阵通道数,默认为 0
*/
// 打开文件
ifstream inFile(fileName.c_str(), ios_base::in);
if(!inFile.is_open()) { cout << "读取文件失败" << endl;}
// 载入数据
istream_iterator<float> begin(inFile); //按float格式取文件数据流的起始指针
istream_iterator<float> end; //取文件流的终止位置
vector<float> inData(begin,end); //将文件数据保存至 std::vector 中
cv::Mat tmpMat = cv::Mat(inData); //将数据由 std::vector 转换为 cv::Mat
// 输出到命令行窗口
//copy(inData.begin(),inData.end(),ostream_iterator<double>(cout,"\t"));
// 检查设定的矩阵尺寸和通道数
size_t dataLength = inData.size();
//1.通道数
if (matChns == 0) {
matChns = 1;
}
//2.行列数
if (matRows != 0 && matCols == 0) {
matCols = dataLength / matChns / matRows;
}
else if (matCols != 0 && matRows == 0) {
matRows = dataLength / matChns / matCols;
}
else if (matCols == 0 && matRows == 0) {
matRows = dataLength / matChns;
matCols = 1;
}
//3.数据总长度
if (dataLength != (matRows * matCols * matChns)) {
cout << "读入的数据长度 不满足 设定的矩阵尺寸与通道数要求,将按默认方式输出矩阵!" << endl;
matChns = 1;
matRows = dataLength;
}
// 将文件数据保存至输出矩阵
matData = tmpMat.reshape(matChns, matRows).clone();
}
补充:
在机器学习与图像处理的过程中通常需要存储各种中间变量或者参数,Matlab提供的.mat文件可以很方便的实现这种功能。Opencv也可以利用FileStorge类通过对XML/YAML格式文件的读写操作实现各种数据格式的存储与读取,类似于Matlab中的.mat文件。
XML与YAML是使用非常广泛的文件格式,可以利用XML/YAML格式的文件存储与还原各式各样的数据结构。也可以存储与载入任意复杂的数据结构,包括了与opencv相关的数据结构。