OpenCV學習(6) 文件和Mat之間的數據交換


      有時候為了便於調試算法,我們需要從文本文件或二進制文件中讀取數據,並把數據放到相應的矩陣中去。我們通常可以通過下面的函數實現。

 

1、從二進制文件中讀取數據。

     新建一個txt文件 input.txt,在vs2010中,右鍵點擊該文件,選擇open with,然后選擇Binary Editor,就可以用二進制的方式打開文件了。

imageimage

image

編輯文件並保存之后,我們可以用下面的函數把數據讀入到矩陣中去。

int gMophEx::LoadData(string fileName, cv::Mat& matData, int matRows, int matCols, int matChns) 

    int retVal = 0; 
 
    // 打開文件 
    ifstream inFile(fileName.c_str(), ios_base::in); 
    if(!inFile.is_open()) 
    { 
        cout << "讀取文件失敗" << endl; 
        retVal = -1; 
        return (retVal); 
    } 
 
    // 載入數據 
    istream_iterator<uchar> begin(inFile);   //按 uchar 格式取文件數據流的起始指針 
    istream_iterator<uchar> end;         //取文件流的終止位置 
    vector<uchar> inData(begin,end);      //將文件數據保存至 std::vector 中 
    cv::Mat tmpMat = cv::Mat(inData);       //將數據由 std::vector 轉換為 cv::Mat  
  
   // 檢查設定的矩陣尺寸和通道數 
    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; 
        retVal = 1; 
        matChns = 1; 
        matRows = dataLength; 
    }  
 
    // 將文件數據保存至輸出矩陣 
    matData = tmpMat.reshape(matChns, matRows).clone(); 
     
    return (retVal); 
}
 

2. 從文本文件中讀取數據 

     上面的代碼可以用來裝入二進制文件,但是二進制文件不直觀,而且二進制編輯器每行只顯示16個ascii碼,不方便編輯。所以我另外寫了一個函數用來裝入文本文件(第一個函數代碼來自網絡搜索)。

比如下面的txt文件,input2.txt,每行、每列的數據都是和矩陣中元素一一對應的,而且兩個元素之間用空格分開,這樣可以便於我們編輯輸入文件,也便於讀取。

0    1    2    3    4    5    6    7    8    9    10    11    12    13    14    15
16    17    18    19    20    21    22    23    24    25    26    27    28    29    30    31
32    33    34    35    36    37    38    39    40    41    42    43    44    45    46    47
48    49    50    51    52    53    54    55    56    57    58    59    60    61    62    63
64    65    66    67    68    69    70    71    72    73    74    75    76    77    78    79
80    81    82    83    84    85    86    87    88    89    90    91    92    93    94    95
96    97    98    99    100    101    102    103    104    105    106    107    108    109    110    111
112    113    114    115    116    117    118    119    120    121    122    123    124    125    126    127
128    129    130    131    132    133    134    135    136    137    138    139    140    141    142    143
144    145    146    147    148    149    150    151    152    153    154    155    156    157    158    159
160    161    162    163    164    165    166    167    168    169    170    171    172    173    174    175
176    177    178    179    180    181    182    183    184    185    186    187    188    189    190    191
192    193    194    195    196    197    198    199    200    201    202    203    204    205    206    207
208    209    210    211    212    213    214    215    216    217    218    219    220    221    222    223
224    225    226    227    228    229    230    231    232    233    234    235    236    237    238    239
240    241    242    243    244    245    246    247    248    249    250    251    252    253    254    255

我們可以通過下面函數把數據裝入到矩陣中:

int gMophEx::LoadDataTxt(string fileName, cv::Mat& matData, int matRows, int matCols, int matChns) 
    { 
    cv::Mat tmpMat;
    //channel一般為3或1
    if(matChns == 3)
       tmpMat= cv::Mat(matRows, matCols, CV_8UC3, cv::Scalar(0,0,0) );      
    else
      tmpMat= cv::Mat(matRows, matCols, CV_8UC1, cv::Scalar(0) );

    //打開文件
    FILE *fp;
    char str[80];
    if((fp = fopen(fileName.c_str(),"r"))==NULL) {
        printf("cannot open file.\n");
        }

    int tt1, tt2, tt3;
    int row = 0;
    int col  = 0;
    while(!feof(fp))
        {
        if(matChns == 3)
            {
            fscanf(fp,"%s",str);
            sscanf(str, "%d", &tt1);
            fscanf(fp,"%s",str);
            sscanf(str, "%d", &tt2);
            fscanf(fp,"%s",str);
            sscanf(str, "%d", &tt3);
            if(tt1 > 255) tt1 = 255;
            if(tt1 < 0) tt1 =0;
            if(tt2 > 255) tt2 = 255;
            if(tt2 < 0) tt2 =0;
            if(tt3 > 255) tt3 = 255;
            if(tt3 < 0) tt3 =0;

            }
        else
            {
            fscanf(fp,"%s",str);
            sscanf(str, "%uc", &tt1);
            if(tt1 > 255) tt1 = 255;
            if(tt1 < 0) tt1 =0;
            tmpMat.at<uchar>(row, col) = tt1;
            col++;
            if(col == matCols) { col = 0; row++;}
            if(row == matRows) break;

            }

        }
    fclose(fp);

   // 將文件數據保存至輸出矩陣 
    matData = tmpMat.reshape(matChns, matRows).clone(); 

    return 1;
    }
 

3. 把矩陣中的數據以文本文件的方式輸出

int gMophEx::WriteData(string fileName, cv::Mat& matData) 
    { 
    int retVal = 0; 

    // 檢查矩陣是否為空 
    if (matData.empty()) 
        { 
        cout << "矩陣為空" << endl;  
        retVal = 1; 
        return (retVal); 
        } 

   // 打開文件 
    ofstream outFile(fileName.c_str(), ios_base::out);  //按新建或覆蓋方式寫入 
    if (!outFile.is_open()) 
        { 
        cout << "打開文件失敗" << endl;  
        retVal = -1; 
        return (retVal); 
        } 

    // 寫入數據 
    for (int r = 0; r < matData.rows; r++) 
        { 
        for (int c = 0; c < matData.cols; c++) 
            { 
            int data = matData.at<uchar>(r,c);    //讀取數據,at<type> - type 是矩陣元素的具體數據格式 
            outFile << data << "\t" ;   //每列數據用 tab 隔開 
            } 
        outFile << endl;  //換行 
        } 

    return (retVal); 
    }
 

4.  簡單的在控制台打印矩陣

void gMophEx::PrintMat(cv::Mat& M)
    {
    int i, j;

    for(i=0; i< M.rows; i++)
        {
        for(j=0; j<M.cols*M.elemSize(); j++)
            {
            printf ("%d ", M.data[i*M.rows*M.elemSize() + j]);
            }
        printf("\n");
        }

    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM