2012年7月4日水曜日

cv::Mat_をテキストファイルに保存・読み込み

 XML/YAML形式でのデータ保存/読み込み方法は紹介されているが,そんなややこしいフォーマット使いたくない,という人向け.

使い方
cv::Mat_<double> mat = (cv::Mat_<double>(3, 2) <<
    1.23, 1.23,
    1.23, 1.23,
    1.23, 1.23);
writeTxt("mat.txt", mat);
readTxt("mat.txt", mat);

フォーマット

行列の要素を見た目のままの配列で保存する.
  • ヘッダー無し
  • 列:スペース区切り
  • 行:改行区切り 
1.23 1.23
1.23 1.23
1.23 1.23

必要なヘッダファイル

だぶんこれで全部だと思う.
#include <opencv2/opencv.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#include <fstream> 

データの保存
フォーマットがシンプルなので特別な処理は何もない.
template<typename Type>
bool writeTxt(const std::string filename, const cv::Mat_<Type> & mat)
{
    using std::string;
    string line;
    std::ofstream ofs(filename.c_str());
    if(!ofs)
    {
        std::cout << boost::format(" cannot open %s\n") % filename;
        return false;
    }
 
    for(int j=0; j<mat.rows; j++)
    {
        for(int i=0; i<mat.cols; i++)
        {
            ofs << mat(j, i);
            if(i < mat.cols - 1) ofs << " ";
            if(i == mat.cols - 1) ofs << "\n";
        }
    }
    return true;
}

データの読み込み 

読み込み時は,行列の行数に応じてcv::Mat_のサイズを変える必要があるのでpush_backを使う.
列数も同様のboost::splitとboost::lexical_castを使う.
template<typename Type>
bool readTxt(const std::string filename, cv::Mat_<Type> & mat)
{
    using std::string;
    string line;
    std::ifstream ifs(filename.c_str());
    if(!ifs)
    {
        std::cout << boost::format(" cannot open %s\n") % filename;
        return false;
    }
 
    mat = cv::Mat_<Type>();
 
    while( getline(ifs, line))
    {
        boost::trim(line);
        std::list<std::string> results;
        boost::split(results, line, boost::is_any_of(" \t"),
            boost::token_compress_on);
 
        cv::Mat_<Type> row(1, results.size());
        std::list<std::string>::iterator iter = results.begin();
        std::list<std::string>::iterator tail = results.end();
        for(int i=0; iter != tail; ++iter, i++)
        {
            row(i) =  boost::lexical_cast<Type>(*iter);
        }
 
        mat.push_back(row);
    }
    return true;
}; 

課題
  • 高速化
  • エラー処理
参考ページ