加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

OpenCV下的CSV文件读、写

发布时间:2020-12-14 02:41:08 所属栏目:大数据 来源:网络整理
导读:1.CSV文件格式简介 ? ?? 逗号分隔值 (Comma-SeparatedValues,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV

1.CSV文件格式简介

? ??逗号分隔值(Comma-SeparatedValues,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。

? ??CSV文件格式的通用标准并不存在,但是在RFC 4180中有基础性的描述。使用的字符编码同样没有被指定,但是7-bitASCII是最基本的通用编码。

? ??一般情况下,CSV文件格式规则如下:

? ??1.? 开头是不留空,以行为单位。

? ??2.? 可含或不含列名,含列名则居文件第一行。

? ??3.? ?一行数据不跨行,无空行。

? ??4.? 以半角逗号(即,)作分隔符,列为空也要表达其存在。

? ??5.? 列内容如存在半角逗号(即,)则用半角双引号(即"")将该字段值包含起来。

? ??6.? 列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来。

? ??7.? 文件读写时引号,逗号操作规则互逆。

? ??8.? 内码格式不限,可为 ASCII、Unicode 或者其他。

? ??9.? 不支持特殊字符

2. Mat矩阵数据存储到CSV文件中

? ? 博文“C++读写CSV文件”提出了一种CSV文件的读取遍历算法和写入算法,http://www.cnblogs.com/snake-hand/p/3170483.html,并利用C++实现了对CSV文件的读、写操作。

? ??本文结合OpenCV的CSV风格格式化输出与流缓冲重定向,比较巧妙地实现了“将Mat 矩阵数据存储到CSV文件”功能。

代码如下:

//保存cout流缓冲区指针
	streambuf *coutBuf = cout.rdbuf();
	fstream matData("E:Testdatafire_2.csv",ios::out|ios::trunc);
	if(!matData){
		cerr<<"File open or create error!"<<endl;
		exit(1);
	}
	//获取文件fire.csv的流缓冲区指针
	streambuf *fileBuf = matData.rdbuf();
	//设置cout流缓冲区指针为文件的流缓冲区指针
	cout.rdbuf(fileBuf);
	cout<<format(svmMat,"csv");
	matData.flush();
	matData.close();
	//恢复cout原来的流缓冲区指针
	cout.rdbuf(coutBuf);

测试结果:


3.从CSV文件读取数据到Mat 矩阵

? ??以下代码为我自己写的read_csv函数,实现了从CSV文件读取数据到Mat矩阵中的功能。

/**
*函数功能:将csv文件数据提取到Mat类型矩阵中
*输入:filepath 文件路径数组指针;img_size Mat类型数据的Size;img_type Mat类型数据的类型(32FC1)
*返回值:Mat 矩阵
*/
Mat read_csv(const char *filepath,Size img_size,int img_type)
{
	Mat image;
	image.create(img_size,img_type);
	string pixel;

	ifstream file(filepath,ifstream::in);
	if (!file)
		cout << "CSV read fail" << endl;

	int nl= image.rows;  // number of lines   
	int nc= image.cols ; // number of columns   
	int eolElem = image.cols - 1;		//每行最后一个元素的下标
	int elemCount = 0;
	if (image.isContinuous())
	{   
		nc= nc*nl;    // then no padded pixels   
		nl= 1;		  // it is now a 1D array   
	}  
	for (int i = 0; i<nl; i++)
	{
		float* data = (float*)image.ptr<ushort>(i);  
		for (int j = 0; j < nc; j++)
		{  
			if(elemCount == eolElem){
				getline(file,pixel,'n');				//任意地读入,直到读到delim字符 'n',delim字符不会被放入buffer中
				data[j] = (float)atof(pixel.c_str());	//将字符串str转换成一个双精度数值并返回结果
				elemCount = 0;							//计数器置零
			}
			else{
				getline(file,',');				//任意地读入,直到读到delim字符 ','delim字符不会被放入buffer中
				data[j] = (float)atof(pixel.c_str());	//将字符串str转换成一个双精度数值并返回结果
				elemCount++;
			}
		}                  
	}
	return image;
}
测试结果:


注意事项:

? ? 注意每一个记录结束时以’n’结尾,而非’,’因此需要特别处理。

OpenCV?的实现:

? ??在我调用read_csv函数时,发现OpenCV已经有实现类似功能的函数:intCvMLData::read_csv(const char* filename)。利用CMake编译OpenCV,点击鼠标右键->转到定义可以方便查看opencv的源代码。(具体方法见以下链接博文)http://www.voidcn.com/article/p-heydxbeh-bey.html

实现一:

? ??例程Fisherfaces in OpenCV中的read_csv函数

static 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 thegiven filename.";
        CV_Error(CV_StsBadArg,error_message);
    }
    string line,path,classlabel;
    while(getline(file,line)) {
        stringstream liness(line);
        getline(liness,separator);
        getline(liness,classlabel);
        if(!path.empty()&& !classlabel.empty()) {
            images.push_back(imread(path,0));
           labels.push_back(atoi(classlabel.c_str()));
        }
    }
}

实现二:int CvMLData::read_csv(const char* filename)

int CvMLData::read_csv(constchar* filename)
{
    const int M = 1000000;
    const char str_delimiter[3] = { '',delimiter,'' };
    FILE* file = 0;
    CvMemStorage* storage;
    CvSeq* seq;
    char *ptr;
    float*el_ptr;
    CvSeqReader reader;
    intcols_count = 0;
    uchar *var_types_ptr = 0;
    clear();
    file = fopen( filename,"rt" );
    if( !file )
        return-1;
    // read the firstline and determine the number of variables
    std::vector<char>_buf(M);
    char* buf =&_buf[0];
    if(!fgets_chomp( buf,M,file ))
    {
        fclose(file);
        return-1;
    }
    ptr = buf;
    while( *ptr== ' ' )
        ptr++;
    for( ; *ptr!= ''; )
    {
        if(*ptr== delimiter || *ptr == ' ')
        {
            cols_count++;
            ptr++;
            while(*ptr == ' ' ) ptr++;
        }
        else
            ptr++;
    }
    cols_count++;
    if (cols_count == 0)
    {
        fclose(file);
        return-1;
    }
    // createtemporary memory storage to store the whole database
    el_ptr = newfloat[cols_count];
    storage = cvCreateMemStorage();
    seq = cvCreateSeq( 0,sizeof(*seq),cols_count*sizeof(float),storage );
    var_types = cvCreateMat( 1,cols_count,CV_8U );
    cvZero( var_types );
    var_types_ptr = var_types->data.ptr;
    for(;;)
    {
        char*token = NULL;
        inttype;
        token = strtok(buf,str_delimiter);
        if(!token)
            break;
        for (int i = 0; i < cols_count-1; i++)
        {
            str_to_flt_elem( token,el_ptr[i],type);
            var_types_ptr[i] |= type;
            token = strtok(NULL,str_delimiter);
            if(!token)
            {
                fclose(file);
                delete[] el_ptr;
                return-1;
            }
        }
        str_to_flt_elem( token,el_ptr[cols_count-1],type);
        var_types_ptr[cols_count-1] |= type;
        cvSeqPush( seq,el_ptr );
        if(!fgets_chomp( buf,file ) )
            break;
    }
    fclose(file);
    values = cvCreateMat( seq->total,CV_32FC1 );
    missing = cvCreateMat( seq->total,CV_8U );
    var_idx_mask = cvCreateMat( 1,values->cols,CV_8UC1 );
    cvSet( var_idx_mask,cvRealScalar(1) );
    train_sample_count = seq->total;
 
    cvStartReadSeq( seq,&reader );
    for(int i = 0; i < seq->total; i++ )
    {
        const float* sdata = (float*)reader.ptr;
        float*ddata = values->data.fl + cols_count*i;
        uchar* dm = missing->data.ptr +cols_count*i;
        for( int j = 0; j < cols_count; j++ )
        {
            ddata[j] = sdata[j];
            dm[j] = ( fabs( MISS_VAL - sdata[j]) <= FLT_EPSILON );
        }
        CV_NEXT_SEQ_ELEM( seq->elem_size,reader );
    }
    if (cvNorm( missing,CV_L1 ) <= FLT_EPSILON )
        cvReleaseMat( &missing );
    cvReleaseMemStorage( &storage );
    delete[]el_ptr;
    return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读