openmvg中cmd模块解析
---恢复内容开始---
在openmvg库中,定义了一个CmdLine类来定义例程的输入参数格式。源文件为.\openMVG\src\third_party\cmdLine\cmdLine.h。
先举个例子来说明一般输入参数格式,选用.\openMVG\src\software\SfM\main_SfMInit_ImageListing.cpp作为例程,对应的可执行文件为openMVG_main_SfMInit_ImageListing,在官网上(https://openmvg.readthedocs.io/en/latest/software/SfM/SfM/#)有该例程用法的介绍:
// Example(3种参数输入方式)
$openMVG_main_SfMInit_ImageListing --imageDirectory images --sensorWidthDatabase images/sensor_width_camera_database.txt --outputDirectory matches $openMVG_main_SfMInit_ImageListing -i images -d images/sensor_width_camera_database.txt -o matches $openMVG_main_SfMInit_ImageListing --imageDirectory=images --sensorWidthDatabase=images/sensor_width_camera_database.txt --outputDirectory=matches
其中第一种“--”后面接着的是长名标识符(longName如imageDirectory),images为对应参数
第二种“-”后面是短标识符(c如i,d,o等)
下面来分析与这3种输入参数格式相关的源代码。
我们先来看其中的一个类Option,它用于存储参数标识符(上面的-d,-i,-o等)与对应的长标识名(imageDirectory等),比如某个Option类种存储着-d和sensorWidthDatabase ,另一个Option类存储着-i和imageDirectory 。类的定义如下:
/// 类中包含3个数据成员,该类为父类,有两个子类(后面介绍)
class Option {
public:
char c; ///短标识符:i,d,o等
bool used; ///用于说明该参数是否已经被检测到,在解析输入参数时使用
std::string longName; /// 长名标识符:imageDirectory等 Option(char d, std::string name) //构造函数
: c(d), used(false), longName(name) {}
virtual ~Option() = default;
virtual bool check(int& argc, char* argv[]) = ; ///检查是否存在有对应的符合格式的参数存在,并解析,具体解析见子类
virtual Option* clone() const = ; ///< Copy
};
OptionField类,是Option的一个子类
template <class T>
class OptionField : public Option {
public:
//构造函数c,name分别对应父类Option种的c,longName;field对应参数比如例子中的输入参数images/sensor_width_camera_database.txt等
//因为输入参数类型不固定,可能是字符串也可能是数字,所以采用模板类
OptionField(char c, T& field, std::string name = "")
: Option(c, name), _field(field) {}
/// 查找正确的输入参数
bool check(int& argc, char* argv[]) override { //这里的argc,argv形参,并不与主程序中的argc,argv等同
std::string param; int arg = ;
if (std::string("-") + c == argv[] ||
(!longName.empty() && std::string("--") + longName == argv[])) { //对应输入参数格式为:-i ImageDataset_SceauxCastle/images
if (argc <= ) // 或:--imageDirectory ImageDataset_SceauxCastle/images
throw std::string("Option ")
+ argv[] + " requires argument";
param = argv[]; arg = ; //将ImageDataset_SceauxCastle/images赋值給param
}
else if (std::string(argv[]).find(std::string("-") + c) == ) { //对应输入参数格式为:-iImageDataset_SceauxCastle/images
param = argv[] + ; arg = ; //将ImageDataset_SceauxCastle/images赋值給param
}
else if (!longName.empty() && //对应输入参数格式为:--imageDirectory=ImageDataset_SceauxCastle/images
std::string(argv[]).find(std::string("--") + longName + '=') == ) {
size_t size = (std::string("--") + longName + '=').size();
param = std::string(argv[]).substr(size); arg = ; //将ImageDataset_SceauxCastle/images赋值給param
}
if (arg>) { //arg>0代表检查到了符合格式的输入参数
if (!read_param(param)) //读入检测到的参数,如果不成功,抛出异常
throw std::string("Unable to interpret ")
+ param + " as argument of " + argv[];
used = true; //该option对象对应的参数已经检测到
std::rotate(argv, argv + arg, argv + argc); //把从参数argv到argv + argc之间的参数序列看成一个圆,对他们进行旋转,旋转后的圆的第一个元素为argv + arg
//作用就是将检测到的参数放在输入参数序列后面
//rotate函数的用法详细介绍见:http://c.biancheng.net/view/609.html
/*
比如原始序列为:openMVG_main_SfMInit_ImageListing -i images -d images/sensor_width_camera_database.txt -o matches
假如argv对应-i argv + argc对应images/sensor_width_camera_database.txt arg=2
-i images -d images/sensor_width_camera_database.txt构成待旋转的圆,argv + arg对应的-d为旋转后圆的第一个元素
那么rotate后的新序列为openMVG_main_SfMInit_ImageListing -d images/sensor_width_camera_database.txt -i images -o matches
*/
argc -= arg;
return true;
}
return false;
}
/// 将读到的参数param赋值给_field;param为string型,_field类型在OptionField对象中预先定义了,见于make_option函数,也在cmdLine.h文件中
bool read_param(const std::string& param) {
std::stringstream str(param); char unused;
return !((str >> _field).fail() || !(str >> unused).fail());
}
/// Copy
Option* clone() const override {
return new OptionField<T>(c, _field, longName);
}
private:
T& _field;
};
另一个类OptionSwitch用的少,用于是否选用某种方法或者模式,比如:输入参数中如果有-u或者--use_sift参数,就使用sift方法,如果没有就不适用,只有是否两种情况;具体类定义就不做介绍了
Option类check用于匹配单个输入参数,CmdLine类实现所有的输入参数与所有的Option对象进行匹配
/// Command line parsing
class CmdLine {
std::vector<Option*> opts; //opts中包含所有的必须的或者可选的参数对应的标识符;即该程序需要输入哪些参数
public:
/// Destructor
~CmdLine() {
std::vector<Option*>::iterator it = opts.begin();
for (; it != opts.end(); ++it)
delete *it;
}
/// Add an option
void add(const Option& opt) { //在Option对象向量中添加Option对象
opts.push_back(opt.clone());
}
/// ************主要的成员函数************
/// 实现输入参数与程序需求的参数进行匹配
void process(int& argc, char* argv[]) {
std::vector<Option*>::iterator it = opts.begin();
for (; it != opts.end(); ++it)
(*it)->used = false;
for (int i = ; i<argc;) {
if (std::string("--") == argv[i]) { // "--" 为参数结尾标志,不知道这个有什么用
std::rotate(argv + i, argv + i + , argv + argc); //旋转,使"--"为序列结尾
--argc;
break;
}
bool found = false; // Find option
for (it = opts.begin(); it != opts.end(); ++it) { //将预先定义的Option类的各个对象分别与输入参数进行匹配
int n = argc - i;
found = (*it)->check(n, argv + i); //argv + i(argv[1])对应的参数与当前Option对象匹配
if (found) {
argc = n + i; //这行也不知道有什么用
break;
}
}
if (!found) { //如果没找到合适的匹配,但是输入的参数开头为"_",则抛出异常未识别标识符
if (std::string(argv[i]).size()> && argv[i][] == '-') {
std::istringstream str(argv[i]);
float v;
if (!(str >> v).eof())
throw std::string("Unrecognized option ") + argv[i];
}
++i;
}
}
}
/// Was the option used in last parsing?
bool used(char c) const {
std::vector<Option*>::const_iterator it = opts.begin();
for (; it != opts.end(); ++it)
if ((*it)->c == c)
return (*it)->used;
assert(false); // Called with non-existent option, probably a bug
return false;
}
};
在openmvg库中例程读入参数的主要流程如下:
#include"cmdLine.h"
#include <Eigen/Core>
//#include <Eigen/Dense>
//#include <Eigen/SparseCore>
//#include <Eigen/StdVector>
using namespace std;
using namespace Eigen; enum EINTRINSIC
{
PINHOLE_CAMERA_START = ,
PINHOLE_CAMERA, // No distortion
PINHOLE_CAMERA_RADIAL1, // radial distortion K1
PINHOLE_CAMERA_RADIAL3, // radial distortion K1,K2,K3
PINHOLE_CAMERA_BROWN, // radial distortion K1,K2,K3, tangential distortion T1,T2
PINHOLE_CAMERA_FISHEYE, // a simple Fish-eye distortion model with 4 distortion coefficients
PINHOLE_CAMERA_END,
CAMERA_SPHERICAL = PINHOLE_CAMERA_END +
}; using Vec3 = Eigen::Vector3d; inline bool split
(
const std::string & rhs,
const char delim,
std::vector<std::string> & items
)
{
items.clear();
std::stringstream ss(rhs);
std::string item;
while (std::getline(ss, item, delim))
{
items.emplace_back(item);
} // return true if the delimiter is present in the input string
return rhs.find(delim) != std::string::npos;
} /// Check that Kmatrix is a string like "f;0;ppx;0;f;ppy;0;0;1"
/// With f,ppx,ppy as valid numerical value
bool checkIntrinsicStringValidity(const std::string & Kmatrix, double & focal, double & ppx, double & ppy)
{
std::vector<std::string> vec_str;
split(Kmatrix, ';', vec_str);
if (vec_str.size() != ) {
std::cerr << "\n Missing ';' character" << std::endl;
return false;
}
// Check that all K matrix value are valid numbers
for (size_t i = ; i < vec_str.size(); ++i) {
double readvalue = 0.0;
std::stringstream ss;
ss.str(vec_str[i]);
if (!(ss >> readvalue)) {
std::cerr << "\n Used an invalid not a number character" << std::endl;
return false;
}
if (i == ) focal = readvalue;
if (i == ) ppx = readvalue;
if (i == ) ppy = readvalue;
}
return true;
} int main()
{
int argc = ;
char* argv[] = { "cmdline_study","-iimages", "-dsensor_width_camera_database.txt", "-ocmdline_study_outputdir", "-k2905.88; 0; 1416; \
; 2905.88; ; \
; ; " };
//1.定义一个CmdLine类
CmdLine cmd; std::string sImageDir, //2.定义输入参数对应数据类型,有的为string,有的为double等
sfileDatabase,
sOutputDir,
sKmatrix;
std::string sPriorWeights;
std::pair<bool, Vec3> prior_w_info(false, Vec3(1.0, 1.0, 1.0));
int i_User_camera_model = PINHOLE_CAMERA_RADIAL3;
bool b_Group_camera_model = true;
int i_GPS_XYZ_method = ;
double focal_pixels = -1.0;
//3.在CmdLine类中添加option对象(即需要输入的参数标识符)
cmd.add(make_option('i', sImageDir, "imageDirectory"));
cmd.add(make_option('d', sfileDatabase, "sensorWidthDatabase"));
cmd.add(make_option('o', sOutputDir, "outputDirectory"));
cmd.add(make_option('f', focal_pixels, "focal"));
cmd.add(make_option('k', sKmatrix, "intrinsics"));
cmd.add(make_option('c', i_User_camera_model, "camera_model"));
cmd.add(make_option('g', b_Group_camera_model, "group_camera_model"));
cmd.add(make_switch('P', "use_pose_prior"));
cmd.add(make_option('W', sPriorWeights, "prior_weights"));
cmd.add(make_option('m', i_GPS_XYZ_method, "gps_to_xyz_method"));
//4.进行输入参数与标识符匹配(CmdLine::process())
try {
if (argc == ) throw std::string("Invalid command line parameter.");
cmd.process(argc, argv);
}
catch (const std::string& s) {
std::cerr << "Usage: " << argv[] << '\n'
<< "[-i|--imageDirectory]\n"
<< "[-d|--sensorWidthDatabase]\n"
<< "[-o|--outputDirectory]\n"
<< "[-f|--focal] (pixels)\n"
<< "[-k|--intrinsics] Kmatrix: \"f;0;ppx;0;f;ppy;0;0;1\"\n"
<< "[-c|--camera_model] Camera model type:\n"
<< "\t" << static_cast<int>(PINHOLE_CAMERA) << ": Pinhole\n"
<< "\t" << static_cast<int>(PINHOLE_CAMERA_RADIAL1) << ": Pinhole radial 1\n"
<< "\t" << static_cast<int>(PINHOLE_CAMERA_RADIAL3) << ": Pinhole radial 3 (default)\n"
<< "\t" << static_cast<int>(PINHOLE_CAMERA_BROWN) << ": Pinhole brown 2\n"
<< "\t" << static_cast<int>(PINHOLE_CAMERA_FISHEYE) << ": Pinhole with a simple Fish-eye distortion\n"
<< "\t" << static_cast<int>(CAMERA_SPHERICAL) << ": Spherical camera\n"
<< "[-g|--group_camera_model]\n"
<< "\t 0-> each view have it's own camera intrinsic parameters,\n"
<< "\t 1-> (default) view can share some camera intrinsic parameters\n"
<< "\n"
<< "[-P|--use_pose_prior] Use pose prior if GPS EXIF pose is available"
<< "[-W|--prior_weights] \"x;y;z;\" of weights for each dimension of the prior (default: 1.0)\n"
<< "[-m|--gps_to_xyz_method] XZY Coordinate system:\n"
<< "\t 0: ECEF (default)\n"
<< "\t 1: UTM\n"
<< std::endl; std::cerr << s << std::endl;
return EXIT_FAILURE;
} system("pause");
return ;
}
openmvg中cmd模块解析的更多相关文章
- Python中pandas模块解析
Pandas基于两种数据类型: series 与 dataframe . 1.Series 一个series是一个一维的数据类型,其中每一个元素都有一个标签.类似于Numpy中元素带标签的数组.其中, ...
- Python中matplotlib模块解析
用Matplotlib绘制二维图像的最简单方法是: 1. 导入模块 导入matplotlib的子模块 import matplotlib.pyplot as plt import numpy as ...
- Python3 中 configparser 模块解析配置的用法详解
configparser 简介 configparser 是 Pyhton 标准库中用来解析配置文件的模块,并且内置方法和字典非常接近.Python2.x 中名为 ConfigParser,3.x 已 ...
- CCS中CMD文件解析
http://blog.csdn.net/u011392772/article/details/49760897 gel文件中主要包含了PLL.DDR等的初始化工作,具体可以看一下gel源码就明白了: ...
- Python中xlrd模块解析
xlrd 导入模块 import xlrd 2.打开指定的excel文件,返回一个data对象 data = xlrd.open_workbook(file) ...
- Python中csv模块解析
导入模块 import csv 2.读取csv文件 file1 = open('test1.csv', 'rb') reader = csv.reader(file1) rows = [row for ...
- TypeScript和Node模块解析策略
一般我们在模块化编码时,总会导入其它模块,通常我们使用如下语法: import { A } from './a'; // ES6语法 import { A } from 'a'; var A = re ...
- 浅析JS中的模块规范(CommonJS,AMD,CMD)////////////////////////zzzzzz
浅析JS中的模块规范(CommonJS,AMD,CMD) 如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已. ...
- JS中的模块规范(CommonJS,AMD,CMD)
JS中的模块规范(CommonJS,AMD,CMD) 如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已. 现在就看看吧, ...
随机推荐
- SpringCloud学习系列-Eureka服务注册与发现(2)
构建 microservicecloud-eureka-7001 eureka服务注册中心Module 1.新建microservicecloud-eureka-7001 2.pom <proj ...
- linux 系统下 tar 的压缩与解压缩命令
1.压缩 [small@sun shine]# tar -zcvf java.tar.gz java java/ java/default/ java/default/THIRDPARTYLICENS ...
- JPA学习(六、JPA_JPQL)
框架学习之JPA(六) JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中 ...
- VSCode支持jsx自动补全
点击settings.json中编辑, 把这段话加上去就可以了 "emmet.includeLanguages": { "javascript": " ...
- java 上传大文件以及文件夹
我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 这次项目的需求: 支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,i ...
- 搭建私有git仓库gogs
安装 gogs 下载 gogs download 安装 解压压缩包. 使用命令 cd 进入到刚刚创建的目录. 执行命令 ./gogs web,然后,就没有然后了. #后台运行 $ nohup ./go ...
- 第四周总结 & 实验报告(二)
第四周课程总结 一.String类 1.实例化 (1)直接赋值 public class Xxxx{ public static void main(String args[]){ String a ...
- java8 stream初试,map排序,list去重,统计重复元素个数,获取map的key集合和value集合
//定义一个100元素的集合,包含A-Z List<String> list = new LinkedList<>(); for (int i =0;i<100;i++) ...
- java 栈和栈帧
文章转载自:http://www.tuicool.com/articles/URZrMnb jvm为每个新创建的线程都分配一个堆栈.堆栈以帧为单位保存线程的状态.jvm对堆栈只进行两种操作:以帧为单位 ...
- 十二、RF自定义库(数据库)
1.自定义第三方库 def DB_select_by_sql(self,db_name,sql): conn=pymysql.connect(db=db_name,user='root',passwo ...