1. 程式人生 > >OpenCV讀取一張圖片的Mat資料型別到.txt檔案

OpenCV讀取一張圖片的Mat資料型別到.txt檔案

剛學計算機視覺,都聽老師講每一張影象都是用數字來儲存的,各種儲存方式等。然後就開始用各種數學方式對影象進行各種變換、處理,但是自己沒親眼看到資料總是感覺不太靠譜,或者自己用一些演算法時不能親眼看到它對影象中每個畫素的處理。這兩天初學OpenCV,受好奇心驅使想了解影象的最底層資料。網上查了各種資料,最終實現將一張圖片的各個點輸出到螢幕或.txt檔案。
1.在OpenCV中,我們一般使用Mat資料型別來儲存一張圖片的資料。所以我們先要了解一下Mat資料型別,可以看一下這篇博文:(OpenCV中矩陣類詳解之一:Mat)http://blog.csdn.net/holybin/article/details/17751063

或者這一篇(OpenCV中對Mat裡面depth,dims,channels,step,data,elemSize和資料地址計算的理解 )http://www.douban.com/note/265479171/
2.然後我們可以寫程式將Mat的資料輸出到控制檯視窗,看這個部落格(opencv2.x新資料結構cv::Mat訪問元素的方法):http://blog.csdn.net/moc062066/article/details/6949826 ,這篇文章的程式碼裡總共用了好幾種方法來輸出影象資料,寫的通俗易懂。
3.將所用的資料都輸出到控制檯有一個問題就是,資料量大,格式不工整,總之不便於檢視吧。所以這裡我們嘗試把它輸出到”.txt”檔案中去。這是根據第二步驟
博文中的程式碼所改寫的。原始碼如下:

#include "opencv2/opencv.hpp"  
#include <iostream>  
#include <fstream>
using namespace std;  
using namespace cv;  

int main(int argc,char** argv)  
{  

    const char* filename = "google.png";  //圖片名

    //CV_8UC3  
    //相應的CV_8SC3---Vec3s  
    //相應的CV_16UC3---Vec3w  
    Mat mat_CV_8UC3 = imread(filename,IMREAD_COLOR); //載入彩色圖
imshow("圖1",mat_CV_8UC3); ofstream File1("file1.txt", ios::out | ios::binary); for(unsigned int nrow = 0; nrow < mat_CV_8UC3.rows; nrow++) { for(unsigned int ncol = 0; ncol < mat_CV_8UC3.cols; ncol++) { Vec3i bgr = mat_CV_8UC3.at<Vec3b>(nrow,ncol);//用Vec3b也行 cout << "("<<bgr.val[0]<<"," <<bgr.val[1]<<"," <<bgr.val[2]<<")"; File1 << "("<<bgr.val[0]<<"," <<bgr.val[1]<<"," <<bgr.val[2]<<")"; } cout << endl; File1 << endl; } File1.close(); ofstream File2("file2.txt", ios::out | ios::binary); for( unsigned int nrow = 0; nrow < mat_CV_8UC3.rows; nrow++) { uchar* data = mat_CV_8UC3.ptr<uchar>(nrow); for(unsigned int ncol = 0; ncol < mat_CV_8UC3.cols * mat_CV_8UC3.channels(); ncol++) { cout << int( data[ncol] ); File2 << int( data[ncol] ); } cout << endl; File2 << endl; } File2.close(); //------CV_8UC1----------start--- Mat mat_CV_8UC1 = imread(filename,IMREAD_GRAYSCALE); //載入灰度圖 imshow("圖2",mat_CV_8UC1); ofstream File3("file3.txt", ios::out | ios::binary); for( unsigned int nrow = 0; nrow < mat_CV_8UC1.rows; nrow++) { for(unsigned int ncol = 0; ncol < mat_CV_8UC1.cols; ncol++) { uchar val = mat_CV_8UC1.at<uchar>(nrow,ncol); // cout << (int(val) > 200 ? 1 :0) ;//cout<<int(val)<< endl ; File3 << (int(val) > 200 ? 1 :0) ;//File3<<int(val)<< endl ; } cout << endl ; File3 << endl ; } File3.close(); cout << endl; ofstream File4("file4.txt", ios::out | ios::binary); for ( unsigned int row = 0 ; row < mat_CV_8UC1.rows ; ++row) { uchar* ptr = mat_CV_8UC1.ptr<uchar>(row); for ( unsigned int col = 0 ; col < mat_CV_8UC1.cols ; ++col) { cout << ( int(ptr[col]) > 200 ? 1 :0) ;//cout<<int(val)<< endl ; File4 << ( int(ptr[col]) > 200 ? 1 :0) ;//cout<<int(val)<< endl ; } cout << endl; File4 << endl; } cout << endl; MatIterator_<uchar> it = mat_CV_8UC1.begin<uchar>(), it_end = mat_CV_8UC1.end<uchar>(); for(int cnt = 1; it != it_end; ++it) { cout << ( int(*it) > 200 ? 1 : 0) ; if( (cnt++ % mat_CV_8UC1.cols) ==0 ) cout << endl; } //------CV_8UC1----------end--- waitKey(0); return 0; }

程式碼簡單,不再解釋。執行程式,得到結果如下:
這裡寫圖片描述
注意同時專案的資料夾中會生成4個新的.txt檔案,這就是將圖片資料所輸出到的檔案,如圖這裡寫圖片描述
這裡我們用記事本開啟的話,會是這個樣子(開啟”file4.txt”):這裡寫圖片描述
它顯示出來的格式並不規整,並沒有如我們所寫的影象中的每一行畫素對應檔案的每一行資料。我們可以嘗試用windows自帶的寫字板開啟,這樣格式是正確的:
這裡寫圖片描述
不過個人感覺最好的方法還是用UltraEdit啦:
這裡寫圖片描述
好,就到這裡,歡迎多多交流。
本文於2015年12月9日作以下更改
這兩天讀淺墨的書,看到第4章《基礎影象容器MAT》這一塊,發現這樣輸出影象矩陣可能會方便(對以程式碼作修改):

    ......
//方法一
    ofstream File1("file1.txt", ios::out | ios::binary);
    File1 << format(mat_CV_8UC3, "python");//一句話搞定,使用Python風格輸出
    File1.close();
    ......

結果如下:
這裡寫圖片描述