OpenCV CommandLineParser未指定参数

时间:2015-10-14 14:56:54

标签: c++ opencv command-line-arguments

使用cv::CommandLineParser时,是否可以解析任意长的非标志参数列表?
例如:

> app -a -b=2 a.txt b.txt c.txt ... 

我希望能够访问所有非标记"位置" args,无需在keys规范中定义预定义数量的args。此号码仅由应用程序的呼叫者确定。

1 个答案:

答案 0 :(得分:1)

OpenCV CommandLineParser无法处理可变数量的位置参数。你可以:

  1. 传递额外的参数(例如-N),指定位置参数的数量;
  2. 将每个不以-开头的参数视为位置参数。
  3. 然后,您可以使用与cv::CommandLineParser相同的接口创建一个自定义命令行解析器,以处理可变数量的位置参数。

    选项1

    struct CustomCLP
    {
        CustomCLP(int argc, const char* const argv[], const cv::String& keys, const String& positional_id)
        {
            String pos_key = "{" + positional_id + "|0|}";
            cv::CommandLineParser pos_clp(argc, argv, pos_key);
            _N = pos_clp.get<int>(positional_id);
    
            cv::String pos_keys = keys;
            for (int i=0; i<_N; ++i)
            {
                pos_keys += "{@pos" + to_string(i) + "||}";
            }
    
            _clp = new CommandLineParser(argc, argv, pos_keys);
        }
    
        ~CustomCLP()
        {
            delete _clp;
        }
    
        bool check() const {return _clp->check();}
        bool has(const cv::String& name) const {return _clp->has(name);}
    
        template<typename T>
        T get(const String& name, bool space_delete = true) const
        {
            return _clp->get<T>(name, space_delete);
        }
        template<typename T>
        T get(int index, bool space_delete = true) const
        {
            return _clp->get<T>(index, space_delete);
        }
    
        int n_positional_args() const { return _N;}
    
    private:
        CommandLineParser* _clp;
        int _N;
    };
    

    您可以指定指定位置参数数量的额外参数(例如-N)。在构造函数中,您解析此数字,并为每个位置参数创建。然后你可以一如既往地使用它。

    选项2

    // SO: http://stackoverflow.com/a/17976541/5008845
    inline std::string trim(const std::string &s)
    {
        auto  wsfront = std::find_if_not(s.begin(), s.end(), std::isspace);
        return std::string(wsfront, std::find_if_not(s.rbegin(), std::string::const_reverse_iterator(wsfront), std::isspace).base());
    }
    
    struct CustomCLP2
    {
        CommandLineParser _clp;
        vector<std::string> pos_args;
    
    public:
        CustomCLP2(int argc, const char* const argv[], const cv::String& keys) :
            _clp(argc, argv, keys)
        {
            for (int i = 1; i < argc; ++i)
            {
                std::string s(argv[i]);
                s = trim(s);
                if (s[0] == '-') continue;
    
                pos_args.push_back(s);
            }
        }
    
        bool check() const { return _clp.check(); }
        bool has(const cv::String& name) const { return _clp.has(name); }
    
        template<typename T>
        T get(const String& name, bool space_delete = true) const
        {
            return _clp.get<T>(name, space_delete);
        }
    
        template<typename T>
        T get(int index, bool space_delete = true) const
        {
            stringstream ss;
            ss << pos_args[index];
            T t;
            ss >> t;
            return t;
        }
    
        template<>
        cv::String get(int index, bool space_delete) const
        {
            return cv::String(pos_args[index]);
        }
    
        int n_positional_args() const { return pos_args.size(); }
    };
    

    在构造函数中,保存每个不以-开头的参数。然后你可以照常检索它。

    <强>用法

    请注意,该界面与CommandLineParser一致(在此示例中,aboutgetPathToApplication等一些方法不可用,但很容易将它们添加到自定义类中。

    命令行参数是:

    Option 1: -a -b=2 -N=3 a.txt b.txt c.txt
    Option 2: -a -b=2 a.txt b.txt c.txt
    

    代码:

    #include <opencv2\opencv.hpp>
    #include <iostream>
    using namespace std;
    using namespace cv;
    
    
    struct CustomCLP
    {
        CustomCLP(int argc, const char* const argv[], const cv::String& keys, const String& positional_id)
        {
            String pos_key = "{" + positional_id + "|0|}";
            cv::CommandLineParser pos_clp(argc, argv, pos_key);
            _N = pos_clp.get<int>(positional_id);
    
            cv::String pos_keys = keys;
            for (int i=0; i<_N; ++i)
            {
                pos_keys += "{@pos" + to_string(i) + "||}";
            }
    
            _clp = new CommandLineParser(argc, argv, pos_keys);
        }
    
        ~CustomCLP()
        {
            delete _clp;
        }
    
        bool check() const {return _clp->check();}
        bool has(const cv::String& name) const {return _clp->has(name);}
    
        template<typename T>
        T get(const String& name, bool space_delete = true) const
        {
            return _clp->get<T>(name, space_delete);
        }
        template<typename T>
        T get(int index, bool space_delete = true) const
        {
            return _clp->get<T>(index, space_delete);
        }
    
        int n_positional_args() const { return _N;}
    
    private:
        CommandLineParser* _clp;
        int _N;
    };
    
    // SO: http://stackoverflow.com/a/17976541/5008845
    inline std::string trim(const std::string &s)
    {
        auto  wsfront = std::find_if_not(s.begin(), s.end(), std::isspace);
        return std::string(wsfront, std::find_if_not(s.rbegin(), std::string::const_reverse_iterator(wsfront), std::isspace).base());
    }
    
    struct CustomCLP2
    {
        CommandLineParser _clp;
        vector<std::string> pos_args;
    
    public:
        CustomCLP2(int argc, const char* const argv[], const cv::String& keys) :
            _clp(argc, argv, keys)
        {
            for (int i = 1; i < argc; ++i)
            {
                std::string s(argv[i]);
                s = trim(s);
                if (s[0] == '-') continue;
    
                pos_args.push_back(s);
            }
        }
    
        bool check() const { return _clp.check(); }
        bool has(const cv::String& name) const { return _clp.has(name); }
    
        template<typename T>
        T get(const String& name, bool space_delete = true) const
        {
            return _clp.get<T>(name, space_delete);
        }
    
        template<typename T>
        T get(int index, bool space_delete = true) const
        {
            stringstream ss;
            ss << pos_args[index];
            T t;
            ss >> t;
            return t;
        }
    
        template<>
        cv::String get(int index, bool space_delete) const
        {
            return cv::String(pos_args[index]);
        }
    
        int n_positional_args() const { return pos_args.size(); }
    };
    
    
    int main(int argc, char* argv[])
    {
        String keys =   
            "{a | | whatever a}"
            "{b | 1 | whatever b}";
    
        //CustomCLP clp(argc, argv, keys, "N");
        CustomCLP2 clp(argc, argv, keys);
    
        if (clp.has("a")) {
            cout << "Has <a>" << endl;
        }
        else {
            cout << "Doesn't have <a>";
        }
    
        int b = clp.get<int>("b");
        cout << "<b> : " << b << endl;
    
        int N = clp.n_positional_args();
    
        for (int i = 0; i < N; ++i)
        {
            cout << to_string(i) << ": " << clp.get<cv::String>(i) << endl;
        }
    
        return 0;
    }