Merge branch 'master' into image-load-process

pull/440/head
Dakota Benjamin 2016-12-21 13:53:28 -05:00 zatwierdzone przez GitHub
commit fc2ccf4ce5
11 zmienionych plików z 75 dodań i 65 usunięć

Wyświetl plik

@ -63,7 +63,6 @@ Include details about your configuration and environment:
* Problem happens with all datasets and projects, not only some datasets or projects: [Yes/No]
### Pull Requests
* ***Pull Requests should be made to the `dev` branch unless it is a critical bug.***
* Include screenshots and animated GIFs in your pull request whenever possible.
* Follow the [PEP8 Python Style Guide](https://www.python.org/dev/peps/pep-0008/).
* End files with a newline.

Wyświetl plik

@ -29,17 +29,22 @@ Requires Ubuntu 14.04 or later, see https://github.com/OpenDroneMap/odm_vagrant
**[Download the latest release here](https://github.com/OpenDroneMap/OpenDroneMap/releases)**
Current version: 0.2 (beta)
Current version: 0.2 (this software is in beta)
1. Extract and enter the OpenDroneMap directory
2. Run `bash configure.sh`
3. Download and extract a sample dataset [here](https://github.com/OpenDroneMap/odm_data_aukerman/archive/master.zip)
4. Run `./run.sh --project-path <PATH>`, replacing `<PATH>` with the dataset path.
5. Enter dataset directory to view results:
- orthophoto: odm_orthophoto/odm_orthophoto.tif
- textured mesh model: odm_texturing/odm_textured_model_geo.obj
- point cloud (georeferenced): odm_georeferencing/odm_georeferenced_model.ply
See below for more detailed installation instructions.
### Installation
Before installing you need to set your environment variables. Open the ~/.bashrc file on your machine and add the following 3 lines at the end. The file can be opened with ```gedit ~/.bashrc``` if you are using an Ubuntu desktop environment. Be sure to replace the "/your/path/" with the correct path to the location where you extracted OpenDroneMap:
export PYTHONPATH=$PYTHONPATH:/your/path/OpenDroneMap/SuperBuild/install/lib/python2.7/dist-packages
export PYTHONPATH=$PYTHONPATH:/your/path/OpenDroneMap/SuperBuild/src/opensfm
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/your/path/OpenDroneMap/SuperBuild/install/lib
Now, enter the OpenDroneMap directory and compile all of the code by executing a single configuration script:
Extract and enter the downloaded OpenDroneMap directory and compile all of the code by executing a single configuration script:
bash configure.sh
@ -48,6 +53,16 @@ For Ubuntu 15.10 users, this will help you get running:
sudo apt-get install python-xmltodict
sudo ln -s /usr/lib/x86_64-linux-gnu/libproj.so.9 /usr/lib/libproj.so
### Environment Variables
There are some environmental variables that need to be set. Open the ~/.bashrc file on your machine and add the following 3 lines at the end. The file can be opened with ```gedit ~/.bashrc``` if you are using an Ubuntu desktop environment. Be sure to replace the "/your/path/" with the correct path to the location where you extracted OpenDroneMap:
export PYTHONPATH=$PYTHONPATH:/your/path/OpenDroneMap/SuperBuild/install/lib/python2.7/dist-packages
export PYTHONPATH=$PYTHONPATH:/your/path/OpenDroneMap/SuperBuild/src/opensfm
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/your/path/OpenDroneMap/SuperBuild/install/lib
Note that using `run.sh` sets these temporarily in the shell.
### Run OpenDroneMap
First you need a set of images, taken from a drone or otherwise. Example data can be cloned from https://github.com/OpenDroneMap/odm_data
@ -109,11 +124,9 @@ has equivalent procedures for Mac OS X and Windows. See [docs.docker.com](docs.d
OpenDroneMap is Dockerized, meaning you can use containerization to build and run it without tampering with the configuration of libraries and packages already
installed on your machine. Docker software is free to install and use in this context. If you don't have it installed,
see the [Docker Ubuntu installation tutorial](https://docs.docker.com/engine/installation/linux/ubuntulinux/) and follow the
instructions up until "Create a Docker group" inclusive. Once Docker is installed, an OpenDroneMap Docker image can be created
instructions through "Create a Docker group". Once Docker is installed, an OpenDroneMap Docker image can be created
like so:
git clone https://github.com/OpenDroneMap/OpenDroneMap.git
cd OpenDroneMap
docker build -t packages -f packages.Dockerfile .
docker build -t odm_image .
docker run -it --user root\
@ -122,8 +135,8 @@ like so:
-v /path/to/gcp_list.txt:/code/gcp_list.txt \
--rm odm_image --project-path /project
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** section.
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** section.
To pass in custom parameters to the run.py script, simply pass it as arguments to the `docker run` command.
@ -133,22 +146,11 @@ A web interface and API to OpenDroneMap is currently under active development in
## Examples
Here are some other videos, which may be outdated:
- https://www.youtube.com/watch?v=7ZTufQkODLs (2015-01-30)
- https://www.youtube.com/watch?v=m0i4GQdfl8A (2015-03-15)
Now that texturing is in the code base, you can access the full textured meshes using MeshLab.
Open MeshLab, choose `File:Import Mesh` and choose your textured mesh from a location similar to the following:
`reconstruction-with-image-size-1200-results\odm_texturing\odm_textured_model.obj`. Long term, the aim is for
the toolchain to also be able to optionally push to a variety of online data repositories, pushing hi-resolution
aerials to [OpenAerialMap](https://openaerialmap.org/), point clouds to [OpenTopography](http://opentopography.org/),
and pushing digital elevation models to an emerging global repository (yet to be named...). That leaves only
digital surface model meshes and UV textured meshes with no global repository home.
Coming soon...
## Documentation:
For documentation, please take a look at our [wiki](https://github.com/OpenDroneMap/OpenDroneMap/wiki).Check here first if you are heaving problems. If you still need help, look through the issue queue or create one. There's also a general help chat [here](https://gitter.im/OpenDroneMap/generalhelp).
For documentation, please take a look at our [wiki](https://github.com/OpenDroneMap/OpenDroneMap/wiki).Check here first if you are having problems. If you still need help, look through the issue queue or create one. There's also a general help chat [here](https://gitter.im/OpenDroneMap/generalhelp).
## Developers

Wyświetl plik

@ -1197,7 +1197,7 @@ void Georef::chooseBestCameraTriplet(size_t &cam0, size_t &cam1, size_t &cam2)
trans.findTransform(cameras_[t].getPos(), cameras_[s].getPos(), cameras_[p].getPos(),
cameras_[t].getReferencedPos(), cameras_[s].getReferencedPos(), cameras_[p].getReferencedPos());
// The total error for the curren camera triplet.
// The total error for the current camera triplet.
double totError = 0.0;
for(size_t r = 0; r < cameras_.size(); ++r)

Wyświetl plik

@ -279,6 +279,12 @@ def config():
default=False,
help='compress the results using gunzip')
parser.add_argument('--verbose', '-v',
action='store_true',
default=False,
help='Print additional messages to the console\n'
'Default: %(default)s')
parser.add_argument('--time',
action='store_true',
default=False,

Wyświetl plik

@ -18,22 +18,8 @@ logging.basicConfig(level=logging.DEBUG,
format='%(levelname)-14s %(message)s' + ENDC)
def ODM_INFO(str):
logging.info(str)
def ODM_WARNING(str):
logging.warning(str)
def ODM_ERROR(str):
logging.error(str)
def ODM_EXCEPTION(str):
logging.exception(str)
def ODM_DEBUG(str):
logging.debug(str)
ODM_INFO = logging.info
ODM_WARNING = logging.warning
ODM_ERROR = logging.error
ODM_EXCEPTION = logging.exception
ODM_DEBUG = logging.debug

Wyświetl plik

@ -16,15 +16,16 @@ def get_ccd_widths():
sensor_data = json.loads(f.read())
return dict(zip(map(string.lower, sensor_data.keys()), sensor_data.values()))
def run(cmd):
"""Run a system command"""
log.ODM_DEBUG('running %s' % cmd)
returnCode = os.system(cmd)
retcode = subprocess.call(cmd, shell=True)
if (returnCode != 0):
log.ODM_ERROR("quitting cause: \n\t" + cmd + "\nreturned with code " +
str(returnCode) + ".\n")
sys.exit('An error occurred. Check stdout above or the logs.')
if retcode < 0:
raise Exception("Child was terminated by signal {}".format(-retcode))
elif retcode > 0:
raise Exception("Child returned {}".format(retcode))
def now():

Wyświetl plik

@ -56,7 +56,8 @@ class ODMApp(ecto.BlackBox):
'meshing': ODMeshingCell(max_vertex=p.args.mesh_size,
oct_tree=p.args.mesh_octree_depth,
samples=p.args.mesh_samples,
solver=p.args.mesh_solver_divide),
solver=p.args.mesh_solver_divide,
verbose=p.args.verbose),
'texturing': ODMMvsTexCell(data_term=p.args.texturing_data_term,
outlier_rem_type=p.args.texturing_outlier_removal_type,
skip_vis_test=p.args.texturing_skip_visibility_test,
@ -65,9 +66,10 @@ class ODMApp(ecto.BlackBox):
skip_hole_fill=p.args.texturing_skip_hole_filling,
keep_unseen_faces=p.args.texturing_keep_unseen_faces),
'georeferencing': ODMGeoreferencingCell(img_size=p.args.resize_to,
gcp_file=p.args.gcp),
'orthophoto': ODMOrthoPhotoCell(resolution=p.args.orthophoto_resolution)
gcp_file=p.args.gcp,
verbose=p.args.verbose),
'orthophoto': ODMOrthoPhotoCell(resolution=p.args.orthophoto_resolution,
verbose=p.args.verbose)
}
return cells

Wyświetl plik

@ -16,6 +16,7 @@ class ODMGeoreferencingCell(ecto.Cell):
'be on the following line format: \neasting '
'northing height pixelrow pixelcol imagename', 'gcp_list.txt')
params.declare("img_size", 'image size used in calibration', 2400)
params.declare("verbose", 'print additional messages to console', False)
def declare_io(self, params, inputs, outputs):
inputs.declare("tree", "Struct with paths", [])
@ -42,6 +43,7 @@ class ODMGeoreferencingCell(ecto.Cell):
gcpfile = io.join_paths(tree.root_path, self.params.gcp_file) \
if self.params.gcp_file else find('gcp_list.txt', tree.root_path)
geocreated = True
verbose = '-verbose' if self.params.verbose else ''
# define paths and create working directories
system.mkdir_p(tree.odm_georeferencing)
@ -63,11 +65,12 @@ class ODMGeoreferencingCell(ecto.Cell):
'imgs_list': tree.opensfm_bundle_list,
'coords': tree.odm_georeferencing_coords,
'log': tree.odm_georeferencing_utm_log
'verbose': verbose
}
# run UTM extraction binary
extract_utm = system.run_and_return('{bin}/odm_extract_utm -imagesPath {imgs}/ '
'-imageListFile {imgs_list} -outputCoordFile {coords} '
'-imageListFile {imgs_list} -outputCoordFile {coords} {verbose} '
'-logFile {log}'.format(**kwargs))
if extract_utm != '':
@ -75,6 +78,7 @@ class ODMGeoreferencingCell(ecto.Cell):
'Ignore if there is a GCP file. Error: %s'
% extract_utm)
# check if we rerun cell or not
rerun_cell = (args.rerun is not None and
args.rerun == 'odm_georeferencing') or \
@ -99,6 +103,7 @@ class ODMGeoreferencingCell(ecto.Cell):
'model_geo': tree.odm_georeferencing_model_obj_geo,
'size': self.params.img_size,
'gcp': gcpfile,
'verbose': verbose
}
if args.use_opensfm_pointcloud:
@ -112,14 +117,14 @@ class ODMGeoreferencingCell(ecto.Cell):
log.ODM_INFO('Found %s' % gcpfile)
system.run('{bin}/odm_georef -bundleFile {bundle} -imagesPath {imgs} -imagesListPath {imgs_list} '
'-bundleResizedTo {size} -inputFile {model} -outputFile {model_geo} '
'-inputPointCloudFile {pc} -outputPointCloudFile {pc_geo} '
'-inputPointCloudFile {pc} -outputPointCloudFile {pc_geo} {verbose} '
'-logFile {log} -georefFileOutputPath {geo_sys} -gcpFile {gcp} '
'-outputCoordFile {coords}'.format(**kwargs))
elif io.file_exists(tree.odm_georeferencing_coords):
log.ODM_INFO('Running georeferencing with generated coords file.')
system.run('{bin}/odm_georef -bundleFile {bundle} -inputCoordFile {coords} '
'-inputFile {model} -outputFile {model_geo} '
'-inputPointCloudFile {pc} -outputPointCloudFile {pc_geo} '
'-inputPointCloudFile {pc} -outputPointCloudFile {pc_geo} {verbose} '
'-logFile {log} -georefFileOutputPath {geo_sys}'.format(**kwargs))
else:
log.ODM_WARNING('Georeferencing failed. Make sure your '

Wyświetl plik

@ -19,6 +19,7 @@ class ODMeshingCell(ecto.Cell):
'is solved in the surface reconstruction step. '
'Increasing this value increases computation '
'times slightly but helps reduce memory usage.', 9)
params.declare("verbose", 'print additional messages to console', False)
def declare_io(self, params, inputs, outputs):
inputs.declare("tree", "Struct with paths", [])
@ -36,6 +37,7 @@ class ODMeshingCell(ecto.Cell):
# get inputs
args = self.inputs.args
tree = self.inputs.tree
verbose = '-verbose' if self.params.verbose else ''
# define paths and create working directories
system.mkdir_p(tree.odm_meshing)
@ -57,7 +59,8 @@ class ODMeshingCell(ecto.Cell):
'max_vertex': self.params.max_vertex,
'oct_tree': self.params.oct_tree,
'samples': self.params.samples,
'solver': self.params.solver
'solver': self.params.solver,
'verbose': verbose
}
if args.use_opensfm_pointcloud:
kwargs['infile'] = tree.opensfm_model
@ -67,7 +70,7 @@ class ODMeshingCell(ecto.Cell):
# run meshing binary
system.run('{bin}/odm_meshing -inputFile {infile} '
'-outputFile {outfile} -logFile {log} '
'-maxVertexCount {max_vertex} -octreeDepth {oct_tree} '
'-maxVertexCount {max_vertex} -octreeDepth {oct_tree} {verbose} '
'-samplesPerNode {samples} -solverDivide {solver}'.format(**kwargs))
else:
log.ODM_WARNING('Found a valid ODM Mesh file in: %s' %

Wyświetl plik

@ -10,6 +10,7 @@ from opendm import types
class ODMOrthoPhotoCell(ecto.Cell):
def declare_params(self, params):
params.declare("resolution", 'Orthophoto ground resolution in pixels/meter', 20)
params.declare("verbose", 'print additional messages to console', False)
def declare_io(self, params, inputs, outputs):
inputs.declare("tree", "Struct with paths", [])
@ -26,6 +27,7 @@ class ODMOrthoPhotoCell(ecto.Cell):
# get inputs
args = self.inputs.args
tree = self.inputs.tree
verbose = '-verbose' if self.params.verbose else ''
# define paths and create working directories
system.mkdir_p(tree.odm_orthophoto)
@ -45,7 +47,8 @@ class ODMOrthoPhotoCell(ecto.Cell):
'log': tree.odm_orthophoto_log,
'ortho': tree.odm_orthophoto_file,
'corners': tree.odm_orthophoto_corners,
'res': self.params.resolution
'res': self.params.resolution,
'verbose': verbose
}
kwargs['model_geo'] = tree.odm_georeferencing_model_obj_geo \
@ -55,7 +58,7 @@ class ODMOrthoPhotoCell(ecto.Cell):
# run odm_orthophoto
system.run('{bin}/odm_orthophoto -inputFile {model_geo} '
'-logFile {log} -outputFile {ortho} -resolution {res} '
'-logFile {log} -outputFile {ortho} -resolution {res} {verbose} '
'-outputCornerFile {corners}'.format(**kwargs))
if not io.file_exists(tree.odm_georeferencing_coords):

Wyświetl plik

@ -13,6 +13,7 @@ class ODMTexturingCell(ecto.Cell):
'greater than textureWithSize.', 4096)
params.declare("size", 'The resolution to rescale the images performing '
'the texturing.', 3600)
params.declare("verbose", 'print additional messages to console', False)
def declare_io(self, params, inputs, outputs):
inputs.declare("tree", "Struct with paths", [])
@ -30,6 +31,7 @@ class ODMTexturingCell(ecto.Cell):
# get inputs
args = self.inputs.args
tree = self.inputs.tree
verbose = '-verbose' if self.params.verbose else ''
# define paths and create working directories
system.mkdir_p(tree.odm_texturing)
@ -56,14 +58,15 @@ class ODMTexturingCell(ecto.Cell):
'log': tree.odm_texuring_log,
'resize': self.params.resize,
'resolution': self.params.resolution,
'size': self.params.size
'size': self.params.size,
'verbose': verbose
}
# run texturing binary
system.run('{bin}/odm_texturing -bundleFile {bundle} '
'-imagesPath {imgs_path} -imagesListPath {imgs_list} '
'-inputModelPath {model} -outputFolder {out_dir}/ '
'-textureResolution {resolution} -bundleResizedTo {resize} '
'-textureResolution {resolution} -bundleResizedTo {resize} {verbose} '
'-textureWithSize {size} -logFile {log}'.format(**kwargs))
else:
log.ODM_WARNING('Found a valid ODM Texture file in: %s'