不安装cygwin而只在windows下运行bundler

时间:2023-02-02 00:18:20

bundler是个挺强大的三维重建库,具体的就不介绍了,上其主页上看去。

这里主要记录一下怎么在windows下运行这东西。网上搜索的都要安装cygwin,但这东西太大了,安装下来1个G以上。空间宝贵,故想不安装它直接在windows下跑。

借助了opencv和Qt,其中opencv是用来将.jpg图像转换成.pgm格式的,因为bunder其中用到的特征检测siftWin32只能用P5开头的.pgm格式的图像;而Qt是用来遍历文件夹下的图像路径的,这个如果熟悉其它如MFC的也可以用其它的代替,反正只要能运行就Ok了是吧。

话不多说,上代码。

bundlerInWin.h

#ifndef BUNDLERINWIN_H
#define BUNDLERINWIN_H

#include <QtWidgets/QWidget>
#include "ui_bundlerinwin.h"

#include <QPushButton>
#include <QLineEdit>
#include <QString>
#include <QSlider>
#include <QSpinBox>

namespace Ui
{
	class bundlerInWin;
};

class bundlerInWin : public QWidget
{
	Q_OBJECT

public:
	bundlerInWin(QWidget *parent = 0);
	~bundlerInWin();

	void initwidgets();
	void initconnects();

public slots :
	bool choosedir();

	void GenListFile();
	void changeImage();
	void runbundler();

	void setLcdvalue(int);
	void setSlidervalue(int);
private:
	Ui::bundlerInWin *ui;

	QLineEdit *dirlineedit;
	QPushButton *dirbtn;
	QString dirname;

	QPushButton *genlistbtn, *changeimgbtn, *runbtn;
	int focal_length;
	QSpinBox *paramedit;
	QSlider *slider;
};

#endif // BUNDLERINWIN_H
 

 

bundlerInWin.cpp

#include "bundlerinwin.h"

#include <QFileDialog>
#include <QMessageBox>
#include <QHBoxLayout>
#include <QVBoxLayout>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
using namespace cv;

string StringRepalceSub(string &str, const string oldSub, const string newSub)
{
	int oldSubLen = oldSub.size();//替换的长度
	unsigned int  p = string::npos;
	p = str.find(oldSub, 0);//查找替换的位置
	if (p == string::npos)	{
		return str;
	}
	else	{
		string restr = str;
		return restr.replace(p, oldSubLen, newSub);
	}

}


bundlerInWin::bundlerInWin(QWidget *parent)
	:ui(new Ui::bundlerInWin), QWidget(parent)
{
	ui->setupUi(this);

	initwidgets();
	initconnects();

	focal_length = 5;
	
	QHBoxLayout *dirlayout = new QHBoxLayout();
	dirlayout->addWidget(dirlineedit);
	dirlayout->addWidget(dirbtn);
	QHBoxLayout *paramlayout = new QHBoxLayout();
	paramlayout->addWidget(paramedit);
	paramlayout->addWidget(slider);
	QVBoxLayout *btnlayout = new QVBoxLayout();
	btnlayout->addWidget(genlistbtn);
	btnlayout->addWidget(changeimgbtn);
	btnlayout->addWidget(runbtn);

	QVBoxLayout *mainlayout = new QVBoxLayout();
	mainlayout->addLayout(dirlayout);
	mainlayout->addLayout(paramlayout);
	mainlayout->addLayout(btnlayout);
	setLayout(mainlayout);
}

bundlerInWin::~bundlerInWin()
{
	delete ui;
}

void bundlerInWin::initwidgets()
{
	dirbtn = new QPushButton("choose dir");
	dirlineedit = new QLineEdit();

	genlistbtn = new QPushButton("genlistfile");
	changeimgbtn = new QPushButton("changeImage");
	runbtn = new QPushButton("run");

	slider = new QSlider(Qt::Horizontal);
	slider->setMinimum(0);
	slider->setMaximum(10000);
	slider->setValue(0);

	paramedit = new QSpinBox();
	paramedit->setRange(0, 10000);
	paramedit->setValue(5);
}

void bundlerInWin::initconnects()
{
	connect(dirbtn, SIGNAL(clicked()), this, SLOT(choosedir()));

	connect(genlistbtn, SIGNAL(clicked()), this, SLOT(GenListFile()));
	connect(changeimgbtn, SIGNAL(clicked()), this, SLOT(changeImage()));
	connect(runbtn, SIGNAL(clicked()), this, SLOT(runbundler()));

	connect(slider, SIGNAL(valueChanged(int)), this, SLOT(setLcdvalue(int)));
	connect(paramedit, SIGNAL(valueChanged(int)), this, SLOT(setSlidervalue(int)));
}

bool bundlerInWin::choosedir()
{
	dirname = QFileDialog::getExistingDirectory(this);
	if (dirname.isEmpty()) {
		QMessageBox::warning(NULL, "warning:", "No such directory!");
		return false;
	}
	dirlineedit->setText(dirname);
	return true;
}

void bundlerInWin::GenListFile()
{
	QDir dir(dirname);
	dir.setFilter(QDir::Files);
	QFileInfoList list = dir.entryInfoList();

	ofstream listfile("result/list.txt");

	int i = 0;
	do {
		QFileInfo fileInfo = list.at(i);
		if (fileInfo.fileName() == "." || fileInfo.fileName() == "..") {
			i++;
			continue;
		}
		listfile << fileInfo.absoluteFilePath().toStdString() << " 0 " << focal_length << endl;
		i++;
	} while (i < list.size());

	listfile.close();
}

void bundlerInWin::changeImage()
{
	ifstream listfile("result/list.txt");
	ofstream keyfile("result/list_keys.txt");
	string str, new_imagename, keyname, comm;
	int len = 0, i = 0;
	QDir dir;
	string tmpstr;
	vector<string> str_list;
	while (getline(listfile, tmpstr)) {
		int pos = tmpstr.find_first_of(" ");
		str = tmpstr.substr(0, pos);
		i++;
		Mat image = imread(str);
		Mat img_gray;
		cvtColor(image, img_gray, CV_RGB2GRAY);
		new_imagename = StringRepalceSub(str, "testImage", "pgmImage");
		keyname = StringRepalceSub(str, "jpg", "key");
		new_imagename = StringRepalceSub(new_imagename, "jpg", "pgm");
//		keyname = StringRepalceSub(str, "png", "key");
//		new_imagename = StringRepalceSub(new_imagename, "png", "pgm");	

		imwrite(new_imagename, img_gray);

		keyfile << keyname << endl;
		comm = dir.currentPath().toStdString() + "/bin/siftWin32.exe <" + new_imagename + " >" + keyname;
		system(comm.c_str());
	}

	listfile.close();
	keyfile.close();
}


void bundlerInWin::runbundler()
{
	system("cls");
	QDir dir;
	string comm;
	comm = dir.currentPath().toStdString() + "/bin/KeyMatchFull.exe result/list_keys.txt result/matches.init.txt";
	system(comm.c_str());
	comm = dir.currentPath().toStdString() + "/bin/bundler.exe result/list.txt --options_file result/options.txt";
	system(comm.c_str());
}

void bundlerInWin::setLcdvalue(int value)
{
	focal_length = slider->value();
	paramedit->setValue(focal_length);
}

void bundlerInWin::setSlidervalue(int value)
{
	focal_length = paramedit->value();
	slider->setValue(focal_length);
}
 

 

main.cpp

#include "bundlerinwin.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	bundlerInWin w;
	w.show();
	return a.exec();
}


 

换种说法,就是:

Windows下调用bundler(有点麻烦,建议写个脚本或程序衔接中间的参数变换什么的)


bundler.exe list.txt --options_file options.txt


其中参数2是图像名称列表,参数4是配置信息(主要包括匹配点文件名matches.init.txt[由KeyMatchFull.exe生成]及其路径)


KeyMatchFull.exe list_keys.txt matches.init.txt


其中参数1是特征点的文件列表,特征点文件(xx.key)由siftWin32.exe生成,参数2是输出文件


siftWin32.exe <xx1.pgm >xx1.key
其中参数2和3是图像名称(貌似涉及到pgm和jpg等的转换)这些.key文件需要在KeyMatchFull.exe的参数1中罗列


--------------------------------------------------------------------------
list.txt 文件样例


../mytest/test0000.jpg
../mytest/test0001.jpg
../mytest/test0002.jpg
../mytest/test0003.jpg
../mytest/test0004.jpg
../mytest/test0005.jpg


--------------------------------------------------------------------------
options.txt 文件样例(主要修改第一行第二个参数,其它可以不改)


--match_table ../result/matches.init.txt
--output bundle.out
--output_all bundle_
--output_dir bundle
--variable_focal_length
--use_focal_estimate
--constrain_focal
--constrain_focal_weight 0.0001
--estimate_distortion
--run_bundle




--------------------------------------------------------------------------
list_keys.txt 文件样例


../mytest/test0000.key
../mytest/test0001.key
../mytest/test0002.key
../mytest/test0003.key
../mytest/test0004.key
../mytest/test0005.key


--------------------------------------------------------------------------