-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b67a8f3
commit 9e1bf31
Showing
1 changed file
with
239 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
#!/usr/bin/python | ||
#! -*- encoding: utf-8 -*- | ||
# | ||
# Created by @FlachyJoe | ||
# | ||
# this script is for easy use of OpenMVG and OpenMVS | ||
# | ||
#usage: SfM_MyPipeline.py input_dir output_dir | ||
# [-h] [-f FIRST_STEP] [-l LAST_STEP] [--0 0 [0 ...]] | ||
# [--1 1 [1 ...]] [--2 2 [2 ...]] [--3 3 [3 ...]] | ||
# [--4 4 [4 ...]] [--5 5 [5 ...]] [--6 6 [6 ...]] | ||
# [--7 7 [7 ...]] [--8 8 [8 ...]] [--9 9 [9 ...]] | ||
# [--10 10 [10 ...]] [--11 11 [11 ...]] | ||
# | ||
#Photogrammetry reconstruction with these steps : | ||
# 0. Intrinsics analysis openMVG_main_SfMInit_ImageListing | ||
# 1. Compute features openMVG_main_ComputeFeatures | ||
# 2. Compute matches openMVG_main_ComputeMatches | ||
# 3. Incremental reconstruction openMVG_main_IncrementalSfM | ||
# 4. Colorize Structure openMVG_main_ComputeSfM_DataColor | ||
# 5. Structure from Known Poses openMVG_main_ComputeStructureFromKnownPoses | ||
# 6. Colorized robust triangulation openMVG_main_ComputeSfM_DataColor | ||
# 7. Export to openMVS openMVG_main_openMVG2openMVS | ||
# 8. Densify point cloud OpenMVS/DensifyPointCloud | ||
# 9. Reconstruct the mesh OpenMVS/ReconstructMesh | ||
# 10. Refine the mesh OpenMVS/RefineMesh | ||
# 11. Texture the mesh OpenMVS/TextureMesh | ||
# | ||
#positional arguments: | ||
# input_dir the directory which contains the pictures set. | ||
# output_dir the directory which will contain the resulting files. | ||
# | ||
#optional arguments: | ||
# -h, --help show this help message and exit | ||
# -f FIRST_STEP, --first_step FIRST_STEP | ||
# the first step to process | ||
# -l LAST_STEP, --last_step LAST_STEP | ||
# the last step to process | ||
# | ||
#Passthrough: | ||
# Option to be pass to command lines (remove - in front of option names) | ||
# e.g. --1 p ULTRA to use the ULTRA preset in openMVG_main_ComputeFeatures | ||
|
||
|
||
import commands | ||
import os | ||
import subprocess | ||
import sys | ||
|
||
# Indicate the openMVG and openMVS binary directories | ||
OPENMVG_BIN = "D:/Pro/OpenMVG/install/bin/" | ||
OPENMVS_BIN = "D:/Pro/OpenMVS/install/bin/" | ||
|
||
# Indicate the openMVG camera sensor width directory | ||
CAMERA_SENSOR_WIDTH_DIRECTORY = OPENMVG_BIN | ||
|
||
DEBUG=False | ||
|
||
## HELPERS for terminal colors | ||
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) | ||
NO_EFFECT, BOLD, UNDERLINE, BLINK, INVERSE, HIDDEN = (0,1,4,5,7,8) | ||
|
||
#from Python cookbook, #475186 | ||
def has_colours(stream): | ||
if not hasattr(stream, "isatty"): | ||
return False | ||
if not stream.isatty(): | ||
return False # auto color only on TTYs | ||
try: | ||
import curses | ||
curses.setupterm() | ||
return curses.tigetnum("colors") > 2 | ||
except: | ||
# guess false in case of error | ||
return False | ||
has_colours = has_colours(sys.stdout) | ||
|
||
def printout(text, colour=WHITE, background=BLACK, effect=NO_EFFECT): | ||
if has_colours: | ||
seq = "\x1b[%d;%d;%dm" % (effect, 30+colour, 40+background) + text + "\x1b[0m" | ||
sys.stdout.write(seq+'\r\n') | ||
else: | ||
sys.stdout.write(text+'\r\n') | ||
|
||
## OBJECTS to store config and data in | ||
|
||
class ConfContainer(object): | ||
"""Container for all the config variables""" | ||
pass | ||
|
||
conf=ConfContainer() | ||
|
||
class aStep: | ||
def __init__(self, info, cmd, opt): | ||
self.info = info | ||
self.cmd = cmd | ||
self.opt = opt | ||
|
||
class stepsStore : | ||
def __init__(self): | ||
self.steps_data=[ | ||
[ "Intrinsics analysis", | ||
os.path.join(OPENMVG_BIN,"openMVG_main_SfMInit_ImageListing"), | ||
["-i", "%input_dir%", "-o", "%matches_dir%", "-d", "%camera_file_params%"] ], | ||
[ "Compute features", | ||
os.path.join(OPENMVG_BIN,"openMVG_main_ComputeFeatures"), | ||
["-i", "%matches_dir%/sfm_data.json", "-o", "%matches_dir%", "-m", "SIFT", "-n", "4"] ], | ||
[ "Compute matches", | ||
os.path.join(OPENMVG_BIN, "openMVG_main_ComputeMatches"), | ||
["-i", "%matches_dir%/sfm_data.json", "-o", "%matches_dir%"] ], | ||
[ "Incremental reconstruction", | ||
os.path.join(OPENMVG_BIN, "openMVG_main_IncrementalSfM"), | ||
["-i", "%matches_dir%/sfm_data.json", "-m", "%matches_dir%", "-o", "%reconstruction_dir%"] ], | ||
[ "Colorize Structure", | ||
os.path.join(OPENMVG_BIN,"openMVG_main_ComputeSfM_DataColor"), | ||
["-i", "%reconstruction_dir%/sfm_data.bin", "-o", "%reconstruction_dir%/colorized.ply"]], | ||
[ "Structure from Known Poses", | ||
os.path.join(OPENMVG_BIN,"openMVG_main_ComputeStructureFromKnownPoses"), | ||
["-i", "%reconstruction_dir%/sfm_data.bin", "-m", "%matches_dir%", "-f", "%matches_dir%/matches.f.bin", "-o", "%reconstruction_dir%/robust.bin"]], | ||
[ "Colorized robust triangulation", | ||
os.path.join(OPENMVG_BIN,"openMVG_main_ComputeSfM_DataColor"), | ||
["-i", "%reconstruction_dir%/robust.bin", "-o", "%reconstruction_dir%/robust_colorized.ply"]], | ||
[ "Export to openMVS", | ||
os.path.join(OPENMVG_BIN,"openMVG_main_openMVG2openMVS"), | ||
["-i", "%reconstruction_dir%/sfm_data.bin", "-o", "%mvs_dir%/scene.mvs","-d","%mvs_dir%"]], | ||
[ "Densify point cloud", | ||
os.path.join(OPENMVS_BIN,"DensifyPointCloud"), | ||
["scene.mvs", "-w","%mvs_dir%"]], | ||
[ "Reconstruct the mesh", | ||
os.path.join(OPENMVS_BIN,"ReconstructMesh"), | ||
["scene_dense.mvs", "-w","%mvs_dir%"]], | ||
[ "Refine the mesh", | ||
os.path.join(OPENMVS_BIN,"RefineMesh"), | ||
["scene_dense_mesh.mvs", "-w","%mvs_dir%"]], | ||
[ "Texture the mesh", | ||
os.path.join(OPENMVS_BIN,"TextureMesh"), | ||
["scene_dense_mesh_refine.mvs", "-w","%mvs_dir%"]] | ||
] | ||
|
||
def __getitem__(self, indice): | ||
return aStep(*self.steps_data[indice]) | ||
|
||
def length(self): | ||
return len(self.steps_data) | ||
|
||
def apply_conf(self, conf): | ||
""" replace each %var% per conf.var value in steps data """ | ||
for s in self.steps_data : | ||
o2=[] | ||
for o in s[2]: | ||
co=o.replace("%input_dir%",conf.input_dir) | ||
co=co.replace("%output_dir%",conf.output_dir) | ||
co=co.replace("%matches_dir%",conf.matches_dir) | ||
co=co.replace("%reconstruction_dir%",conf.reconstruction_dir) | ||
co=co.replace("%mvs_dir%",conf.mvs_dir) | ||
co=co.replace("%camera_file_params%",conf.camera_file_params) | ||
o2.append(co) | ||
s[2]=o2 | ||
|
||
steps=stepsStore() | ||
|
||
## ARGS | ||
import argparse | ||
parser = argparse.ArgumentParser( | ||
formatter_class=argparse.RawDescriptionHelpFormatter, | ||
description="Photogrammetry reconstruction with these steps : \r\n"+ | ||
"\r\n".join(("\t%i. %s\t %s" % (t, steps[t].info, steps[t].cmd) for t in range(steps.length()))) | ||
) | ||
parser.add_argument('input_dir', help="the directory wich contains the pictures set.") | ||
parser.add_argument('output_dir', help="the directory wich will contain the resulting files.") | ||
parser.add_argument('-f','--first_step', type=int, default=0, help="the first step to process") | ||
parser.add_argument('-l','--last_step', type=int, default=11, help="the last step to process" ) | ||
|
||
group = parser.add_argument_group('Passthrough',description="Option to be passed to command lines (remove - in front of option names)\r\ne.g. --1 p ULTRA to use the ULTRA preset in openMVG_main_ComputeFeatures") | ||
for n in range(steps.length()) : | ||
group.add_argument('--'+str(n), nargs='+') | ||
|
||
parser.parse_args(namespace=conf) #store args in the ConfContainer | ||
|
||
## FOLDERS | ||
|
||
def mkdir_ine(dirname): | ||
"""Create the folder if not presents""" | ||
if not os.path.exists(dirname): | ||
os.mkdir(dirname) | ||
|
||
#Absolute path for input and ouput dirs | ||
conf.input_dir=os.path.abspath(conf.input_dir) | ||
conf.output_dir=os.path.abspath(conf.output_dir) | ||
|
||
if not os.path.exists(conf.input_dir): | ||
sys.exit("%s : path not found" % conf.input_dir) | ||
|
||
|
||
conf.matches_dir = os.path.join(conf.output_dir, "matches") | ||
conf.reconstruction_dir = os.path.join(conf.output_dir, "reconstruction_sequential") | ||
conf.mvs_dir = os.path.join(conf.output_dir, "mvs") | ||
conf.camera_file_params = os.path.join(CAMERA_SENSOR_WIDTH_DIRECTORY, "sensor_width_camera_database.txt") | ||
|
||
mkdir_ine(conf.output_dir) | ||
mkdir_ine(conf.matches_dir) | ||
mkdir_ine(conf.reconstruction_dir) | ||
mkdir_ine(conf.mvs_dir) | ||
|
||
steps.apply_conf(conf) | ||
|
||
## WALK | ||
print "# Using input dir : %s" % conf.input_dir | ||
print "# output_dir : %s" % conf.output_dir | ||
print "# First step : %i" % conf.first_step | ||
print "# Last step : %i" % conf.last_step | ||
for cstep in range(conf.first_step, conf.last_step+1): | ||
printout("#%i. %s" % (cstep, steps[cstep].info), effect=INVERSE) | ||
|
||
opt=getattr(conf,str(cstep)) | ||
if opt is not None : | ||
#add - sign to short options and -- to long ones | ||
for o in range(0,len(opt),2): | ||
if len(opt[o])>1: | ||
opt[o]='-'+opt[o] | ||
opt[o]='-'+opt[o] | ||
else: | ||
opt=[] | ||
|
||
#Remove steps[cstep].opt options now defined in opt | ||
for anOpt in steps[cstep].opt : | ||
if anOpt in opt : | ||
idx=steps[cstep].opt.index(anOpt) | ||
if DEBUG : | ||
print '#\t'+'Remove '+ str(anOpt) + ' from defaults options at id ' + str(idx) | ||
del steps[cstep].opt[idx:idx+2] | ||
|
||
cmdline = [steps[cstep].cmd] + steps[cstep].opt + opt | ||
|
||
if not DEBUG : | ||
pStep = subprocess.Popen(cmdline) | ||
pStep.wait() | ||
else: | ||
print '\t'+' '.join(cmdline) |