【CommandLineParser类】opencv库中的命令行解析类
CommandLineParser类用于命令行解析,可以在程序文件中直接调用参数。
1. 构造函数
cv::CommandLineParser::CommandLineParser( int argc,
const char *const argv[],
const String & keys )
- argc:命令行参数的数量
- argv:命令行参数的数组
- keys:描述可接受的命令行参数的字符串
keys是一个字符串,包含多个块,每一个都被装在大括号里且描述一个参数。每个参数都被“ | ”符号分隔成三部分。 第一部分是参数名称。 第二部分是参数的默认值,可以为空。 第三部分是描述该参数的帮助信息,可以为空。
格式:
参数或指令的名称 | 参数或指令的内容 | 说明
const String keys =
"{low |20 | low threshold }"
"{high |40 | high threshold }"
"{mode |1 | same as cv::findContours }" ;
2. 常用函数
1. get() : 获取指令名称的参数值
- name 指令名称
- space_delete 此参数默认为true,把参数内容中的头尾的空格去掉。
template <typename T>
T get(const String& name, bool space_delete = true) const
{
T val = T();
getByName(name, space_delete, ParamType<T>::type, (void*)&val);
return val;
}
template <typename T>
T get(int index, bool space_delete = true) const
{
T val = T();
getByIndex(index, space_delete, ParamType<T>::type, (void*)&val);
return val;
}
2. has() : 查看是否有此指令名称,返回bool类型
备注: 此函数本质上是检查两个东西: 1、此指令是否存在 2、此指令对应的指令内容存在; 以上二者都存在,返回true;
所以,只要在命令行输入此值令,并且指令存在,一定返回ture.(因为如果不指定参数内容,系统会默认true)
但是,在构造函数key_map中,如果指令参数没有填写。即使key_map中存在此指令,也会返回false。(因为没有参数内容)(另外;前提是命令行没有输入此指令)
bool has(const String& name) const;
3. check() : 查看指令是否有错误,无法解析
bool check() const;
4. about() : 输出指定内容
void about(const String& message);
5. printMessage() : 打印参考内容
void printMessage() const
6. printErrors() : 打印错误
void printErrors() const;
3. 简明应用
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, const char ** argv)
{
const String keys =
"{help h usage ? | | print this message }"
"{@test | | image for edge detection }"
"{@output |edge.tiff | image for draw contours }"
"{@data | | edges data in txt format }"
"{low |20 | low threshold }"
"{high |40 | high threshold }"
"{mode |1 | same as cv::findContours }"
"{alpha |1.0 | gaussian alpha }";
CommandLineParser parser(argc, argv, keys);
parser.about("print anything you want");
if (!parser.check())
{
parser.printErrors();
return 0;
}
if (parser.has("help"))
{
parser.printMessage();
return 0;
}
if (!parser.has("@test"))
{
parser.printMessage();
return 0;
}
if (!parser.has("@data"))
{
parser.printMessage();
return 0;
}
String imageFile = parser.get<String>(0);
String outputFile = parser.get<String>("@output");
int low = parser.get<int>("low");
int high = parser.get<int>("high");
double alpha = parser.get<double>("alpha");
int mode = parser.get<int>("mode");
cout << "alpha:" << alpha << endl;
cout << "mode: " << mode << endl;
cout << parser.get<string>("@test") << endl;
cout << parser.get<string>("@data") << endl;
return 0;
}
4. 个人在项目中的应用
#include<opencv2/opencv.hpp>
#include<iostream>
#include <unistd.h>
#include "config.h"
#include "server.h"
using namespace cv;
using namespace std;
int main(int argc, const char ** argv)
{
//1.Define the parameters you need
//Variable keys of type string : use ConmandLineParser to control terminal commmand
const string keys =
"{help h usage ? | | These variable parameters you can change your own }"
"{@inputPath | /input | source images path }"
"{@binaryPath | /binary | output binary images path }"
"{@resultPath | /result | output result images path }"
"{@jsonPath | /config.json | config json path }";
//Variable usage of type string : use getopt to crotrol terminal command . for example ,you can use -m1 -m2 for different mode
const string usage =
"Usage : opencv -m mode -t time -c type\r\n \
mode : algorithm mode (-1/0/1/2/3)\r\n \
time : picture time (1,2)\r\n \
config : 0(default) 1(config) 2(saveconfig)\r\n \
";
CommandLineParser parser(argc, argv, keys);
parser.about("Convenient for data exchange template program");
//2.check parser
if (!parser.check())
{
parser.printErrors();
return 0;
}
if (parser.has("help"))
{
cout << usage << endl;
parser.printMessage();
return 0;
}
//3.get pather path
string jsonPath = parser.get<String>("@jsonPath");
char buf[128] = {0};
getcwd(buf, sizeof(buf));
for(int i = strlen(buf) - 1; i>0; --i)
{
if( buf[i] == '/' )
{
buf[i] = '\0';
break;
}
}
jsonPath = buf+jsonPath;
//4.Define the parameters setting
string inputPath = buf+parser.get<String>("@inputPath");
string binaryPath = buf+parser.get<String>("@binaryPath");
string resultPath = buf+parser.get<String>("@resultPath");
int mode = -1;
int config = 0;
int time = 2;
int opt;
while ((opt = getopt(argc, (char **)argv, "m:t:c:")) != -1)
{
switch (opt)
{
case 'm':
mode = atoi(optarg);
break;
case 't':
time = atoi(optarg);
break;
case 'c':
config = atoi(optarg);
break;
case '?':
cout << usage << endl;
return 0;
default:
return 0;
}
}
JsonConfig::instance().setJsonPath(jsonPath);
//5.update from json or update the json
vector<string> jsonKeys{"INPUTPATH","BINARYPATH","RESULTPATH","MODE"};
if(config == 1)
{
inputPath = JsonConfig::instance().get<string>(jsonKeys[0]);
binaryPath = JsonConfig::instance().get<string>(jsonKeys[1]);
resultPath = JsonConfig::instance().get<string>(jsonKeys[2]);
mode = JsonConfig::instance().get<int>(jsonKeys[3]);
}
if(config == 2)
{
JsonConfig::instance().setJsonPath(jsonPath);
for(int i = 0 ; i < jsonKeys.size() ; i++)
{
string key = jsonKeys[i];
if(!JsonConfig::instance().check(key))
{
JsonConfig::instance().add(key,0);
}
}
JsonConfig::instance().change("INPUTPATH",inputPath);
JsonConfig::instance().change("BINARYPATH",binaryPath);
JsonConfig::instance().change("RESULTPATH",resultPath);
JsonConfig::instance().change("MODE",mode);
JsonConfig::instance().erase("roidata");
Server server(inputPath,binaryPath,resultPath);
server.StatDetect(time,config,mode);
JsonConfig::instance().show();
return 0;
}
//6.server
Server server(inputPath,binaryPath,resultPath);
server.StatDetect(time,config,mode);
return 0;
}