OpenDroneMap-ODM/opendm/types.py

131 wiersze
5.3 KiB
Python
Czysty Zwykły widok Historia

2015-11-17 17:17:56 +00:00
import os
2015-12-02 14:24:38 +00:00
import cv2
import pyexiv2
2015-11-17 17:17:56 +00:00
import subprocess
import log
2015-11-26 12:15:02 +00:00
import io
2015-11-18 16:39:38 +00:00
import system
2015-11-17 17:17:56 +00:00
class ODMPhoto:
""" ODMPhoto - a class for ODMPhotos
"""
def __init__(self, path_file, args):
2015-11-17 17:17:56 +00:00
# general purpose
self.path_file = path_file
2015-11-27 16:48:15 +00:00
self.filename = io.extract_file_from_path_file(path_file)
2015-11-20 10:00:43 +00:00
# useful attibutes
2015-11-19 12:01:15 +00:00
self.width = None
self.height = None
2015-11-20 10:00:43 +00:00
self.ccd_width = None
self.focal_length = None
self.focal_length_px = None
2015-11-19 12:01:15 +00:00
# other attributes
2015-11-17 17:17:56 +00:00
self.camera_make = None
self.camera_model = None
2015-11-27 10:00:08 +00:00
# parse values from metadata
self.parse_pyexiv2_values(self.path_file, args)
2015-11-17 17:17:56 +00:00
# compute focal lenght into pixels
2015-11-27 16:48:15 +00:00
self.update_focal()
2015-11-17 17:17:56 +00:00
2015-11-27 16:48:15 +00:00
# print log message
2015-11-30 15:50:15 +00:00
log.ODM_DEBUG('Loaded %s | dimensions: %s x %s | focal: %s | ccd: %s' % \
2015-11-27 16:48:15 +00:00
(self.filename, self.width, self.height, self.focal_length, self.ccd_width))
2015-11-27 10:00:08 +00:00
2015-11-27 16:48:15 +00:00
def update_focal(self):
2015-11-27 10:00:08 +00:00
# compute focal length in pixels
if self.focal_length and self.ccd_width:
# take width or height as reference
2015-11-17 17:17:56 +00:00
if self.width > self.height:
2015-11-27 10:00:08 +00:00
# f(px) = w(px) * f(mm) / ccd(mm)
2015-11-17 17:17:56 +00:00
self.focal_length_px = \
self.width * (self.focal_length / self.ccd_width)
else:
2015-11-27 10:00:08 +00:00
# f(px) = h(px) * f(mm) / ccd(mm)
2015-11-17 17:17:56 +00:00
self.focal_length_px = \
self.height * (self.focal_length / self.ccd_width)
def parse_pyexiv2_values(self, _path_file, args):
# read image metadata
metadata = pyexiv2.ImageMetadata(_path_file)
metadata.read()
# loop over image tags
for key in metadata:
# try/catch tag value due to weird bug in pyexiv2
# ValueError: invalid literal for int() with base 10: ''
try:
val = metadata[key].value
# parse tag names
if key == 'Exif.Image.Make': self.camera_make = val
elif key == 'Exif.Image.Model': self.camera_model = val
elif key == 'Exif.Photo.FocalLength': self.focal_length = float(val)
except Exception, e:
pass
2015-12-02 14:24:38 +00:00
# needed to do that since sometimes metadata contains wrong data
img = cv2.imread(_path_file)
self.width = img.shape[1]
self.height = img.shape[0]
2015-12-02 14:24:38 +00:00
# force focal and ccd_width with user parameter
if args['force_focal']: self.focal_length = args['force_focal']
if args['force_ccd']: self.ccd_width = args['force_ccd']
2015-11-26 12:15:02 +00:00
# find ccd_width from file if needed
2015-11-26 12:15:02 +00:00
if self.ccd_width is None and self.camera_model is not None:
# load ccd_widths from file
ccd_widths = system.get_ccd_widths()
2015-11-26 12:15:02 +00:00
# search ccd by camera model
key = [x for x in ccd_widths.keys() if self.camera_model in x]
# convert to float if found
2015-11-27 16:48:15 +00:00
if key: self.ccd_width = float(ccd_widths[key[0]])
2015-11-27 10:00:08 +00:00
# else:
# log.ODM_ERROR('Could not find ccd_width in file')
# TODO: finish this class
class ODMReconstruction(object):
2015-12-02 14:24:38 +00:00
def __init__(self, root_path):
### root path to the project
self.root_path = io.absolute_path_file(root_path)
### modules paths
# here are defined where all modules should be located in
# order to keep track all files al directories during the
# whole reconstruction process.
self.dataset_raw = io.join_paths(self.root_path, 'images')
self.dataset_resized = io.join_paths(self.root_path, 'images_resized')
self.opensfm = io.join_paths(self.root_path, 'opensfm')
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_georeferencing = io.join_paths(self.root_path, 'odm_georeferencing')
self.odm_orthophoto = io.join_paths(self.root_path, 'odm_orthophoto')
### important files paths
# opensfm
self.opensfm_bundle = io.join_paths(self.opensfm, 'bundle_r000.out')
self.opensfm_bundle_list = io.join_paths(self.opensfm, 'list_r000.out')
self.opensfm_image_list = io.join_paths(self.opensfm, 'image_list.txt')
self.opensfm_reconstruction = io.join_paths(self.opensfm, 'reconstruction.json')
# pmvs
self.pmvs_options = io.join_paths(self.pmvs, 'recon0/pmvs_options.txt')
self.pmvs_model = io.join_paths(self.pmvs, 'models/pmvs_options.txt.ply')
# odm_meshing
self.mesh = io.join_paths(self.odm_meshing, 'odm_mesh.ply')
# odm_texturing && odm_georeferencing
self.textured_model = io.join_paths(self.odm_texturing, 'odm_textured_model_geo.ply')
self.textured_model_obj = io.join_paths(self.odm_texturing, 'odm_textured_model.obj')
self.textured_model_mtl = io.join_paths(self.odm_texturing, 'odm_textured_model.mtl')
self.textured_model_obj_geo = io.join_paths(self.odm_texturing, 'odm_textured_model_geo.obj')
self.textured_model_mtl_geo = io.join_paths(self.odm_texturing, 'odm_textured_model_geo.mtl')
# odm_orthophoto
self.orthophoto = io.join_paths(self.odm_orthophoto, 'odm_orthophoto.png')
2015-11-27 10:00:08 +00:00