プログラムの設定ファイルとしてYAML形式のファイルが良さそうかなと思ったのですが、読み込みの実装方法を調べてみました。GitHubにいろいろと独自のライブラリが公開されているのですが、何とOpenCVで簡単に実現が出来たのですね。全然知らなくて、こんな身近な方法で実現出来るとは驚きました。
簡単にサンプル的な実装をしたので、ソースコードをご紹介します。環境はWindows上でVisual Studio 2019を用いています。
ソースコードは以下のような感じです。
#include <iostream> #include <string> #include <filesystem> #include <vector> #include "boost/program_options.hpp" #include "opencv2/core.hpp" namespace fs = std::filesystem; namespace po = boost::program_options; int main (int argc, char** argv) { po::options_description opt("Options"); opt.add_options() ("help,h", "Help") ("conf", po::value<std::string>(), "Configuration file path"); po::variables_map vm; try { po::store(po::parse_command_line(argc, argv, opt), vm); } catch (const boost::program_options::error_with_option_name& e) { std::cout << e.what() << std::endl; } po::notify(vm); if (vm.count("help")) { std::cout << opt << std::endl; exit(-1); } // YAMLファイルへのパスを引数から取得する const std::string config_filename = vm["conf"].as<std::string>(); std::cout << "Reading: " << config_filename << std::endl; // YAMLファイルを読み込むためのFileStorageインスタンスを生成 cv::FileStorage fs; // YAMLファイルの読み込み fs.open(config_filename, cv::FileStorage::Mode::READ | cv::FileStorage::Mode::FORMAT_YAML, "Shift_JIS"); if (!fs.isOpened()) { std::cerr << "Failed to open " << config_filename << std::endl; return -1; } // count を取得 int count; fs["count"] >> count; std::cout << "count " << count << std::endl; // images を取得 cv::FileNode n = fs["images"]; if (n.type() != cv::FileNode::SEQ) { std::cerr << "images is not a sequence!" << std::endl; return -1; } // 取得したimagesの要素をvectorに格納 std::vector<std::string> images; cv::FileNodeIterator it = n.begin(), it_end = n.end(); for (; it != it_end; ++it) { images.emplace_back((std::string)*it); } for (auto img : images) { std::cout << "image " << img << std::endl; } // parameters のparam1とparam2を取得 int param1, param2; n = fs["parameters"]; n["param1"] >> param1; n["param2"] >> param2; std::cout << "param1 " << param1 << std::endl; std::cout << "param2 " << param2 << std::endl; // Mat型のrotationとtranslationを取得 cv::Mat R, T; fs["rotation"] >> R; fs["translation"] >> T; std::cout << "rotation = " << R << std::endl; std::cout << "translation = " << T << std::endl; return 0; }
今回の実験用に用意したYAMLファイルの中身は下記です。
%YAML:1.0 count: 1000 images: - "DSC0001.jpg" - "DSC0002.jpg" - "DSC0003.jpg" parameters: param1: 1 param2: 2 rotation: # Rotation Matrix rows: 3 cols: 3 dt: d data: [ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 ] translation: # Translation Vector rows: 3 cols: 1 dt: d data: [ 0.0, 0.0, 0.0 ]