目录
简介
OpenCV源码中对CommandLineParse的说明如下:
Designed for command line parsing
CommandLineParse类主要用来解析命令行输入参数。
作用:方便用户在命令行使用过程中减少工作量。
不用每次都手动输入参数,非常方便。
具体如何用请看代码,里面有用中文详细注释。
说明
什么是位置参数
你在控制台窗口下输入这样一个指令
test.exe F:\images\logo.jpg F:\images\abc.png 3abc 4 defg
划线的部分就是位置参数,它们是有自己的顺序的,
“F:\images\logo.jpg”就是第一个位置参数
“F:\images\abc.png”是第二个位置参数
“3abc”是第三个位置参数
“4 defg”是第四个位置参数
以此类推……
什么是关键字参数
CmdLineParser.exe -image F:\images\logo.jpg -camera false -file_name F:/images/test.mp4
“-image F:\images\logo.jpg”,“-camera false”,“-file_name F:/images/test.mp4”都是关键字参数,
包含两部分:参数名称和参数的值
以这个为例,“-image F:\images\logo.jpg”
“image”是参数名称(没有前面的横线-,不要问我为什么)
“F:\images\logo.jpg”是参数的值
关键字参数
Keys syntax
The keys parameter is a string containing several blocks, each one is enclosed in curley braces and describes one argument. Each argument contains three parts separated by the
|
symbol:
- argument names is a space-separated list of option synonyms (to mark argument as positional, prefix it with the
@
symbol)- default value will be used if the argument was not provided (can be empty)
- help message (can be empty)
笔者翻译:
关键字语法
关键字参数是一个包含多个区块的字符串,每个区块都包含在花括号中并描述一个参数。 每个参数包含三个部分,由符号|分隔:
Part 1. 参数名称是以空格分隔的同义词列表(如果要将参数标记为位置参数,使用@符号作为前缀)
Part 2. 如果未提供参数,则将使用默认值(可以为空)
Part 3. 帮助信息(可以是空的)
For example:
const String keys = {
"{help h usage ? | | print this message }"
"{@image1 | | image1 for compare }"
"{@image2 | | image2 for compare }"
"{@repeat |1 | number }"
"{path |. | path to file }"
"{fps | -1.0 | fps for output video }"
"{N count |100 | count of objects }"
"{ts timestamp | | use time stamp }"
};
参考文档:
https://docs.opencv.org/3.0.0/d0/d2e/classcv_1_1CommandLineParser.html
总结:每个关键字参数用双引号+花括号括起来,
格式为如下,用竖线|来区分,第一部分(第一个分隔符|左边)的参数名称用空格来区分,是同义词,可以是全称、简称、近义词
@可以将某个参数标记为位置参数【注意这句】
参数名称 参数名称 |参数的默认值 | 关于参数的帮助语句
如何访问关键字参数
举例
string inputImage = parser.get<String>("@image"); //注意有@,详细参考下一小节《如何访问位置参数》
bool useCamera = parser.get<bool>("camera"); //camera为bool值
string file = parser.get<string>("file_name"); //file_name为字符串
int type = parser.get<int>("type"); // 输入为整数
如何访问位置参数
两种方式来获取位置参数:
1. You can access positional arguments by their @
-prefixed name:
用“@参数名称”来访问【类似老师点名时叫的“名字”】(因为@可以将某个参数标记为位置参数)
string inputImage = parser.get<String>("@image");
2. Access positional arguments by index.
Returns argument converted to selected type. Indexes are counted from zero.
用索引(index)来访问。索引从零开始。【类似老师点名时叫的“学号”】
笔者提供的例子中只有一个位置参数,用@将image标记为位置参数,所以它的所以是0.
【注意】不要和控制台(cmd.exe)中的char ** argv搞混了。argv中应该是1,即argv[1],因为argv[0]一直都是.exe的名字,例如“CmdLineParser.exe”,或者“HelloWorld.exe”,或者“test.exe”
string inputImage = parser.get<string>(0);
如何使用&调试方法
以这个为例,位置参数0与关键字参数@image默认使用“F:/images/lena.jpg”
const char* keys =
{
"{help h||}"
"{@image|F:/images/lena.jpg|input image file}"
"{type|3|band pass filter type}"
};
1. 如果需要更改输入的参数格式与内容,只需要改keys里面的内容
例如:我程序里默认使用“F:/images/lena.jpg”这张图片,但是我想换一张图片,可以在控制台这样输入:
CmdLineParser.exe -image F:\images\logo.jpg
非常方便。
2. const char* keys已经设定好默认参数了,就可以直接在Visual Studio下用F5,不需要再另外设定Command Arguments
推荐调试伴侣:Image Watch【目前只支持VS2012/2013/2015】
下载链接:
https://marketplace.visualstudio.com/items?itemName=VisualCPPTeam.ImageWatch
3. 如果在Visual Studio里Command Arguments设定了不同于默认值的参数(例如F:\images\logo.jpg),会以设定的参数(F:\images\logo.jpg)为准,就不会使用默认的参数(F:/images/lena.jpg)了。
这时设定需要带参数名称-image【有横线-】
-image F:\images\logo.png
4. 获取整数
可能会出现这个情况
Error: Bad argument (can not convert: [true] to [int]) in cv::from_str, file D:\software\OpenCV\SourceCode\opencv-3.4.2\modules\core\src\command_line_parser.cpp, line 121
只要把关键字与参数之间加个等号“=”就好了
-image="F:\3DAA\01-40_TC.jpg" -type=2
-image "F:\3DAA\01-40_TC.jpg" -type=2
以上两种都可以,参数为字符串情况可以不用加等号。
实例代码
//头文件
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv; //包含cv命名空间
using namespace std;
static void help()
{
printf("Current OpenCV version:" CV_VERSION);
std::cout << "\nThis program demonstrates the use of CommandLineParser.\n"
<< "Usage: \n" << "test [image_name -- Defaults to F:/images/lena.jpg]" << std::endl;
}
const char* keys =
{
"{help h||}" //help信息
"{@image|F:/images/lena.jpg|input image file}" //默认读入F:/images/answer_bottom.png
"{camera c |false | use camera or not}" //参数名称1 参数名称2 |参数的默认值 |关于参数的帮助语句
"{file_name f |F:/images/fun.gif | movie file path }" //参数名称1 参数名称2 |参数的默认值 |关于参数的帮助语句
};
int main(int argc, char ** argv)
{
//【1】构造一个CommandLineParser实例,并打印帮助信息
CommandLineParser parser(argc, argv, keys);
if (parser.has("help"))
{
help();
return 0;
}
parser.printMessage(); //打印帮助信息
//【2】处理image参数
string inputImage = parser.get<string>(0); //image参数为字符串,用索引来访问位置参数
//string inputImage = parser.get<string>("@image"); //用“@参数名称”来访问
cout << "inputImage:" << inputImage << endl;
// Load the source image. HighGUI use.
Mat srcImage = imread(inputImage, CV_LOAD_IMAGE_COLOR); //读入图片
if (srcImage.empty())
{
std::cerr << "Cannot read image file: " << inputImage << std::endl;
return -1;
}
char input_title[] = "input image"; //输入窗口的标题
char output_title[] = "output image"; //输出窗口的标题
//CV_WINDOW_NORMAL - 用户可以调整窗口大小
//CV_WINDOW_AUTOSIZE - 用户不可以调整窗口大小,由展示的图片决定
namedWindow(input_title, CV_WINDOW_AUTOSIZE);
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
imshow(input_title, srcImage); //显示输入图片
//【3】对输入图片进行处理
Mat dstImage;
cvtColor(srcImage, dstImage, COLOR_BGR2GRAY); //转为灰度图
imshow(output_title, dstImage); //显示输入图片
//【4】处理camera与 file_name参数
bool useCamera = parser.get<bool>("camera"); //camera为bool值
string file = parser.get<string>("file_name"); //file_name为字符串
cout << "useCamera:" << useCamera << endl;
cout << "file:" << file << endl;
VideoCapture cap;
if (useCamera)
cap.open(0);
else
cap.open(file.c_str());
//【5】读取视频并对视频中的每一帧进行提取边缘
//参考网址 https ://blog.youkuaiyun.com/qq_32925781/article/details/53709271
while (true) {
Mat frame;
Mat edge;
cap >> frame;
if (frame.empty())
break;
cvtColor(frame, edge, COLOR_BGR2GRAY); //转为灰度图
blur(edge, edge, Size(7, 7)); //进行blur处理
Canny(edge, edge, 10, 30); //提取边缘
imshow("Video", frame); //显示原始视频中的一帧图片
imshow("After canny", edge); //显示经过处理的图像 - 边缘图
//等待50ms,如果从键盘输入的是q、Q、或者是Esc键,则退出
int key = waitKey(50);
if (key == 'q' || key == 'Q' || key == 27)
break;
}
waitKey(0); // 【6】等待任意按键按下
return 0;
}
效果图
补充:VisualStudio控制台程序带有参数的设定方法
如果不想使用CommandLineParse类,生成的.exe需要参数,那么在Debug(F5)时,需要提前输入参数,输入方法如下:
如果有多个参数,用空格分开,例如 F:/images/lena.jpg F:/images/mac.jpg