OpenCV學習筆記(23)cv.Mat 與 .txt 文件數據的讀寫操作

1、按OpenCV格式實現的 .txt 文件讀寫

可以用 cvSave 和 cvLoad 實現,格式和 .xml/.yml 的差不多,不過如果專用與 OpenCV 的數據讀寫,還是用  .xml/.yml 文件格式較好,我比較喜歡 .yml 格式,可讀性非常棒。

用 cvSave 和 cvLoad 讀寫 .txt 文件,其實現方式和數據格式與 .yml 文件基本一致。

例如:cvSave("camera_matrix.txt",camera_matrix);  //保存了 camera_matrix 的數組頭以及和它所指的data(類似yml形式的文件)


2、導入/導出其它程序的 .txt 文件數據

可以用常規的 sprintf_s 和 fprintf_s 來實現,不過效率比較低,這裏介紹一種快捷易用的方法,利用了 std 的 steam 和 vector。

 

#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>

using namespace std;

/*----------------------------
 * 功能 : 將 cv::Mat 數據寫入到 .txt 文件
 *----------------------------
 * 函數 : WriteData
 * 訪問 : public 
 * 返回 : -1:打開文件失敗;0:寫入數據成功;1:矩陣爲空
 *
 * 參數 : fileName	[in]	文件名
 * 參數 : matData	[in]	矩陣數據
 */
int 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);
}


/*----------------------------
 * 功能 : 從 .txt 文件中讀入數據,保存到 cv::Mat 矩陣
 *		- 默認按 float 格式讀入數據,
 *		- 如果沒有指定矩陣的行、列和通道數,則輸出的矩陣是單通道、N 行 1 列的
 *----------------------------
 * 函數 : LoadData
 * 訪問 : public 
 * 返回 : -1:打開文件失敗;0:按設定的矩陣參數讀取數據成功;1:按默認的矩陣參數讀取數據
 *
 * 參數 : fileName	[in]	文件名
 * 參數 : matData	[out]	矩陣數據
 * 參數 : matRows	[in]	矩陣行數,默認爲 0
 * 參數 : matCols	[in]	矩陣列數,默認爲 0
 * 參數 : matChns	[in]	矩陣通道數,默認爲 0
 */
int LoadData(string fileName, cv::Mat& matData, int matRows = 0, int matCols = 0, int matChns = 0)
{
	int retVal = 0;

	// 打開文件
	ifstream inFile(fileName.c_str(), ios_base::in);
	if(!inFile.is_open())
	{
		cout << "讀取文件失敗" << endl;
		retVal = -1;
		return (retVal);
	}

	// 載入數據
	istream_iterator<float> begin(inFile);	//按 float 格式取文件數據流的起始指針
	istream_iterator<float> end;			//取文件流的終止位置
	vector<float> inData(begin,end);		//將文件數據保存至 std::vector 中
	cv::Mat tmpMat = cv::Mat(inData);		//將數據由 std::vector 轉換爲 cv::Mat

	// 輸出到命令行窗口
	//copy(vec.begin(),vec.end(),ostream_iterator<double>(cout,"\t")); 

	// 檢查設定的矩陣尺寸和通道數
	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);
}


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章