reorganize and adding ecto

pull/249/head
edgarriba 2015-11-26 12:15:02 +00:00
rodzic 54cb2250ab
commit 487b541966
13 zmienionych plików z 393 dodań i 253 usunięć

Wyświetl plik

@ -6,9 +6,9 @@ processopts = ['resize', 'opensfm', 'cmvs', 'pmvs',
'odm_orthophoto'] 'odm_orthophoto']
parser = argparse.ArgumentParser(description='OpenDroneMap') parser = argparse.ArgumentParser(description='OpenDroneMap')
parser.add_argument('--images-src', parser.add_argument('--project-path',
metavar='<string>', metavar='<string>',
help='Path to the images to process') help='Path to the project to process')
parser.add_argument('--resize-to', # currently doesn't support 'orig' parser.add_argument('--resize-to', # currently doesn't support 'orig'
metavar='<integer>', metavar='<integer>',

Wyświetl plik

@ -1,48 +0,0 @@
import os
import log
import context
import datatypes
def load_dataset(images_dir, args):
# check if the extension is sopported
def supported_extension(file_name):
(pathfn, ext) = os.path.splitext(file_name)
return ext.lower() in context.supported_extensions
log.ODM_DEBUG('Loading dataset from: %s' % images_dir)
# find files in the given directory
files = os.listdir(images_dir)
# filter images for its extension type
# by now only 'jpg' and 'jpeg are supported
files = [f for f in files if supported_extension(f)]
if len(files) < 1:
log.ODM_ERROR('Not found enough supported images in %s' % images_dir)
return
photos = []
# create ODMPhoto list
for f in files:
path_file = os.path.join(images_dir, f)
photos.append(datatypes.ODMPhoto(path_file, args))
log.ODM_INFO('Found %s usable images' % len(photos))
return photos
def extract_file_from_path_file(path_file):
path, file = os.path.split(path_file)
return file
def extract_path_from_file(file):
path_file = os.path.abspath(os.path.dirname(file))
path, file = os.path.split(path_file)
return path
def join_paths(path1, path2):
return os.path.join(path1, path2)

22
opendm/io.py 100644
Wyświetl plik

@ -0,0 +1,22 @@
import os
def get_files_list(path_dir):
return os.listdir(path_dir)
def absolute_path_file(path_file):
return os.path.abspath(path_file)
def extract_file_from_path_file(path_file):
path, file = os.path.split(path_file)
return file
def extract_path_from_file(file):
path_file = os.path.abspath(os.path.dirname(file))
path, file = os.path.split(path_file)
return path
def join_paths(path1, path2):
return os.path.join(path1, path2)
def file_exists(path_file):
return os.path.isfile(path_file)

Wyświetl plik

@ -2,8 +2,10 @@ import os
import errno import errno
import json import json
import datetime import datetime
import sys
from opendm import context from opendm import context
from opendm import log
def get_ccd_widths(): def get_ccd_widths():
"""Return the CCD Width of the camera listed in the JSON defs file.""" """Return the CCD Width of the camera listed in the JSON defs file."""
@ -12,10 +14,11 @@ def get_ccd_widths():
def run(cmd): def run(cmd):
"""Run a system command""" """Run a system command"""
print 'running', cmd log.ODM_DEBUG('running %s' % cmd)
returnCode = os.system(cmd) returnCode = os.system(cmd)
print 'b'
if (returnCode != 0): if (returnCode != 0):
# TODO(edgar): add as log.ODM_ERROR
sys.exit("\nquitting cause: \n\t" + cmd + "\nreturned with code " + sys.exit("\nquitting cause: \n\t" + cmd + "\nreturned with code " +
str(returnCode) + ".\n") str(returnCode) + ".\n")

Wyświetl plik

@ -2,7 +2,7 @@ import log
import system import system
import dataset import dataset
import datatypes import types
from scripts.resize import resize from scripts.resize import resize
from scripts.opensfm import opensfm from scripts.opensfm import opensfm

Wyświetl plik

@ -3,41 +3,8 @@ import pyexiv2
import subprocess import subprocess
import log import log
import dataset import io
import system import system
import tasks
class ODMApp:
''' ODMApp - a class for ODM Activities
'''
def __init__(self, args):
# Internal app config
self.args = args
self.project_path = os.path.abspath(args['images_src'])
# Initialize odm photos
self.photos = []
# Task manager
# configure and schedule tasks
self.task_manager = tasks.ODMTaskManager(self)
# Run all tasks given an starting point
def run_all(self, initial_task, final_task):
# found ids for tasks
t_dict = tasks.tasks_dict
initial_task_id = [k for k in t_dict if t_dict[k]==initial_task][0]
final_task_id = [k for k in t_dict if t_dict[k]==final_task][0]
if initial_task_id > final_task_id:
log.ODM_ERROR('Initial task must be lower than final')
return
# setup task manager
self.task_manager.initial_task_id = int(initial_task_id)
self.task_manager.final_task_id = int(final_task_id)
# run defined pipeline
self.task_manager.run_tasks()
class ODMPhoto: class ODMPhoto:
""" ODMPhoto - a class for ODMPhotos """ ODMPhoto - a class for ODMPhotos
@ -46,7 +13,7 @@ class ODMPhoto:
# general purpose # general purpose
self.path_file = path_file self.path_file = path_file
# useful attibutes # useful attibutes
self.file_name = None self.filename = None
self.width = None self.width = None
self.height = None self.height = None
self.ccd_width = None self.ccd_width = None
@ -94,10 +61,10 @@ class ODMPhoto:
self.height * (self.focal_length / self.ccd_width) self.height * (self.focal_length / self.ccd_width)
log.ODM_DEBUG('Loaded %s | dimensions: %s x %s | focal: %smm | ccd: %smm' % \ log.ODM_DEBUG('Loaded %s | dimensions: %s x %s | focal: %smm | ccd: %smm' % \
(self.file_name, self.width, self.height, self.focal_length, self.ccd_width)) (self.filename, self.width, self.height, self.focal_length, self.ccd_width))
else: else:
log.ODM_WARNING('No CCD width or focal length found for image file: \n' + log.ODM_WARNING('No CCD width or focal length found for image file: \n' +
self.file_name + ' camera: \"' + self.camera_model) self.filename + ' camera: \"' + self.camera_model)
def parse_pyexiv2_values(self, _path_file, args): def parse_pyexiv2_values(self, _path_file, args):
@ -116,14 +83,18 @@ class ODMPhoto:
elif key == 'Exif.Photo.FocalLength': elif key == 'Exif.Photo.FocalLength':
self.focal_length = float(val) self.focal_length = float(val)
# extract and set filename from path file
self.filename = io.extract_file_from_path_file(_path_file)
# find ccd_width from file if needed # find ccd_width from file if needed
if self.ccd_width is None: if self.ccd_width is None and self.camera_model is not None:
# load ccd_widths from file # load ccd_widths from file
ccd_widths = system.get_ccd_widths() ccd_widths = system.get_ccd_widths()
# search ccd by camera model
key = [x for x in ccd_widths.keys() if self.camera_model in x][0] key = [x for x in ccd_widths.keys() if self.camera_model in x]
if key is not None: # convert to float if found
self.ccd_width = float(ccd_widths[key]) if len(key) > 0:
self.ccd_width = float(ccd_widths[key][0])
else: else:
log.ODM_ERROR('Could not find ccd_width in file') log.ODM_ERROR('Could not find ccd_width in file')
@ -150,7 +121,7 @@ class ODMPhoto:
# parse values to attributes # parse values to attributes
if key == 'File name': if key == 'File name':
self.path_file = val self.path_file = val
self.file_name = dataset.extract_file_from_path_file(val) self.filename = io.extract_file_from_path_file(val)
elif key == 'File size': self.file_size = val elif key == 'File size': self.file_size = val
elif key == 'File date': self.file_date = val elif key == 'File date': self.file_date = val
elif key == 'Camera make': self.camera_make = val elif key == 'Camera make': self.camera_make = val

32
run.py
Wyświetl plik

@ -1,14 +1,16 @@
#!/usr/bin/python #!/usr/bin/python
import sys import sys
import ecto
from scripts.odm_app import ODMApp
from opendm import log from opendm import log
from opendm import config from opendm import config
from opendm import system from opendm import system
from opendm.datatypes import ODMApp
def usage(): def usage():
log.ODM_ERROR('USAGE: %s --images-src dataset_path' % sys.argv[0]) log.ODM_ERROR('USAGE: %s --project-path [project_path]' % sys.argv[0])
log.ODM_ERROR('OpenDroneMap app finished - %s' % system.now()) log.ODM_ERROR('OpenDroneMap app finished - %s' % system.now())
sys.exit(0) sys.exit(0)
@ -17,28 +19,18 @@ if __name__ == '__main__':
log.ODM_INFO('Initializing OpenDroneMap app - %s' % system.now()) log.ODM_INFO('Initializing OpenDroneMap app - %s' % system.now())
# Force to provide the images path # Force to provide the images path
if config.args.get('images_src') is None: if config.args.get('project_path') is None:
usage() usage()
# Initialize odm app # create an instance of my App BlackBox
# internally configure all tasks # internally configure all tasks
app = ODMApp(config.args) app = ODMApp(project_path=config.args['project_path'], args=config.args)
log.ODM_INFO('Runnning OpenDroneMap app - %s' % system.now()) # create a plasm that only contains the BlackBox
plasm = ecto.Plasm()
plasm.insert(app)
# run single task # execute the plasm
if config.args.get('run_only') is not None: plasm.execute(niter=1)
# task to run
tasks = config.args['run_only']
app.run_all(tasks, tasks)
# run multiple tasks
else:
# get initial and final tasks
initial_task = config.args['start_with']
final_task = config.args['end_with']
# run tasks
app.run_all(initial_task, final_task)
log.ODM_INFO('OpenDroneMap app finished - %s' % system.now()) log.ODM_INFO('OpenDroneMap app finished - %s' % system.now())

Wyświetl plik

@ -1,32 +0,0 @@
import system
def cmvs():
"""Run CMVS"""
print "\n - running cmvs - " + system.now()
os.chdir(jobOptions["jobDir"])
run("\"" + BIN_PATH + "/cmvs\" pmvs/ " + str(args['--cmvs-maxImages']) \
+ " " + str(CORES))
run("\"" + BIN_PATH + "/genOption\" pmvs/ " + str(args['--pmvs-level']) \
+ " " + str(args['--pmvs-csize']) + " " + str(args['--pmvs-threshold']) \
+ " " + str(args['--pmvs-wsize']) + " " + str(args['--pmvs-minImageNum']) \
+ " " + str(CORES))
if args['--end-with'] != "cmvs":
pmvs()
def pmvs():
"""Run PMVS"""
print "\n - running pmvs - " + system.now()
os.chdir(jobOptions["jobDir"])
run("\"" + BIN_PATH + "/pmvs2\" pmvs/ option-0000")
run("cp -Rf \"" + jobOptions["jobDir"] + "/pmvs/models\" \"" + jobOptions["jobDir"] + "-results\"")
if args['--end-with'] != "pmvs":
odm_meshing()

39
scripts/cmvs.py 100644
Wyświetl plik

@ -0,0 +1,39 @@
import ecto
from opendm import io
from opendm import log
from opendm import system
class ODMCmvsCell(ecto.Cell):
def declare_params(self, params):
params.declare("cmvs_max_images", "The application arguments.", False)
params.declare("pmvs_level", "The application arguments.", False)
params.declare("pmvs_csize", "The application arguments.", 0)
params.declare("pmvs_threshold", "The application arguments.", 0)
params.declare("pmvs_wsize", "The application arguments.", 0)
params.declare("pmvs_min_image_num", "The application arguments.", 0)
def declare_io(self, params, inputs, outputs):
inputs.declare("project_path", "The directory to the images to load.", "")
inputs.declare("bundler_file_path", "Clusters output. list of reconstructions", [])
def process(self, inputs, outputs):
log.ODM_INFO('Running OMD CMVS Cell')
# get inputs
bundler_file_path = self.inputs.bundler_file_path
project_path = io.absolute_path_file(self.inputs.project_path)
# run cmvs binary
#bin_dir='/home/vagrant/software/OpenDroneMap-edgarriba/SuperBuild/build/cmvs/main/cmvs'
bin_dir='/home/vagrant/software/OpenDroneMap-edgarriba/SuperBuild/build/cmvs/main/pmv2'
cmvs_max_images = self.params.cmvs_max_images
num_cores = 4
system.run('%s %s %s %s' %
(bin_dir, bundler_file_path, cmvs_max_images, num_cores))
log.ODM_INFO('Running OMD CMVS Cell - Finished')

53
scripts/dataset.py 100644
Wyświetl plik

@ -0,0 +1,53 @@
import os
import ecto
from opendm import context
from opendm import io
from opendm import types
from opendm import log
class ODMLoadDatasetCell(ecto.Cell):
# def declare_params(self, params):
# params.declare("args", "The application arguments.", {})
def declare_io(self, params, inputs, outputs):
inputs.declare("images_dir", "The directory to the images to load.", "")
inputs.declare("args", "The application arguments.", {})
outputs.declare("photos", "Clusters output. list of ODMPhoto's", [])
def process(self, inputs, outputs):
# check if the extension is sopported
def supported_extension(file_name):
(pathfn, ext) = os.path.splitext(file_name)
return ext.lower() in context.supported_extensions
log.ODM_INFO('Running ODM Load Dataset Cell')
# get parameters
args = self.inputs.args
images_dir = io.absolute_path_file(self.inputs.images_dir)
log.ODM_DEBUG('Loading dataset from: %s' % images_dir)
# find files in the given directory
files = io.get_files_list(images_dir)
# filter images for its extension type
# by now only 'jpg' and 'jpeg are supported
files = [f for f in files if supported_extension(f)]
photos = []
if len(files) < 1:
log.ODM_ERROR('Not enough supported images in %s' % images_dir)
else:
# create ODMPhoto list
for f in files:
path_file = io.join_paths(images_dir, f)
photos.append(types.ODMPhoto(path_file, args))
log.ODM_INFO('Found %s usable images' % len(photos))
# append photos to cell output
outputs.photos = photos
log.ODM_INFO('Running ODM Load Dataset Cell - Finished')

82
scripts/odm_app.py 100644
Wyświetl plik

@ -0,0 +1,82 @@
import ecto
from dataset import ODMLoadDatasetCell
#from resize import OMDResizeCell
from cmvs import ODMCmvsCell
from opensfm import ODMOpenSfMCell, ODMLoadReconstructionCell, ODMConvertToBundleCell
class ODMApp(ecto.BlackBox):
''' ODMApp - a class for ODM Activities
'''
def __init__(self, *args, **kwargs):
ecto.BlackBox.__init__(self, *args, **kwargs)
@staticmethod
def declare_direct_params(p):
p.declare("args", "The application arguments.", {})
p.declare("project_path", "The directory to the project.", "")
@staticmethod
def declare_cells(p):
print p.args
"""
Implement the virtual function from the base class
Only cells from which something is forwarded have to be declared
"""
cells = { 'project_path': ecto.Constant(value=p.project_path),
'args': ecto.Constant(value=p.args),
'load_dataset': ODMLoadDatasetCell(),
#'resize': OMDResizeCell()
'opensfm': ODMOpenSfMCell(use_exif_size=False,
feature_process_size=p.args['resize_to'],
feature_min_frames=p.args['min_num_features'],
processes=8,
matching_gps_neighbors=p.args['matcher_k']),
'load_reconstruction': ODMLoadReconstructionCell(),
'convert_reconstruction': ODMConvertToBundleCell(),
'cmvs': ODMCmvsCell(cmvs_max_images=p.args['cmvs_maxImages'],
pmvs_level=p.args['pmvs_level'],
pmvs_csize=p.args['pmvs_csize'],
pmvs_threshold=p.args['pmvs_threshold'],
pmvs_wsize=p.args['pmvs_wsize'],
pmvs_min_image_num=p.args['pmvs_minImageNum'])
}
return cells
def connections(self, _p):
# define initial and final tasks
# TODO: not sure how to manage that
initial_task = _p.args['start_with']
final_task = _p.args['end_with']
run_only = _p.args['run_only']
print run_only
# define the connections like you would for the plasm
connections = []
# load the dataset
connections = [ self.project_path[:] >> self.load_dataset['images_dir'],
self.args[:] >> self.load_dataset['args'] ]
# resize images
#connections += [ self.load_dataset['photos'] >> self.resize['photos'] ]
# connect loaded data with opensfm
connections += [ self.project_path[:] >> self.opensfm['project_path'],
self.load_dataset['photos'] >> self.opensfm['photos'] ]
# load reconstruction
connections += [ self.project_path[:] >> self.load_reconstruction['project_path'],
self.load_dataset['photos'] >> self.load_reconstruction['photos'] ]
# convert data to Bundler format
connections += [ self.project_path[:] >> self.convert_reconstruction['project_path'],
self.load_reconstruction['reconstructions'] >> self.convert_reconstruction['reconstructions'] ]
# run cmvs
# connections += [ self.project_path[:] >> self.cmvs['project_path'],
# self.convert_reconstruction['bundler_file_path'] >> self.cmvs['bundler_file_path'] ]
return connections

Wyświetl plik

@ -1,79 +1,130 @@
import ecto
from opendm import log from opendm import log
from opendm import dataset from opendm import io
from opendm import system from opendm import system
from opendm import context from opendm import context
def opensfm(project_path, args, photos): class ODMOpenSfMCell(ecto.Cell):
log.ODM_INFO('Running Open Structure from Motion (OpenSfm)') def declare_params(self, params):
params.declare("use_exif_size", "The application arguments.", False)
# check if we have input data params.declare("feature_process_size", "The application arguments.", False)
if len(photos) == 0: params.declare("feature_min_frames", "The application arguments.", 0)
log.ODM_WARNING('Photos array is empty - Proceed to load images') params.declare("processes", "The application arguments.", 0)
images_dir = dataset.join_paths(project_path, 'images/') params.declare("matching_gps_neighbors", "The application arguments.", 0)
photos = dataset.load_dataset(images_dir, args)
# preconditions def declare_io(self, params, inputs, outputs):
if len(photos) < 1: inputs.declare("project_path", "The directory to the images to load.", "")
log.ODM_ERROR('Not enough photos in photos array to reconstruct') inputs.declare("photos", "Clusters output. list of ODMPhoto's", [])
return False inputs.declare("reconstructions", "Clusters output. list of reconstructions", [])
# create working directory def process(self, inputs, outputs):
working_dir = dataset.join_paths(project_path, 'opensfm')
system.mkdir_p(working_dir)
try: log.ODM_INFO('Running OMD OpenSfm Cell')
# define opensfm execution command
system.run('PYTHONPATH=%s %s/bin/run_all %s' % \
(context.pyopencv_path, context.opensfm_path, images_dir))
except Exception, e:
log.ODM_ERROR(str(e))
return False
return True # get inputs
photos = self.inputs.photos
project_path = io.absolute_path_file(self.inputs.project_path)
def opensfm2(): # create file list directory
print "\n - running OpenSfM - " + now() list_path = io.join_paths(project_path, 'opensfm')
system.mkdir_p(list_path)
os.chdir(jobOptions["jobDir"]) # check if reconstruction was done before
file_list_path = io.join_paths(list_path, 'image_list.txt')
# Create bundler's list.txt if io.file_exists(file_list_path):
filesList = "" log.ODM_WARNING('Found a valid reconstruction file')
for fileObject in objects: log.ODM_INFO('Running OMD OpenSfm Cell - Finished')
if fileObject["isOk"]: return
filesList += "./" + fileObject["src"] + " 0 {:.5f}\n".format(fileObject["focalpx"])
filesList = filesList.rstrip('\n')
with open(jobOptions["step_3_filelist"], 'w') as fout: # create file list
fout.write(filesList) with open(file_list_path, 'w') as fout:
for photo in photos:
fout.write('%s\n' % photo.path_file)
# Create opensfm working folder # create config file for OpenSfM
mkdir_p("opensfm") config = [
"use_exif_size: no",
"feature_process_size: %s" % self.params.feature_process_size,
"feature_min_frames: %s" % self.params.feature_min_frames,
"processes: %s" % self.params.processes,
"matching_gps_neighbors: %s" % self.params.matching_gps_neighbors
]
# Configure OpenSfM # write config file
config = [ config_filename = io.join_paths(project_path, 'config.yaml')
"use_exif_size: no", with open(config_filename, 'w') as fout:
"feature_process_size: {}".format(jobOptions["resizeTo"]), fout.write("\n".join(config))
"feature_min_frames: {}".format(args.min_num_features),
"processes: {}".format(CORES),
]
if args.matcher_preselect:
config.append("matching_gps_neighbors: {}".format(args.matcher_k))
with open('opensfm/config.yaml', 'w') as fout: # Run OpenSfM reconstruction
fout.write("\n".join(config)) system.run('PYTHONPATH=%s %s/bin/run_all %s' %
(context.pyopencv_path, context.opensfm_path, list_path))
print 'running import_bundler' # append reconstructions to output
# Convert bundler's input to opensfm self.outputs.reconstructions = []
run('PYTHONPATH={} "{}/bin/import_bundler" opensfm --list list.txt'.format(PYOPENCV_PATH, OPENSFM_PATH))
log.ODM_INFO('Running OMD OpenSfm Cell - Finished')
# Run OpenSfM reconstruction # # Convert back to bundler's format
run('PYTHONPATH={} "{}/bin/run_all" opensfm'.format(PYOPENCV_PATH, OPENSFM_PATH)) # run('PYTHONPATH={} "{}/bin/export_bundler" opensfm'.format(PYOPENCV_PATH, OPENSFM_PATH))
#
# bundler_to_pmvs("opensfm/bundle_r000.out")
# Convert back to bundler's format
run('PYTHONPATH={} "{}/bin/export_bundler" opensfm'.format(PYOPENCV_PATH, OPENSFM_PATH))
bundler_to_pmvs("opensfm/bundle_r000.out") #########################################################################################
class ODMLoadReconstructionCell(ecto.Cell):
def declare_io(self, params, inputs, outputs):
inputs.declare("project_path", "The directory to the images to load.", "")
inputs.declare("photos", "Clusters output. list of ODMPhoto's", [])
outputs.declare("reconstructions", "Clusters output. list of reconstructions", [])
def process(self, inputs, outputs):
log.ODM_INFO('Running OMD Load Reconstruction Cell')
log.ODM_INFO('Running OMD Load Reconstruction Cell - Finished')
#########################################################################################
class ODMConvertToBundleCell(ecto.Cell):
def declare_io(self, params, inputs, outputs):
inputs.declare("project_path", "The directory to the images to load.", "")
inputs.declare("reconstructions", "The directory to the images to load.", "")
outputs.declare("bundler_file_path", "The directory to the images to load.", "")
def process(self, inputs, outputs):
log.ODM_INFO('Running OMD Convert to Bundle Cell')
# get inputs
reconstructions = self.inputs.reconstructions
project_path = io.absolute_path_file(self.inputs.project_path)
# create file list directory
list_path = io.join_paths(project_path, 'opensfm')
bundler_path_file = io.join_paths(list_path, 'bundle_r000.out')
# Run OpenSfM reconstruction
# system.run('PYTHONPATH=%s %s/bin/export_bundler %s' %
# (context.pyopencv_path, context.opensfm_path, list_path))
system.run('PYTHONPATH=%s %s/bin/export_pmvs %s' %
(context.pyopencv_path, context.opensfm_path, list_path))
# appends created file to output
self.outputs.bundler_file_path = bundler_path_file
if io.file_exists(bundler_path_file):
log.ODM_DEBUG('Bundler file created to: %s' % bundler_path_file)
else:
log.ODM_ERROR('Something went wrong when exporting to Bundler')
return
log.ODM_INFO('Running OMD Convert to Bundle Cell - Finished')
if args.end_with != "bundler":
cmvs()

Wyświetl plik

@ -1,60 +1,67 @@
import ecto
import cv2 import cv2
import pyexiv2 import pyexiv2
from opendm import log from opendm import log
from opendm import system from opendm import system
from opendm import dataset from opendm import io
def resize(project_path, args, photos): class OMDResizeCell(ecto.Cell):
def declare_params(self, params):
params.declare("args", "The application arguments.", [])
log.ODM_INFO('Preparing images - %s' % project_path) def declare_io(self, params, inputs, outputs):
inputs.declare("project_path", "Clusters output. list of tuples", [])
inputs.declare("photos", "Clusters inputs. list of ODMPhoto's", [])
outputs.declare("photos", "Clusters output. list of ODMPhoto's", [])
# check if we have input data def process(self, inputs, outputs):
if len(photos) == 0: # get parameters
log.ODM_WARNING('Photos array is empty - Proceed to load images') args = self.params.args
images_dir = dataset.join_paths(project_path, 'images') # get inputs
photos = dataset.load_dataset(images_dir, args) photos = inputs.photos
project_path = inputs.project_path
# preconditions # preconditions
if len(photos) < 1: if len(photos) < 1:
log.ODM_ERROR('Not enough photos in photos to resize') log.ODM_ERROR('Not enough photos in photos to resize')
return False else:
# create working directory
working_dir = io.join_paths(project_path, 'images_resize')
system.mkdir_p(working_dir)
# create working directory # loop over photos
working_dir = dataset.join_paths(project_path, 'images_resize') for photo in photos:
system.mkdir_p(working_dir) try:
# open and resize image with opencv
img = cv2.imread(photo.path_file)
# compute new size
max_side = max(photo.width, photo.height)
ratio = float(args['resize_to']) / float(max_side)
img_r = cv2.resize(img, None, fx=ratio, fy=ratio)
# write image with opencv
new_path_file = io.join_paths(working_dir, photo.file_name)
cv2.imwrite(new_path_file, img_r)
# read metadata with pyexiv2
old_meta = pyexiv2.ImageMetadata(photo.path_file)
new_meta = pyexiv2.ImageMetadata(new_path_file)
old_meta.read()
new_meta.read()
# copy metadata
old_meta.copy(new_meta)
new_meta.write()
# log message
log.ODM_DEBUG('Resized image %s | dimensions: %s' % \
(photo.file_name, img_r.shape))
# loop over photos # TODO(edgar): update photos array
for photo in photos: photos[photo] = datatypes.ODMPhoto(photo.path_file, args)
try:
# open and resize image with opencv
img = cv2.imread(photo.path_file)
# compute new size
max_side = max(photo.width, photo.height)
ratio = float(args['resize_to']) / float(max_side)
img_r = cv2.resize(img, None, fx=ratio, fy=ratio)
# write image with opencv
new_path_file = dataset.join_paths(working_dir, photo.file_name)
cv2.imwrite(new_path_file, img_r)
# read metadata with pyexiv2
old_meta = pyexiv2.ImageMetadata(photo.path_file)
new_meta = pyexiv2.ImageMetadata(new_path_file)
old_meta.read()
new_meta.read()
# copy metadata
old_meta.copy(new_meta)
new_meta.write()
# log message
log.ODM_DEBUG('Resized image %s | dimensions: %s' % \
(photo.file_name, img_r.shape))
# TODO(edgar): update photos array except cv2.error as e:
# something went wrong with this image
log.ODM_ERROR('Could not resize image %s' % photo.file_name)
log.ODM_ERROR('%s' % e)
except cv2.error as e: log.ODM_INFO('Resized %s images' % len(photos))
# something went wrong with this image # append photos to cell output
log.ODM_ERROR('Could not resize image %s' % photo.file_name) outputs.photos = photos
log.ODM_ERROR('%s' % e)
return False
log.ODM_INFO('Resized %s images' % len(photos))
return True