c++中二维数组与二维mwarray数据格式之间的相互转换

上回书说到,如何将matlab中的函数转换成可以在vs中用c++调用的dll库。但是在使用的过程中,matlab对应的函数必须要用指定的数据格式—mwarray—作为输入。问题是,c++的数据操作是按行读取,但是matlab的函数在使用mwarray过程中是按列调用数据的。笔者调用过程主要的时间精力都放在数据格式上了,这里写一点相关的心得。

最大的心得:不管按行按列,只要把mwarray的格式内容和matlab使用过程中的一模一样即可。

比如,笔者用到的一个函数输入是500x19,那只要mwarray也是500x19即可。这里的实际意义是用于决策树的输入信息,500条信息,每条信息有18维特征和1维ID。数据按列输入,也就是每次将这一维(特征)的信息全部输入。

int readInToMatrix(string FilePath)
{
	int row = 30;
	int col = 8;
	std::vector > TLabelVV,TFeatureVV;// 二位数据组
	//std::vector one_row;		//行向量
	std::vector TLabelV,TFeatureV;
	std::vector::iterator it;	//迭代器
	std::ifstream ifstr_data(FilePath);	//读文件
	//double aa = ifstr_data;
	double TF,TL;							//传值中间值	
	int row_count = 0;					//换行标记
	int line_count = 0;					//列标记

	for (line_count = 0; line_count < row; line_count++)
	{

		for (row_count = 0; row_count < col; row_count++)
		{
			if (row_count == 7)
			{
				ifstr_data >> TL;
				TLabelV.push_back(TL);//将数据压入堆栈。
			}
			else 
			{
				ifstr_data >> TF;
				TFeatureV.push_back(TF);//将数据压入堆栈。
			}	
					
		}
		TLabelVV.push_back(TLabelV);
		TFeatureVV.push_back(TFeatureV);
		TLabelV.clear();
		TFeatureV.clear();
	}	
	ifstr_data.close();

	//定义训练数据
	double * trainf = new double[210];
	int trainNum = 0;

	double * trainl = new double[30];
	//trainNum = 0;
	for (int i = 0; i < TLabelVV.size(); i++)
	{
		for (int j = 0; j < TLabelVV[0].size(); j++)
		{
			trainl[trainNum] = TLabelVV[i][j];
			trainNum++;
		}
	}

	trainNum = 0;
	for (int i = 0; i < TFeatureVV[0].size(); i++)
	{
		for (int j = 0; j < TFeatureVV.size(); j++)
		{
			trainf[trainNum] = TFeatureVV[j][i];//第一个放7.2[0][0] 下一个7.7[1][0]直到[30][0]
			trainNum++;
		}
	}
	
	mwArray TrainLabelData(trainNum / 7,1,  mxDOUBLE_CLASS, mxREAL);
	mwArray TrainFeatureData(trainNum/7,col-1,  mxDOUBLE_CLASS, mxREAL);
	TrainLabelData.SetData(trainl, 30);
	TrainFeatureData.SetData(trainf, 7*30);
}

在ICP算法中,我用的是2x650的数据格式作为输入,2是指x和y的坐标,650是点的个数。这时候和上面的情况有所不同,每次输入的是一个点的两个信息。

 vector> fun1::ICPget(vector> Modelpoint, vector> Datapoint)
  {
	  vector> dataout;
	  //将modelpoint的轮廓信息导入model
	  size_t M_n = Modelpoint.size();
	  //统计点的个数
	  int M_PointNum=0;
	  for (int i = 0; i < M_n; i++)
	  {
		  //在第i个点集组,e.g.i=0即为外轮廓
		  for (int j = 0; j < Modelpoint[i].size(); j++)
		  {	
			  M_PointNum++;
		  }
	  }
	  
	  M_PointNum = M_PointNum * 2;
	  double * M_p = new double[M_PointNum];
	  int M_num = 0;
	  //double M_p[188];
	  //不同的轮廓点集个数不同=1+内轮廓个数。若无内轮廓,i=0就解决了。
	  for (int i = 0; i < M_n; i++)
	  {
		  //在第i个点集组,e.g.i=0即为外轮廓
		  for (int j = 0; j < Modelpoint[i].size(); j++)
		  {
			  //按列写、读,x1,y1,x2,y2
			  M_p[M_num] = Modelpoint[i][j].x;
			  M_num++;
			  M_p[M_num] = Modelpoint[i][j].y;
			  M_num++;
		  }
	  }
	  
	  //将datapoint的轮廓信息导入data	  
	  size_t D_n = Datapoint.size();
	  int D_PointNum = 0;
	  for (int i = 0; i < D_n; i++)
	  {
		  //在第i个点集组,e.g.i=0即为外轮廓
		  for (int j = 0; j < Datapoint[i].size(); j++)
		  {
			  D_PointNum++;
		  }
	  }
	  
	  D_PointNum = D_PointNum * 2;

	  double * D_p = new double[D_PointNum];
	  int D_num = 0;
	  //不同的轮廓点集个数不同=1+内轮廓个数。若无内轮廓,i=0就解决了。
	  for (int i = 0; i < Datapoint.size(); i++)
	  {
		  //在第i个点集组,e.g.i=0即为外轮廓
		  for (int j = 0; j < Datapoint[i].size(); j++)
		  {
			  D_p[D_num] = Datapoint[i][j].x;
			  D_num++;
			  D_p[D_num] = Datapoint[i][j].y;
			  D_num++;
		  }
	  }
	  //为了后续计算RMS方便
      //此处选取点较少的作为model,点较多的作为data
	  //mwArray model;
	  //mwArray data;
	  if (M_num <= D_num)
	  {		  
	  }
	  else
	  {
		  int a = D_num;
		  D_num = M_num;
		  M_num = a;
	  }

	  mwArray model(2, D_num / 2, mxDOUBLE_CLASS, mxREAL);
	  mwArray data(2, M_num / 2, mxDOUBLE_CLASS, mxREAL);
	  //存放内容是MP,数量是size*2
	  model.SetData(D_p, D_num);
	  data.SetData(M_p, M_num);
	  //千万别忘了以防指针泄露 M_P要和下面的OUT比较rms后面删除
	  delete[]D_p;
}

关于mwarray数据写入和读取,可参考下文

https://blog.csdn.net/qq_29567701/article/details/84872932

你可能感兴趣的:(c++中二维数组与二维mwarray数据格式之间的相互转换)