【C++】Mat型数据写入txt文件并可用标签进行搜索读出

实习交给我的一个任务,在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);
}

这里写图片描述

猜你喜欢

转载自blog.csdn.net/shangpapa3/article/details/76180400
今日推荐