实习交给我的一个任务,在txt中存入Mat型数据,并且每个数据都有标签,可以一直写入,如果标签重复就不用写入了。然后可以根据标签找到对应的Mat型数据。
根据要求写了两个函数,分别为:
int WriteData(string fileName, string dataName, std::vector<cv::Mat> data);
int LoadData(string fileName, string label, cv::Mat& matData);
起初以为是检查Mat型数据是否重复,写了这个函数,大家有需要可以用,这里我没有用到。
int matIsEqual(const cv::Mat mat1, const cv::Mat mat2,int &ff)
{
ff = 0;
if (mat1.empty() && mat2.empty()) return true;
if (mat1.cols != mat2.cols || mat1.rows != mat2.rows || mat1.dims != mat2.dims ||mat1.channels() != mat2.channels()) ff = 0;
if (mat1.size() != mat2.size() || mat1.channels() != mat2.channels() || mat1.type() != mat2.type()) ff = 0;
int nrOfElements1 = mat1.total()*mat1.elemSize();
if (nrOfElements1 != mat2.total()*mat2.elemSize()) ff = 0;
if(memcmp(mat1.data, mat2.data, nrOfElements1) == 0) ff =1;
return false;
}
作为小白,代码有很多不规范的地方,欢迎批评指正
另外有一个疑问?根据标签查找Mat数据实现的过程,也就是LoadData函数有些繁琐,先将txt存入string型vector,找到标签,将下面位置的数据存入另一个int型vector,并转化成Mat型,这时候矩阵是N行1列,再进行reshape,得到想要的结果。
这样Mat型的数据只能是固定行列的,如何改进这一问题呢?
希望可以得到大神的指导。
下面直接上任务的完整代码
#include <fstream>
#include <cv.h>
using namespace std;
using namespace cv;
#define Rows 4
#define Cols 4
int WriteData(string fileName, string dataName, std::vector<cv::Mat> data);
int LoadData(string fileName, string label, cv::Mat& matData);
int main()
{
//写入主函数部分
std::vector<cv::Mat> mat;
string name = "#bbb";
cv::Mat img(4, 4, CV_8U, 4);
mat.push_back(img.clone());
WriteData("song.txt", name,mat);
//读取主函数部分
//cv::Mat Data;
//cout << "请输入格式为#aaa的字符串:" << endl;
//string str;
//cin >> str;
//LoadData("song.txt", str, Data);
//cout << Data << endl;
return 0;
}
/*----------------------------------
* 功能:将cv::Mat数据写入到 .txt 文件
*-----------------------------------*/
int WriteData(string fileName, string dataName,std::vector<cv::Mat> data)
{
int retVal = 0;
int ff = 0;
// 打开文件
ofstream outFile(fileName.c_str(), ios::app); //若存在接最后一行写入
if (!outFile.is_open())
{
cout << "打开文件失败" << endl;
retVal = -1;
return(retVal);
}
写入mat文件名
for (int i = 0; i < data.size(); i++)
{
cv::Mat matData = data[i];
//检查矩阵是否为空
if (matData.empty())
{
continue;
}
else
{
//检查标签是否重复
ifstream inFile(fileName.c_str(), ios_base::in);
if (!inFile.is_open())
{
cout << "读取文件失败" << endl;
retVal = -1;
return (retVal);
}
istream_iterator<string> begin(inFile); //按string格式取文件数据流的起始指针
istream_iterator<string> end; //取文件流的终止位置
vector<string> vec(begin, end); //将文件数据保存至 std::vector 中
vector<int> inData;
int test = 1;
for (auto it = vec.begin(); it != vec.end(); it++)
{
istringstream record(*it);
string s;
int figure = 0;
record >> s;
//寻找标签
if (s[0] = '#')
{
if (s.compare(dataName) == 0)
{
test = 0;
break;
}
}
}
// 写入数据
if (test==1)
{
outFile << dataName << endl;//换行
for (int r = 0; r < matData.rows; r++)
{
for (int c = 0; c < matData.cols; c++)
{
int num = matData.at<uchar>(r, c); //读取数据,at<type> - type 是矩阵元素的具体数据格式
outFile << num << "\t"; //每列数据用 tab 隔开
}
outFile << endl; //换行
}
}
}
}
return (retVal);
}
/*------------------------------------------
* 功能:从.txt 文件找出对应标签的cv::Mat数据
*-------------------------------------------*/
int LoadData(string fileName, string label, cv::Mat& matData)
{
int retVal = 0;
// 打开文件
ifstream inFile(fileName.c_str(), ios_base::in);
if (!inFile.is_open())
{
cout << "读取文件失败" << endl;
retVal = -1;
return (retVal);
}
//载入数据
istream_iterator<string> begin(inFile); //按string格式取文件数据流的起始指针
istream_iterator<string> end; //取文件流的终止位置
vector<string> vec(begin, end); //将文件数据保存至 std::vector 中
vector<int> inData;
int test = 1;
for (auto it = vec.begin(); it != vec.end(); it++)
{
istringstream record(*it);
string s;
int figure = 0;
record >> s;
//寻找标签
if (test == 1)
{
if (s[0] = '#')
{
if (s.compare(label) == 0)
{
test = 0;
continue;
}
else continue;
}
else continue;
}
//找到标签
else
{
while (s[0] != '#')
{
int c;
c = atoi(s.c_str());
inData.push_back(c);
break;
}
if (s[0] == '#') break;
}
}
if (test == 1)
{
cout << "对不起,标签未找到。" << endl;
retVal = 1;
return (retVal);
}
cv::Mat tmpMat = cv::Mat(inData);//将数据由 std::vector 转换为 cv::Mat
size_t dataLength = inData.size();
if (dataLength != Cols*Rows)
{
cout << "对不起,读入的数据长度不满足设定的矩阵尺寸要求。" << endl;
retVal = 1;
return (retVal);
}
else matData = tmpMat.reshape(Cols, Rows).clone(); //将文件数据保存至输出矩阵
return (retVal);
}