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