Remove PMVS module

Former-commit-id: eda8beaefe
pull/1161/head
Dakota Benjamin 2018-07-01 17:28:55 -04:00
rodzic 6c64d1172c
commit 80cbc2f03b
19 zmienionych plików z 26 dodań i 490 usunięć

Wyświetl plik

@ -6,12 +6,9 @@ SuperBuild/install
SuperBuild/src
build
opensfm
pmvs
odm_orthophoto
odm_texturing
odm_meshing
odm_georeferencing
images_resize
.git

Wyświetl plik

@ -105,7 +105,7 @@ or
python run.py --rerun-from odm_meshing project-name
The options for rerunning are: 'resize', 'opensfm', 'slam', 'cmvs', 'pmvs', 'odm_meshing', 'mvs_texturing', 'odm_georeferencing', 'odm_orthophoto'
The options for rerunning are: 'resize', 'opensfm', 'slam', 'smvs', 'odm_meshing', 'mvs_texturing', 'odm_georeferencing', 'odm_orthophoto'
### View Results
@ -151,7 +151,7 @@ You can also view the orthophoto GeoTIFF in [QGIS](http://www.qgis.org/) or othe
## Build and Run Using Docker
(Instructions below apply to Ubuntu 14.04, but the Docker image workflow
(Instructions below apply to Ubuntu 14.04, but the Docker image workflow
has equivalent procedures for Mac OS X and Windows. See [docs.docker.com](https://docs.docker.com/))
OpenDroneMap is Dockerized, meaning you can use containerization to build and run it without tampering with the configuration of libraries and packages already
@ -177,7 +177,7 @@ If you want to build your own Docker image from sources, type:
Using this method, the containerized ODM will process the images in the OpenDroneMap/images directory and output results
to the OpenDroneMap/odm_orthophoto and OpenDroneMap/odm_texturing directories as described in the [Viewing Results](https://github.com/OpenDroneMap/OpenDroneMap/wiki/Output-and-Results) section.
If you want to view other results outside the Docker image simply add which directories you're interested in to the run command in the same pattern
established above. For example, if you're interested in the dense cloud results generated by PMVS and in the orthophoto,
established above. For example, if you're interested in the dense cloud results generated by OpenSfM and in the orthophoto,
simply use the following `docker run` command after building the image:
docker run -it --rm \
@ -195,7 +195,7 @@ If you want to get all intermediate outputs, run the following command:
-v "$(pwd)/odm_orthophoto:/code/odm_orthophoto" \
-v "$(pwd)/odm_texturing:/code/odm_texturing" \
-v "$(pwd)/opensfm:/code/opensfm" \
-v "$(pwd)/pmvs:/code/pmvs" \
-v "$(pwd)/smvs:/code/smvs" \
opendronemap/opendronemap
To pass in custom parameters to the run.py script, simply pass it as arguments to the `docker run` command. For example:
@ -222,7 +222,7 @@ When building your own Docker image, if image size is of importance to you, you
This will clean up intermediate steps in the Docker build process, resulting in a significantly smaller image (about half the size).
Experimental flags need to be enabled in Docker to use the ```--squash``` flag. To enable this, insert the following into the file ```/etc/docker/daemon.json```:
{
"experimental": true
}
@ -244,7 +244,7 @@ Coming soon...
## Documentation:
For documentation, everything is being moved to [http://docs.opendronemap.org/](http://docs.opendronemap.org/) but you can also take a look at our [wiki](https://github.com/OpenDroneMap/OpenDroneMap/wiki). Check those places first if you are having problems. There's also help at [community forum](http://community.opendronemap.org/), and if you still need help and think you've found a bug or need an enhancement, look through the issue queue or create one.
For documentation, everything is being moved to [http://docs.opendronemap.org/](http://docs.opendronemap.org/) but you can also take a look at our [wiki](https://github.com/OpenDroneMap/OpenDroneMap/wiki). Check those places first if you are having problems. There's also help at [community forum](http://community.opendronemap.org/), and if you still need help and think you've found a bug or need an enhancement, look through the issue queue or create one.
## Developers

Wyświetl plik

@ -114,14 +114,12 @@ SETUP_EXTERNAL_PROJECT(Hexer 1.4 ON)
# ---------------------------------------------------------------------------------------------
# Open Geometric Vision (OpenGV)
# Open Structure from Motion (OpenSfM)
# Clustering Views for Multi-view Stereo (CMVS)
# Catkin
# Ecto
#
set(custom_libs OpenGV
OpenSfM
CMVS
Catkin
Ecto
LASzip

Wyświetl plik

@ -1,28 +0,0 @@
set(_proj_name cmvs)
set(_SB_BINARY_DIR "${SB_BINARY_DIR}/${_proj_name}")
ExternalProject_Add(${_proj_name}
PREFIX ${_SB_BINARY_DIR}
TMP_DIR ${_SB_BINARY_DIR}/tmp
STAMP_DIR ${_SB_BINARY_DIR}/stamp
#--Download step--------------
DOWNLOAD_DIR ${SB_DOWNLOAD_DIR}/${_proj_name}
URL https://github.com/edgarriba/CMVS-PMVS/archive/master.zip
URL_MD5 dbb1493f49ca099b4208381bd20d1435
#--Update/Patch step----------
UPDATE_COMMAND ""
#--Configure step-------------
SOURCE_DIR ${SB_SOURCE_DIR}/${_proj_name}
CONFIGURE_COMMAND cmake <SOURCE_DIR>/program
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH=${SB_INSTALL_DIR}/bin
-DCMAKE_INSTALL_PREFIX:PATH=${SB_INSTALL_DIR}
#--Build step-----------------
BINARY_DIR ${_SB_BINARY_DIR}
#--Install step---------------
INSTALL_DIR ${SB_INSTALL_DIR}
#--Output logging-------------
LOG_DOWNLOAD OFF
LOG_CONFIGURE OFF
LOG_BUILD OFF
)

Wyświetl plik

@ -10,8 +10,6 @@ Licensing for portions of OpenDroneMap are as follows:
* libcv - BSD - http://opencv.org/license.html
* libcvaux - BSD - http://opencv.org/license.html
* bundler - GPLv3 - http://www.gnu.org/copyleft/gpl.html
* cmvs - GPLv3 - http://www.gnu.org/copyleft/gpl.html
* pmvs2 - GPLv3 - http://www.gnu.org/copyleft/gpl.html
* parallel - GPLv3 - http://www.gnu.org/copyleft/gpl.html
* PoissonRecon - BSD - http://www.cs.jhu.edu/~misha/Code/PoissonRecon/license.txt
* vlfeat - BSD - http://www.vlfeat.org/license.html

Wyświetl plik

@ -7,7 +7,7 @@ from appsettings import SettingsParser
import sys
# parse arguments
processopts = ['dataset', 'opensfm', 'slam', 'cmvs', 'pmvs', 'smvs',
processopts = ['dataset', 'opensfm', 'slam', 'smvs',
'odm_meshing', 'odm_25dmeshing', 'mvs_texturing', 'odm_georeferencing',
'odm_dem', 'odm_orthophoto']
@ -241,63 +241,6 @@ def config():
'with --smvs-enable-shading when you have simple JPGs with '
'SRGB gamma correction. Default: %(default)s')
parser.add_argument('--cmvs-maxImages',
metavar='<integer>',
default=500,
type=int,
help='The maximum number of images per cluster. '
'Default: %(default)s')
parser.add_argument('--pmvs-level',
metavar='<positive integer>',
default=1,
type=int,
help=('The level in the image pyramid that is used '
'for the computation. see '
'http://www.di.ens.fr/pmvs/documentation.html for '
'more pmvs documentation. Default: %(default)s'))
parser.add_argument('--pmvs-csize',
metavar='<positive integer>',
default=2,
type=int,
help='Cell size controls the density of reconstructions'
'Default: %(default)s')
parser.add_argument('--pmvs-threshold',
metavar='<float: -1.0 <= x <= 1.0>',
default=0.7,
type=float,
help=('A patch reconstruction is accepted as a success '
'and kept if its associated photometric consistency '
'measure is above this threshold. Default: %(default)s'))
parser.add_argument('--pmvs-wsize',
metavar='<positive integer>',
default=7,
type=int,
help='pmvs samples wsize x wsize pixel colors from '
'each image to compute photometric consistency '
'score. For example, when wsize=7, 7x7=49 pixel '
'colors are sampled in each image. Increasing the '
'value leads to more stable reconstructions, but '
'the program becomes slower. Default: %(default)s')
parser.add_argument('--pmvs-min-images',
metavar='<positive integer>',
default=3,
type=int,
help=('Each 3D point must be visible in at least '
'minImageNum images for being reconstructed. 3 is '
'suggested in general. Default: %(default)s'))
parser.add_argument('--pmvs-num-cores',
metavar='<positive integer>',
default=context.num_cores,
type=int,
help=('The maximum number of cores to use in dense '
'reconstruction. Default: %(default)s'))
parser.add_argument('--mesh-size',
metavar='<positive integer>',
default=100000,
@ -612,11 +555,6 @@ def config():
log.ODM_INFO('Fast orthophoto is turned on, automatically setting --use-25dmesh')
args.use_25dmesh = True
# Cannot use pmvs
if args.use_pmvs:
log.ODM_INFO('Fast orthophoto is turned on, cannot use pmvs (removing --use-pmvs)')
args.use_pmvs = False
if args.dtm and args.pc_classify == 'none':
log.ODM_INFO("DTM is turned on, automatically turning on point cloud classification")
args.pc_classify = "smrf"

Wyświetl plik

@ -23,11 +23,6 @@ ccd_widths_path = os.path.join(opensfm_path, 'opensfm/data/sensor_data.json')
# define orb_slam2 path
orb_slam2_path = os.path.join(superbuild_path, "src/orb_slam2")
# define pmvs path
cmvs_path = os.path.join(superbuild_path, "install/bin/cmvs")
cmvs_opts_path = os.path.join(superbuild_path, "install/bin/genOption")
pmvs2_path = os.path.join(superbuild_path, "install/bin/pmvs2")
# define smvs join_paths
makescene_path = os.path.join(superbuild_path, 'src', 'elibs', 'mve', 'apps', 'makescene', 'makescene') #TODO: don't install in source
smvs_path = os.path.join(superbuild_path, 'src', 'elibs', 'smvs', 'app', 'smvsrecon')

Wyświetl plik

@ -8,8 +8,6 @@ from scripts.opensfm import opensfm
# Define pipeline tasks
tasks_dict = {'1': 'opensfm',
'2': 'cmvs',
'3': 'pmvs',
'4': 'odm_meshing',
'5': 'mvs_texturing',
'6': 'odm_georeferencing',
@ -52,7 +50,7 @@ class ODMTaskManager(object):
'args': _odm_app.args,
'photos': _odm_app.photos}
elif task_name in ['cmvs', 'pmvs', 'odm_meshing', 'mvs_texturing', 'odm_georeferencing', 'odm_orthophoto', 'zip_results']:
elif task_name in [ 'odm_meshing', 'mvs_texturing', 'odm_georeferencing', 'odm_orthophoto', 'zip_results']:
# setup this task
command = None
inputs = {}

Wyświetl plik

@ -274,14 +274,8 @@ class ODM_GeoRef(object):
with open(json_file, 'w') as f:
f.write(pipeline)
<<<<<<< HEAD
# call pdal
system.run('{bin}/pdal pipeline -i {json} --readers.ply.filename={f_in} '
'--writers.las.filename={f_out}'.format(**kwargs))
=======
# call pdal
system.run('{bin}/pdal pipeline -i {json} --readers.ply.filename={f_in}'.format(**kwargs))
>>>>>>> 4a00c4d8411befc0c1b01a36f713e61633f002b3
def utm_to_latlon(self, _file, _photo, idx):
@ -421,7 +415,6 @@ class ODM_Tree(object):
self.dataset_raw = io.join_paths(self.root_path, 'images')
self.opensfm = io.join_paths(self.root_path, 'opensfm')
self.smvs = io.join_paths(self.root_path, 'smvs')
self.pmvs = io.join_paths(self.root_path, 'pmvs')
self.odm_meshing = io.join_paths(self.root_path, 'odm_meshing')
self.odm_texturing = io.join_paths(self.root_path, 'odm_texturing')
self.odm_25dtexturing = io.join_paths(self.root_path, 'odm_texturing_25d')
@ -446,13 +439,6 @@ class ODM_Tree(object):
self.opensfm_model = io.join_paths(self.opensfm, 'depthmaps/merged.ply')
self.opensfm_transformation = io.join_paths(self.opensfm, 'geocoords_transformation.txt')
# pmvs
self.pmvs_rec_path = io.join_paths(self.pmvs, 'recon0')
self.pmvs_bundle = io.join_paths(self.pmvs_rec_path, 'bundle.rd.out')
self.pmvs_visdat = io.join_paths(self.pmvs_rec_path, 'vis.dat')
self.pmvs_options = io.join_paths(self.pmvs_rec_path, 'pmvs_options.txt')
self.pmvs_model = io.join_paths(self.pmvs_rec_path, 'models/option-0000.ply')
# smvs
self.smvs_model = io.join_paths(self.smvs, 'smvs_dense_point_cloud.ply')
self.mve_path = io.join_paths(self.opensfm, 'mve')

2
run.py
Wyświetl plik

@ -33,7 +33,7 @@ if __name__ == '__main__':
+ args.project_path + "/odm_orthophoto "
+ args.project_path + "/odm_texturing "
+ args.project_path + "/opensfm "
+ args.project_path + "/pmvs")
+ args.project_path + "/smvs")
# create an instance of my App BlackBox
# internally configure all tasks

Wyświetl plik

@ -1,68 +0,0 @@
import ecto
from opendm import io
from opendm import log
from opendm import system
from opendm import context
class ODMCmvsCell(ecto.Cell):
def declare_params(self, params):
params.declare("max_images", 'The maximum number of images '
'per cluster', 500)
params.declare("cores", 'The maximum number of cores to use '
'in dense reconstruction.', context.num_cores)
def declare_io(self, params, inputs, outputs):
inputs.declare("tree", "Struct with paths", [])
inputs.declare("args", "Struct with paths", [])
inputs.declare("reconstruction", "list of ODMReconstructions", [])
outputs.declare("reconstruction", "list of ODMReconstructions", [])
def process(self, inputs, outputs):
# Benchmarking
start_time = system.now_raw()
log.ODM_INFO('Running ODM CMVS Cell')
# get inputs
args = self.inputs.args
tree = self.inputs.tree
# check if we rerun cell or not
rerun_cell = (args.rerun is not None and
args.rerun == 'cmvs') or \
(args.rerun_all) or \
(args.rerun_from is not None and
'cmvs' in args.rerun_from)
if not io.file_exists(tree.pmvs_bundle) or rerun_cell:
log.ODM_DEBUG('Writing CMVS vis in: %s' % tree.pmvs_bundle)
# copy bundle file to pmvs dir
from shutil import copyfile
copyfile(tree.opensfm_bundle,
tree.pmvs_bundle)
kwargs = {
'bin': context.cmvs_path,
'prefix': self.inputs.tree.pmvs_rec_path,
'max_images': self.params.max_images,
'cores': self.params.cores
}
# run cmvs
system.run('{bin} {prefix}/ {max_images} {cores}'.format(**kwargs))
else:
log.ODM_WARNING('Found a valid CMVS file in: %s' %
tree.pmvs_bundle)
outputs.reconstruction = inputs.reconstruction
if args.time:
system.benchmark(start_time, tree.benchmarking, 'CMVS')
log.ODM_INFO('Running ODM CMVS Cell - Finished')
return ecto.OK if args.end_with != 'cmvs' else ecto.QUIT

Wyświetl plik

@ -5,8 +5,6 @@ from opendm import io
from opendm import system
from opendm import context
import pmvs2nvmcams
class ODMMvsTexCell(ecto.Cell):
def declare_params(self, params):
params.declare("data_term", 'Data term: [area, gmi] default: gmi', "gmi")
@ -38,7 +36,7 @@ class ODMMvsTexCell(ecto.Cell):
# define paths and create working directories
system.mkdir_p(tree.odm_texturing)
if args.use_25dmesh: system.mkdir_p(tree.odm_25dtexturing)
if args.use_25dmesh: system.mkdir_p(tree.odm_25dtexturing)
# check if we rerun cell or not
rerun_cell = (args.rerun is not None and
@ -62,11 +60,11 @@ class ODMMvsTexCell(ecto.Cell):
'model': tree.odm_25dmesh,
# We always skip the visibility test when using the 2.5D mesh
# because many faces end up being narrow, and almost perpendicular
# because many faces end up being narrow, and almost perpendicular
# to the ground plane. The visibility test improperly classifies
# them as "not seen" since the test is done on a single triangle vertex,
# and while one vertex might be occluded, the other two might not.
'force_skip_vis_test': True
'force_skip_vis_test': True
}]
for r in runs:
@ -82,7 +80,7 @@ class ODMMvsTexCell(ecto.Cell):
skipLocalSeamLeveling = ""
skipHoleFilling = ""
keepUnseenFaces = ""
if (self.params.skip_vis_test or r['force_skip_vis_test']):
skipGeometricVisibilityTest = "--skip_geometric_visibility_test"
if (self.params.skip_glob_seam_leveling):
@ -98,8 +96,6 @@ class ODMMvsTexCell(ecto.Cell):
kwargs = {
'bin': context.mvstex_path,
'out_dir': io.join_paths(r['out_dir'], "odm_textured_model"),
'pmvs_folder': tree.pmvs_rec_path,
'nvm_file': io.join_paths(tree.pmvs_rec_path, "nvmCams.nvm"),
'model': r['model'],
'dataTerm': self.params.data_term,
'outlierRemovalType': self.params.outlier_rem_type,
@ -111,16 +107,8 @@ class ODMMvsTexCell(ecto.Cell):
'toneMapping': self.params.tone_mapping
}
if not args.use_pmvs:
kwargs['nvm_file'] = io.join_paths(tree.opensfm,
"reconstruction.nvm")
else:
log.ODM_DEBUG('Generating .nvm file from pmvs output: %s'
% '{nvm_file}'.format(**kwargs))
# Create .nvm camera file.
pmvs2nvmcams.run('{pmvs_folder}'.format(**kwargs),
'{nvm_file}'.format(**kwargs))
kwargs['nvm_file'] = io.join_paths(tree.opensfm,
"reconstruction.nvm")
# Make sure tmp directory is empty
mvs_tmp_dir = os.path.join(r['out_dir'], 'tmp')

Wyświetl plik

@ -10,8 +10,6 @@ from dataset import ODMLoadDatasetCell
from run_opensfm import ODMOpenSfMCell
from smvs import ODMSmvsCell
from odm_slam import ODMSlamCell
from pmvs import ODMPmvsCell
from cmvs import ODMCmvsCell
from odm_meshing import ODMeshingCell
from mvstex import ODMMvsTexCell
from odm_georeferencing import ODMGeoreferencingCell
@ -51,13 +49,6 @@ class ODMApp(ecto.BlackBox):
fixed_camera_params=p.args.use_fixed_camera_params,
hybrid_bundle_adjustment=p.args.use_hybrid_bundle_adjustment),
'slam': ODMSlamCell(),
'cmvs': ODMCmvsCell(max_images=p.args.cmvs_maxImages),
'pmvs': ODMPmvsCell(level=p.args.pmvs_level,
csize=p.args.pmvs_csize,
thresh=p.args.pmvs_threshold,
wsize=p.args.pmvs_wsize,
min_imgs=p.args.pmvs_min_images,
cores=p.args.pmvs_num_cores),
'smvs': ODMSmvsCell(alpha=p.args.smvs_alpha,
scale=p.args.smvs_scale,
threads=p.args.max_concurrency,
@ -135,7 +126,7 @@ class ODMApp(ecto.BlackBox):
self.args[:] >> self.smvs['args'],
self.opensfm['reconstruction'] >> self.smvs['reconstruction']]
# create odm mesh from pmvs point cloud
# create odm mesh from smvs point cloud
connections += [self.tree[:] >> self.meshing['tree'],
self.args[:] >> self.meshing['args'],
self.smvs['reconstruction'] >> self.meshing['reconstruction']]
@ -169,20 +160,14 @@ class ODMApp(ecto.BlackBox):
connections += [self.tree[:] >> self.slam['tree'],
self.args[:] >> self.slam['args']]
# run cmvs
connections += [self.tree[:] >> self.cmvs['tree'],
self.args[:] >> self.cmvs['args'],
self.slam['reconstruction'] >> self.cmvs['reconstruction']]
# run pmvs
connections += [self.tree[:] >> self.pmvs['tree'],
self.args[:] >> self.pmvs['args'],
self.cmvs['reconstruction'] >> self.pmvs['reconstruction']]
connections += [self.tree[:] >> self.smvs['tree'],
self.args[:] >> self.smvs['args'],
self.slam['reconstruction'] >> self.smvs['reconstruction']]
# create odm mesh
connections += [self.tree[:] >> self.meshing['tree'],
self.args[:] >> self.meshing['args'],
self.pmvs['reconstruction'] >> self.meshing['reconstruction']]
self.smvs['reconstruction'] >> self.meshing['reconstruction']]
# create odm texture
connections += [self.tree[:] >> self.texturing['tree'],

Wyświetl plik

@ -92,13 +92,12 @@ class ODMGeoreferencingCell(ecto.Cell):
'verbose': verbose
}
if not args.use_pmvs:
if args.fast_orthophoto:
kwargs['pc'] = os.path.join(tree.opensfm, 'reconstruction.ply')
else:
kwargs['pc'] = tree.opensfm_model
if args.fast_orthophoto:
kwargs['pc'] = os.path.join(tree.opensfm, 'reconstruction.ply')
else:
kwargs['pc'] = tree.pmvs_model
kwargs['pc'] = tree.opensfm_model
# Check to see if the GCP file exists

Wyświetl plik

@ -39,7 +39,6 @@ class ODMSlamCell(ecto.Cell):
# create working directories
system.mkdir_p(tree.opensfm)
system.mkdir_p(tree.pmvs)
vocabulary = os.path.join(context.orb_slam2_path,
'Vocabulary/ORBvoc.txt')
@ -96,16 +95,5 @@ class ODMSlamCell(ecto.Cell):
'Found a valid Bundler file in: {}'.format(
tree.opensfm_reconstruction))
# check if reconstruction was exported to pmvs before
if not io.file_exists(tree.pmvs_visdat) or rerun_cell:
# run PMVS converter
system.run(
'PYTHONPATH={} {}/bin/export_pmvs {} --output {}'.format(
context.pyopencv_path, context.opensfm_path, tree.opensfm,
tree.pmvs))
else:
log.ODM_WARNING('Found a valid CMVS file in: {}'.format(
tree.pmvs_visdat))
log.ODM_INFO('Running OMD Slam Cell - Finished')
return ecto.OK if args.end_with != 'odm_slam' else ecto.QUIT

Wyświetl plik

@ -1,84 +0,0 @@
import ecto
from opendm import io
from opendm import log
from opendm import system
from opendm import context
class ODMPmvsCell(ecto.Cell):
def declare_params(self, params):
params.declare("level", 'The level in the image pyramid that is used '
'for the computation', 1)
params.declare("csize", 'Cell size controls the density of reconstructions', 2)
params.declare("thresh", 'A patch reconstruction is accepted as a success '
'and kept, if its associcated photometric consistency '
'measure is above this threshold.', 0.7)
params.declare("wsize", 'pmvs samples wsize x wsize pixel colors from '
'each image to compute photometric consistency '
'score. For example, when wsize=7, 7x7=49 pixel '
'colors are sampled in each image. Increasing the '
'value leads to more stable reconstructions, but '
'the program becomes slower.', 7)
params.declare("min_imgs", 'Each 3D point must be visible in at least '
'minImageNum images for being reconstructed. 3 is '
'suggested in general.', 3)
params.declare("cores", 'The maximum number of cores to use in dense '
' reconstruction.', context.num_cores)
def declare_io(self, params, inputs, outputs):
inputs.declare("tree", "Struct with paths", [])
inputs.declare("args", "The application arguments.", {})
inputs.declare("reconstruction", "list of ODMReconstructions", [])
outputs.declare("reconstruction", "list of ODMReconstructions", [])
def process(self, inputs, outputs):
# Benchmarking
start_time = system.now_raw()
log.ODM_INFO('Running OMD PMVS Cell')
# get inputs
args = self.inputs.args
tree = self.inputs.tree
# check if we rerun cell or not
rerun_cell = (args.rerun is not None and
args.rerun == 'pmvs') or \
(args.rerun_all) or \
(args.rerun_from is not None and
'pmvs' in args.rerun_from)
if not io.file_exists(tree.pmvs_model) or rerun_cell:
log.ODM_DEBUG('Creating dense pointcloud in: %s' % tree.pmvs_model)
kwargs = {
'bin': context.cmvs_opts_path,
'prefix': tree.pmvs_rec_path,
'level': self.params.level,
'csize': self.params.csize,
'thresh': self.params.thresh,
'wsize': self.params.wsize,
'min_imgs': self.params.min_imgs,
'cores': self.params.cores
}
# generate pmvs2 options
system.run('{bin} {prefix}/ {level} {csize} {thresh} {wsize} '
'{min_imgs} {cores}'.format(**kwargs))
# run pmvs2
system.run('%s %s/ option-0000' %
(context.pmvs2_path, tree.pmvs_rec_path))
else:
log.ODM_WARNING('Found a valid PMVS file in %s' % tree.pmvs_model)
outputs.reconstruction = inputs.reconstruction
if args.time:
system.benchmark(start_time, tree.benchmarking, 'PMVS')
log.ODM_INFO('Running ODM PMVS Cell - Finished')
return ecto.OK if args.end_with != 'pmvs' else ecto.QUIT

Wyświetl plik

@ -1,144 +0,0 @@
import os
import numpy as np
from opendm import log
# Go from QR-factorizatoin to corresponding RQ-factorization.
def rq(A):
Q,R = np.linalg.qr(np.flipud(A).T)
R = np.flipud(R.T)
Q = Q.T
return R[:,::-1],Q[::-1,:]
# Create a unit quaternion from rotation matrix.
def rot2quat(R):
# Float epsilon (use square root to be well with the stable region).
eps = np.sqrt(np.finfo(float).eps)
# If the determinant is not 1, it's not a rotation matrix
if np.abs(np.linalg.det(R) - 1.0) > eps:
log.ODM_ERROR('Matrix passed to rot2quat was not a rotation matrix, det != 1.0')
tr = np.trace(R)
quat = np.zeros((1,4))
# Is trace big enough be computationally stable?
if tr > eps:
S = 0.5 / np.sqrt(tr + 1.0)
quat[0,0] = 0.25 / S
quat[0,1] = (R[2,1] - R[1,2]) * S
quat[0,2] = (R[0,2] - R[2,0]) * S
quat[0,3] = (R[1,0] - R[0,1]) * S
else: # It's not, use the largest diagonal.
if R[0,0] > R[1,1] and R[0,0] > R[2,2]:
S = np.sqrt(1.0 + R[0,0] - R[1,1] - R[2,2]) * 2.0
quat[0,0] = (R[2,1] - R[1,2]) / S
quat[0,1] = 0.25 * S
quat[0,2] = (R[0,1] + R[1,0]) / S
quat[0,3] = (R[0,2] + R[2,0]) / S
elif R[1,1] > R[2,2]:
S = np.sqrt(1.0 - R[0,0] + R[1,1] - R[2,2]) * 2.0
quat[0,0] = (R[0,2] - R[2,0]) / S
quat[0,1] = (R[0,1] + R[1,0]) / S
quat[0,2] = 0.25 * S
quat[0,3] = (R[1,2] + R[2,1]) / S
else:
S = np.sqrt(1.0 - R[0,0] - R[1,1] + R[2,2]) * 2.0
quat[0,0] = (R[1,0] - R[0,1]) / S
quat[0,1] = (R[0,2] + R[2,0]) / S
quat[0,2] = (R[1,2] + R[2,1]) / S
quat[0,3] = 0.25 * S
return quat
# Decompose a projection matrix into parts
# (Intrinsic projection, Rotation, Camera position)
def decomposeProjection(projectionMatrix):
# Check input:
if projectionMatrix.shape != (3,4):
log.ODM_ERROR('Unable to decompose projection matrix, shape != (3,4)')
RQ = rq(projectionMatrix[:,:3])
# Fix sign, since we know K is upper triangular and has a positive diagonal.
signMat = np.diag(np.diag(np.sign(RQ[0])))
K = signMat*RQ[0]
R = signMat*RQ[1]
# Calculate camera position from translation vector.
t = np.linalg.inv(-1.0*projectionMatrix[:,:3])*projectionMatrix[:,3]
return K, R, t
# Parses pvms contour file.
def parseContourFile(filePath):
with open(filePath, 'r') as contourFile:
if (contourFile.readline().strip() != "CONTOUR"):
return np.array([])
else:
pMatData = np.loadtxt(contourFile, float, '#', None, None, 0)
if pMatData.shape == (3,4):
return pMatData
return np.array([])
# Creates a .nvm camera file in the pmvs folder.
def run(pmvsFolder, outputFile):
projectionFolder = pmvsFolder + "/txt"
imageFolder = pmvsFolder + "/visualize"
pMatrices = []
imageFileNames = []
# for all files in the visualize folder:
for imageFileName in os.listdir(imageFolder):
fileNameNoExt = os.path.splitext(imageFileName)[0]
# look for corresponding projection matrix txt file
projectionFilePath = os.path.join(projectionFolder, fileNameNoExt)
projectionFilePath += ".txt"
if os.path.isfile(projectionFilePath):
pMatData = parseContourFile(projectionFilePath)
if pMatData.size == 0:
log.ODM_WARNING('Unable to parse contour file, skipping: %s'
% projectionFilePath)
else:
pMatrices.append(np.matrix(pMatData))
imageFileNames.append(imageFileName)
# Decompose projection matrices
focals = []
rotations = []
translations = []
for projection in pMatrices:
KRt = decomposeProjection(projection)
focals.append(KRt[0][0,0])
rotations.append(rot2quat(KRt[1]))
translations.append(KRt[2])
# Create .nvm file
with open (outputFile, 'w') as nvmFile:
nvmFile.write("NVM_V3\n\n")
nvmFile.write('%d' % len(rotations) + "\n")
for idx, imageFileName in enumerate(imageFileNames):
nvmFile.write(os.path.join("visualize", imageFileName))
nvmFile.write(" " + '%f' % focals[idx])
nvmFile.write(" " + '%f' % rotations[idx][0,0] +
" " + '%f' % rotations[idx][0,1] +
" " + '%f' % rotations[idx][0,2] +
" " + '%f' % rotations[idx][0,3])
nvmFile.write(" " + '%f' % translations[idx][0] +
" " + '%f' % translations[idx][1] +
" " + '%f' % translations[idx][2])
nvmFile.write(" 0 0\n")
nvmFile.write("0\n\n")
nvmFile.write("0\n\n")
nvmFile.write("0")

Wyświetl plik

@ -42,7 +42,6 @@ class ODMOpenSfMCell(ecto.Cell):
# create working directories
system.mkdir_p(tree.opensfm)
system.mkdir_p(tree.pmvs)
# check if we rerun cell or not
rerun_cell = (args.rerun is not None and
@ -169,15 +168,6 @@ class ODMOpenSfMCell(ecto.Cell):
log.ODM_WARNING('Found a valid Bundler file in: %s' %
tree.opensfm_reconstruction)
# if args.use_pmvs:
# # check if reconstruction was exported to pmvs before
# if not io.file_exists(tree.pmvs_visdat) or rerun_cell:
# # run PMVS converter
# system.run('PYTHONPATH=%s %s/bin/export_pmvs %s --output %s' %
# (context.pyopencv_path, context.opensfm_path, tree.opensfm, tree.pmvs))
# else:
# log.ODM_WARNING('Found a valid CMVS file in: %s' % tree.pmvs_visdat)
if reconstruction.georef:
system.run('PYTHONPATH=%s %s/bin/opensfm export_geocoords %s --transformation --proj \'%s\'' %
(context.pyopencv_path, context.opensfm_path, tree.opensfm, reconstruction.georef.projection.srs))

Wyświetl plik

@ -66,7 +66,7 @@ class ODMSmvsCell(ecto.Cell):
"-a%s" % self.params.alpha,
"-s%s" % self.params.scale,
"-o%s" % self.params.output_scale,
"--debug-lvl=%s" % '1' if self.params.verbose else '0',
"--debug-lvl=%s" % ('1' if self.params.verbose else '0'),
"%s" % '-S' if self.params.shading else '',
"%s" % '-g' if self.params.gamma_srgb and self.params.shading else '',
"--force" if rerun_cell else ''