kopia lustrzana https://github.com/OpenDroneMap/ODM
rodzic
df311ffc4c
commit
1085848b4e
|
@ -1,25 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
|
||||
BIN_PATH_ABS = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
def get_ccd_widths():
|
||||
"""Return the CCD Width of the camera listed in the JSON defs file."""
|
||||
with open(BIN_PATH_ABS + '/data/ccd_defs.json') as jsonFile:
|
||||
return json.load(jsonFile)
|
||||
|
||||
try:
|
||||
ccd_defs = get_ccd_widths()
|
||||
print "CCD_DEFS compiles OK"
|
||||
print "Definitions in file: {0}".format(len(ccd_defs))
|
||||
exit_code=0
|
||||
except IOError as e:
|
||||
print "I/O error with CCD_DEFS file: {0}".format(e.strerror)
|
||||
exit_code=255
|
||||
except:
|
||||
print "Error with CCD_DEFS file: {0}".format(sys.exc_info()[1])
|
||||
exit_code=255
|
||||
|
||||
sys.exit(exit_code)
|
|
@ -91,21 +91,10 @@ def config():
|
|||
metavar='<string>',
|
||||
help='Path to config file for orb-slam')
|
||||
|
||||
parser.add_argument('--force-focal',
|
||||
metavar='<positive float>',
|
||||
type=float,
|
||||
help=('Override the focal length information for the '
|
||||
'images'))
|
||||
|
||||
parser.add_argument('--proj',
|
||||
metavar='<PROJ4 string>',
|
||||
help='Projection used to transform the model into geographic coordinates')
|
||||
|
||||
parser.add_argument('--force-ccd',
|
||||
metavar='<positive float>',
|
||||
type=float,
|
||||
help='Override the ccd width information for the images')
|
||||
|
||||
parser.add_argument('--min-num-features',
|
||||
metavar='<integer>',
|
||||
default=8000,
|
||||
|
|
|
@ -18,7 +18,6 @@ sys.path.append(pyopencv_path)
|
|||
|
||||
# define opensfm path
|
||||
opensfm_path = os.path.join(superbuild_path, "src/opensfm")
|
||||
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")
|
||||
|
|
|
@ -0,0 +1,440 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import print_function
|
||||
from __future__ import absolute_import
|
||||
"""
|
||||
|
||||
get_image_size.py
|
||||
====================
|
||||
|
||||
:Name: get_image_size
|
||||
:Purpose: extract image dimensions given a file path
|
||||
|
||||
:Author: Paulo Scardine (based on code from Emmanuel VAÏSSE)
|
||||
|
||||
:Created: 26/09/2013
|
||||
:Copyright: (c) Paulo Scardine 2013
|
||||
:Licence: MIT
|
||||
|
||||
"""
|
||||
import collections
|
||||
import json
|
||||
import os
|
||||
import io
|
||||
import struct
|
||||
|
||||
FILE_UNKNOWN = "Sorry, don't know how to get size for this file."
|
||||
|
||||
|
||||
class UnknownImageFormat(Exception):
|
||||
pass
|
||||
|
||||
|
||||
types = collections.OrderedDict()
|
||||
BMP = types['BMP'] = 'BMP'
|
||||
GIF = types['GIF'] = 'GIF'
|
||||
ICO = types['ICO'] = 'ICO'
|
||||
JPEG = types['JPEG'] = 'JPEG'
|
||||
PNG = types['PNG'] = 'PNG'
|
||||
TIFF = types['TIFF'] = 'TIFF'
|
||||
|
||||
image_fields = ['path', 'type', 'file_size', 'width', 'height']
|
||||
|
||||
|
||||
class Image(collections.namedtuple('Image', image_fields)):
|
||||
|
||||
def to_str_row(self):
|
||||
return ("%d\t%d\t%d\t%s\t%s" % (
|
||||
self.width,
|
||||
self.height,
|
||||
self.file_size,
|
||||
self.type,
|
||||
self.path.replace('\t', '\\t'),
|
||||
))
|
||||
|
||||
def to_str_row_verbose(self):
|
||||
return ("%d\t%d\t%d\t%s\t%s\t##%s" % (
|
||||
self.width,
|
||||
self.height,
|
||||
self.file_size,
|
||||
self.type,
|
||||
self.path.replace('\t', '\\t'),
|
||||
self))
|
||||
|
||||
def to_str_json(self, indent=None):
|
||||
return json.dumps(self._asdict(), indent=indent)
|
||||
|
||||
|
||||
def get_image_size(file_path):
|
||||
"""
|
||||
Return (width, height) for a given img file content - no external
|
||||
dependencies except the os and struct builtin modules
|
||||
"""
|
||||
img = get_image_metadata(file_path)
|
||||
return (img.width, img.height)
|
||||
|
||||
|
||||
def get_image_size_from_bytesio(input, size):
|
||||
"""
|
||||
Return (width, height) for a given img file content - no external
|
||||
dependencies except the os and struct builtin modules
|
||||
|
||||
Args:
|
||||
input (io.IOBase): io object support read & seek
|
||||
size (int): size of buffer in byte
|
||||
"""
|
||||
img = get_image_metadata_from_bytesio(input, size)
|
||||
return (img.width, img.height)
|
||||
|
||||
|
||||
def get_image_metadata(file_path):
|
||||
"""
|
||||
Return an `Image` object for a given img file content - no external
|
||||
dependencies except the os and struct builtin modules
|
||||
|
||||
Args:
|
||||
file_path (str): path to an image file
|
||||
|
||||
Returns:
|
||||
Image: (path, type, file_size, width, height)
|
||||
"""
|
||||
size = os.path.getsize(file_path)
|
||||
|
||||
# be explicit with open arguments - we need binary mode
|
||||
with io.open(file_path, "rb") as input:
|
||||
return get_image_metadata_from_bytesio(input, size, file_path)
|
||||
|
||||
|
||||
def get_image_metadata_from_bytesio(input, size, file_path=None):
|
||||
"""
|
||||
Return an `Image` object for a given img file content - no external
|
||||
dependencies except the os and struct builtin modules
|
||||
|
||||
Args:
|
||||
input (io.IOBase): io object support read & seek
|
||||
size (int): size of buffer in byte
|
||||
file_path (str): path to an image file
|
||||
|
||||
Returns:
|
||||
Image: (path, type, file_size, width, height)
|
||||
"""
|
||||
height = -1
|
||||
width = -1
|
||||
data = input.read(26)
|
||||
msg = " raised while trying to decode as JPEG."
|
||||
|
||||
if (size >= 10) and data[:6] in (b'GIF87a', b'GIF89a'):
|
||||
# GIFs
|
||||
imgtype = GIF
|
||||
w, h = struct.unpack("<HH", data[6:10])
|
||||
width = int(w)
|
||||
height = int(h)
|
||||
elif ((size >= 24) and data.startswith(b'\211PNG\r\n\032\n')
|
||||
and (data[12:16] == b'IHDR')):
|
||||
# PNGs
|
||||
imgtype = PNG
|
||||
w, h = struct.unpack(">LL", data[16:24])
|
||||
width = int(w)
|
||||
height = int(h)
|
||||
elif (size >= 16) and data.startswith(b'\211PNG\r\n\032\n'):
|
||||
# older PNGs
|
||||
imgtype = PNG
|
||||
w, h = struct.unpack(">LL", data[8:16])
|
||||
width = int(w)
|
||||
height = int(h)
|
||||
elif (size >= 2) and data.startswith(b'\377\330'):
|
||||
# JPEG
|
||||
imgtype = JPEG
|
||||
input.seek(0)
|
||||
input.read(2)
|
||||
b = input.read(1)
|
||||
try:
|
||||
while (b and ord(b) != 0xDA):
|
||||
while (ord(b) != 0xFF):
|
||||
b = input.read(1)
|
||||
while (ord(b) == 0xFF):
|
||||
b = input.read(1)
|
||||
if (ord(b) >= 0xC0 and ord(b) <= 0xC3):
|
||||
input.read(3)
|
||||
h, w = struct.unpack(">HH", input.read(4))
|
||||
break
|
||||
else:
|
||||
input.read(
|
||||
int(struct.unpack(">H", input.read(2))[0]) - 2)
|
||||
b = input.read(1)
|
||||
width = int(w)
|
||||
height = int(h)
|
||||
except struct.error:
|
||||
raise UnknownImageFormat("StructError" + msg)
|
||||
except ValueError:
|
||||
raise UnknownImageFormat("ValueError" + msg)
|
||||
except Exception as e:
|
||||
raise UnknownImageFormat(e.__class__.__name__ + msg)
|
||||
elif (size >= 26) and data.startswith(b'BM'):
|
||||
# BMP
|
||||
imgtype = 'BMP'
|
||||
headersize = struct.unpack("<I", data[14:18])[0]
|
||||
if headersize == 12:
|
||||
w, h = struct.unpack("<HH", data[18:22])
|
||||
width = int(w)
|
||||
height = int(h)
|
||||
elif headersize >= 40:
|
||||
w, h = struct.unpack("<ii", data[18:26])
|
||||
width = int(w)
|
||||
# as h is negative when stored upside down
|
||||
height = abs(int(h))
|
||||
else:
|
||||
raise UnknownImageFormat(
|
||||
"Unkown DIB header size:" +
|
||||
str(headersize))
|
||||
elif (size >= 8) and data[:4] in (b"II\052\000", b"MM\000\052"):
|
||||
# Standard TIFF, big- or little-endian
|
||||
# BigTIFF and other different but TIFF-like formats are not
|
||||
# supported currently
|
||||
imgtype = TIFF
|
||||
byteOrder = data[:2]
|
||||
boChar = ">" if byteOrder == "MM" else "<"
|
||||
# maps TIFF type id to size (in bytes)
|
||||
# and python format char for struct
|
||||
tiffTypes = {
|
||||
1: (1, boChar + "B"), # BYTE
|
||||
2: (1, boChar + "c"), # ASCII
|
||||
3: (2, boChar + "H"), # SHORT
|
||||
4: (4, boChar + "L"), # LONG
|
||||
5: (8, boChar + "LL"), # RATIONAL
|
||||
6: (1, boChar + "b"), # SBYTE
|
||||
7: (1, boChar + "c"), # UNDEFINED
|
||||
8: (2, boChar + "h"), # SSHORT
|
||||
9: (4, boChar + "l"), # SLONG
|
||||
10: (8, boChar + "ll"), # SRATIONAL
|
||||
11: (4, boChar + "f"), # FLOAT
|
||||
12: (8, boChar + "d") # DOUBLE
|
||||
}
|
||||
ifdOffset = struct.unpack(boChar + "L", data[4:8])[0]
|
||||
try:
|
||||
countSize = 2
|
||||
input.seek(ifdOffset)
|
||||
ec = input.read(countSize)
|
||||
ifdEntryCount = struct.unpack(boChar + "H", ec)[0]
|
||||
# 2 bytes: TagId + 2 bytes: type + 4 bytes: count of values + 4
|
||||
# bytes: value offset
|
||||
ifdEntrySize = 12
|
||||
for i in range(ifdEntryCount):
|
||||
entryOffset = ifdOffset + countSize + i * ifdEntrySize
|
||||
input.seek(entryOffset)
|
||||
tag = input.read(2)
|
||||
tag = struct.unpack(boChar + "H", tag)[0]
|
||||
if(tag == 256 or tag == 257):
|
||||
# if type indicates that value fits into 4 bytes, value
|
||||
# offset is not an offset but value itself
|
||||
type = input.read(2)
|
||||
type = struct.unpack(boChar + "H", type)[0]
|
||||
if type not in tiffTypes:
|
||||
raise UnknownImageFormat(
|
||||
"Unkown TIFF field type:" +
|
||||
str(type))
|
||||
typeSize = tiffTypes[type][0]
|
||||
typeChar = tiffTypes[type][1]
|
||||
input.seek(entryOffset + 8)
|
||||
value = input.read(typeSize)
|
||||
value = int(struct.unpack(typeChar, value)[0])
|
||||
if tag == 256:
|
||||
width = value
|
||||
else:
|
||||
height = value
|
||||
if width > -1 and height > -1:
|
||||
break
|
||||
except Exception as e:
|
||||
raise UnknownImageFormat(str(e))
|
||||
elif size >= 2:
|
||||
# see http://en.wikipedia.org/wiki/ICO_(file_format)
|
||||
imgtype = 'ICO'
|
||||
input.seek(0)
|
||||
reserved = input.read(2)
|
||||
if 0 != struct.unpack("<H", reserved)[0]:
|
||||
raise UnknownImageFormat(FILE_UNKNOWN)
|
||||
format = input.read(2)
|
||||
assert 1 == struct.unpack("<H", format)[0]
|
||||
num = input.read(2)
|
||||
num = struct.unpack("<H", num)[0]
|
||||
if num > 1:
|
||||
import warnings
|
||||
warnings.warn("ICO File contains more than one image")
|
||||
# http://msdn.microsoft.com/en-us/library/ms997538.aspx
|
||||
w = input.read(1)
|
||||
h = input.read(1)
|
||||
width = ord(w)
|
||||
height = ord(h)
|
||||
else:
|
||||
raise UnknownImageFormat(FILE_UNKNOWN)
|
||||
|
||||
return Image(path=file_path,
|
||||
type=imgtype,
|
||||
file_size=size,
|
||||
width=width,
|
||||
height=height)
|
||||
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class Test_get_image_size(unittest.TestCase):
|
||||
data = [{
|
||||
'path': 'lookmanodeps.png',
|
||||
'width': 251,
|
||||
'height': 208,
|
||||
'file_size': 22228,
|
||||
'type': 'PNG'}]
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def test_get_image_size_from_bytesio(self):
|
||||
img = self.data[0]
|
||||
p = img['path']
|
||||
with io.open(p, 'rb') as fp:
|
||||
b = fp.read()
|
||||
fp = io.BytesIO(b)
|
||||
sz = len(b)
|
||||
output = get_image_size_from_bytesio(fp, sz)
|
||||
self.assertTrue(output)
|
||||
self.assertEqual(output,
|
||||
(img['width'],
|
||||
img['height']))
|
||||
|
||||
def test_get_image_metadata_from_bytesio(self):
|
||||
img = self.data[0]
|
||||
p = img['path']
|
||||
with io.open(p, 'rb') as fp:
|
||||
b = fp.read()
|
||||
fp = io.BytesIO(b)
|
||||
sz = len(b)
|
||||
output = get_image_metadata_from_bytesio(fp, sz)
|
||||
self.assertTrue(output)
|
||||
for field in image_fields:
|
||||
self.assertEqual(getattr(output, field), None if field == 'path' else img[field])
|
||||
|
||||
def test_get_image_metadata(self):
|
||||
img = self.data[0]
|
||||
output = get_image_metadata(img['path'])
|
||||
self.assertTrue(output)
|
||||
for field in image_fields:
|
||||
self.assertEqual(getattr(output, field), img[field])
|
||||
|
||||
def test_get_image_metadata__ENOENT_OSError(self):
|
||||
with self.assertRaises(OSError):
|
||||
get_image_metadata('THIS_DOES_NOT_EXIST')
|
||||
|
||||
def test_get_image_metadata__not_an_image_UnknownImageFormat(self):
|
||||
with self.assertRaises(UnknownImageFormat):
|
||||
get_image_metadata('README.rst')
|
||||
|
||||
def test_get_image_size(self):
|
||||
img = self.data[0]
|
||||
output = get_image_size(img['path'])
|
||||
self.assertTrue(output)
|
||||
self.assertEqual(output,
|
||||
(img['width'],
|
||||
img['height']))
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
"""
|
||||
Print image metadata fields for the given file path.
|
||||
|
||||
Keyword Arguments:
|
||||
argv (list): commandline arguments (e.g. sys.argv[1:])
|
||||
Returns:
|
||||
int: zero for OK
|
||||
"""
|
||||
import logging
|
||||
import optparse
|
||||
import sys
|
||||
|
||||
prs = optparse.OptionParser(
|
||||
usage="%prog [-v|--verbose] [--json|--json-indent] <path0> [<pathN>]",
|
||||
description="Print metadata for the given image paths "
|
||||
"(without image library bindings).")
|
||||
|
||||
prs.add_option('--json',
|
||||
dest='json',
|
||||
action='store_true')
|
||||
prs.add_option('--json-indent',
|
||||
dest='json_indent',
|
||||
action='store_true')
|
||||
|
||||
prs.add_option('-v', '--verbose',
|
||||
dest='verbose',
|
||||
action='store_true',)
|
||||
prs.add_option('-q', '--quiet',
|
||||
dest='quiet',
|
||||
action='store_true',)
|
||||
prs.add_option('-t', '--test',
|
||||
dest='run_tests',
|
||||
action='store_true',)
|
||||
|
||||
argv = list(argv) if argv is not None else sys.argv[1:]
|
||||
(opts, args) = prs.parse_args(args=argv)
|
||||
loglevel = logging.INFO
|
||||
if opts.verbose:
|
||||
loglevel = logging.DEBUG
|
||||
elif opts.quiet:
|
||||
loglevel = logging.ERROR
|
||||
logging.basicConfig(level=loglevel)
|
||||
log = logging.getLogger()
|
||||
log.debug('argv: %r', argv)
|
||||
log.debug('opts: %r', opts)
|
||||
log.debug('args: %r', args)
|
||||
|
||||
if opts.run_tests:
|
||||
import sys
|
||||
sys.argv = [sys.argv[0]] + args
|
||||
import unittest
|
||||
return unittest.main()
|
||||
|
||||
output_func = Image.to_str_row
|
||||
if opts.json_indent:
|
||||
import functools
|
||||
output_func = functools.partial(Image.to_str_json, indent=2)
|
||||
elif opts.json:
|
||||
output_func = Image.to_str_json
|
||||
elif opts.verbose:
|
||||
output_func = Image.to_str_row_verbose
|
||||
|
||||
EX_OK = 0
|
||||
EX_NOT_OK = 2
|
||||
|
||||
if len(args) < 1:
|
||||
prs.print_help()
|
||||
print('')
|
||||
prs.error("You must specify one or more paths to image files")
|
||||
|
||||
errors = []
|
||||
for path_arg in args:
|
||||
try:
|
||||
img = get_image_metadata(path_arg)
|
||||
print(output_func(img))
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except OSError as e:
|
||||
log.error((path_arg, e))
|
||||
errors.append((path_arg, e))
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
errors.append((path_arg, e))
|
||||
pass
|
||||
if len(errors):
|
||||
import pprint
|
||||
print("ERRORS", file=sys.stderr)
|
||||
print("======", file=sys.stderr)
|
||||
print(pprint.pformat(errors, indent=2), file=sys.stderr)
|
||||
return EX_NOT_OK
|
||||
return EX_OK
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
sys.exit(main(argv=sys.argv[1:]))
|
|
@ -3,6 +3,7 @@ import exifread
|
|||
import re
|
||||
from fractions import Fraction
|
||||
from opensfm.exif import sensor_string
|
||||
from opendm import get_image_size
|
||||
from pyproj import Proj
|
||||
|
||||
import log
|
||||
|
@ -15,15 +16,11 @@ class ODM_Photo:
|
|||
""" ODMPhoto - a class for ODMPhotos
|
||||
"""
|
||||
|
||||
def __init__(self, path_file, force_focal, force_ccd):
|
||||
def __init__(self, path_file):
|
||||
# general purpose
|
||||
self.filename = io.extract_file_from_path_file(path_file)
|
||||
# useful attibutes
|
||||
self.width = None
|
||||
self.height = None
|
||||
self.ccd_width = None
|
||||
self.focal_length = None
|
||||
self.focal_length_px = None
|
||||
# other attributes
|
||||
self.camera_make = ''
|
||||
self.camera_model = ''
|
||||
|
@ -32,33 +29,17 @@ class ODM_Photo:
|
|||
self.longitude = None
|
||||
self.altitude = None
|
||||
# parse values from metadata
|
||||
self.parse_exif_values(path_file, force_focal, force_ccd)
|
||||
# compute focal length into pixels
|
||||
self.update_focal()
|
||||
self.parse_exif_values(path_file)
|
||||
|
||||
# print log message
|
||||
log.ODM_DEBUG('Loaded {}'.format(self))
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return '{} | camera: {} | dimensions: {} x {} | focal: {} | ccd: {} | lat: {} | lon: {} | alt: {}'.format(
|
||||
self.filename, self.make_model, self.width, self.height, self.focal_length,
|
||||
self.ccd_width, self.latitude, self.longitude, self.altitude)
|
||||
return '{} | camera: {} | dimensions: {} x {} | lat: {} | lon: {} | alt: {}'.format(
|
||||
self.filename, self.make_model, self.width, self.height, self.latitude, self.longitude, self.altitude)
|
||||
|
||||
def update_focal(self):
|
||||
# compute focal length in pixels
|
||||
if self.focal_length and self.ccd_width:
|
||||
# take width or height as reference
|
||||
if self.width > self.height:
|
||||
# f(px) = w(px) * f(mm) / ccd(mm)
|
||||
self.focal_length_px = \
|
||||
self.width * (self.focal_length / self.ccd_width)
|
||||
else:
|
||||
# f(px) = h(px) * f(mm) / ccd(mm)
|
||||
self.focal_length_px = \
|
||||
self.height * (self.focal_length / self.ccd_width)
|
||||
|
||||
def parse_exif_values(self, _path_file, _force_focal, _force_ccd):
|
||||
def parse_exif_values(self, _path_file):
|
||||
# Disable exifread log
|
||||
logging.getLogger('exifread').setLevel(logging.CRITICAL)
|
||||
|
||||
|
@ -70,8 +51,6 @@ class ODM_Photo:
|
|||
self.camera_make = tags['Image Make'].values.encode('utf8')
|
||||
if 'Image Model' in tags:
|
||||
self.camera_model = tags['Image Model'].values.encode('utf8')
|
||||
if 'EXIF FocalLength' in tags:
|
||||
self.focal_length = self.float_values(tags['EXIF FocalLength'])[0]
|
||||
if 'GPS GPSAltitude' in tags:
|
||||
self.altitude = self.float_values(tags['GPS GPSAltitude'])[0]
|
||||
if 'GPS GPSAltitudeRef' in tags and self.int_values(tags['GPS GPSAltitudeRef'])[0] > 0:
|
||||
|
@ -87,28 +66,13 @@ class ODM_Photo:
|
|||
self.make_model = sensor_string(self.camera_make, self.camera_model)
|
||||
|
||||
# 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]
|
||||
|
||||
# force focal and ccd_width with user parameter
|
||||
if _force_focal:
|
||||
self.focal_length = _force_focal
|
||||
if _force_ccd:
|
||||
self.ccd_width = _force_ccd
|
||||
|
||||
# find ccd_width from file if needed
|
||||
if self.ccd_width is None and self.camera_model is not None:
|
||||
# load ccd_widths from file
|
||||
ccd_widths = system.get_ccd_widths()
|
||||
# search ccd by camera model
|
||||
key = [x for x in ccd_widths.keys() if self.make_model in x]
|
||||
# convert to float if found
|
||||
if key:
|
||||
self.ccd_width = float(ccd_widths[key[0]])
|
||||
else:
|
||||
log.ODM_WARNING('Could not find ccd_width in file. Use --force-ccd or edit the sensor_data.json '
|
||||
'file to manually input ccd width')
|
||||
try:
|
||||
self.width, self.height = get_image_size.get_image_size(_path_file)
|
||||
except get_image_size.UnknownImageFormat:
|
||||
# Fallback to slower cv2
|
||||
img = cv2.imread(_path_file)
|
||||
self.width = img.shape[1]
|
||||
self.height = img.shape[0]
|
||||
|
||||
def dms_to_decimal(self, dms, sign):
|
||||
"""Converts dms coords to decimal degrees"""
|
||||
|
@ -126,7 +90,7 @@ class ODM_Photo:
|
|||
def int_values(self, tag):
|
||||
return map(int, tag.values)
|
||||
|
||||
# TODO: finish this class
|
||||
|
||||
class ODM_Reconstruction(object):
|
||||
"""docstring for ODMReconstruction"""
|
||||
|
||||
|
@ -197,15 +161,6 @@ class ODM_Reconstruction(object):
|
|||
log.ODM_EXCEPTION('Could not set projection. Please use a proj4 string')
|
||||
|
||||
|
||||
class ODM_GCPoint(object):
|
||||
"""docstring for ODMPoint"""
|
||||
|
||||
def __init__(self, x, y, z):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.z = z
|
||||
|
||||
|
||||
class ODM_GeoRef(object):
|
||||
"""docstring for ODMUtmZone"""
|
||||
|
||||
|
@ -258,24 +213,6 @@ class ODM_GeoRef(object):
|
|||
self.utm_east_offset = float(offsets[0])
|
||||
self.utm_north_offset = float(offsets[1])
|
||||
|
||||
def create_gcps(self, _file):
|
||||
if not io.file_exists(_file):
|
||||
log.ODM_ERROR('Could not find file %s' % _file)
|
||||
return
|
||||
|
||||
with open(_file) as f:
|
||||
# parse coordinates
|
||||
lines = f.readlines()[2:]
|
||||
for l in lines:
|
||||
xyz = l.split(' ')
|
||||
if len(xyz) == 3:
|
||||
x, y, z = xyz[:3]
|
||||
elif len(xyz) == 2:
|
||||
x, y = xyz[:2]
|
||||
z = 0
|
||||
self.gcps.append(ODM_GCPoint(float(x), float(y), float(z)))
|
||||
# Write to json file
|
||||
|
||||
def parse_transformation_matrix(self, _file):
|
||||
if not io.file_exists(_file):
|
||||
log.ODM_ERROR('Could not find file %s' % _file)
|
||||
|
|
|
@ -9,12 +9,6 @@ from opendm import log
|
|||
from opendm import system
|
||||
from shutil import copyfile
|
||||
|
||||
|
||||
def make_odm_photo(force_focal, force_ccd, path_file):
|
||||
return types.ODM_Photo(path_file,
|
||||
force_focal,
|
||||
force_ccd)
|
||||
|
||||
def save_images_database(photos, database_file):
|
||||
with open(database_file, 'w') as f:
|
||||
f.write(json.dumps(map(lambda p: p.__dict__, photos)))
|
||||
|
@ -45,10 +39,6 @@ def load_images_database(database_file):
|
|||
class ODMLoadDatasetCell(ecto.Cell):
|
||||
|
||||
def declare_params(self, params):
|
||||
params.declare("force_focal", 'Override the focal length information for the '
|
||||
'images', None)
|
||||
params.declare("force_ccd", 'Override the ccd width information for the '
|
||||
'images', None)
|
||||
params.declare("verbose", 'indicate verbosity', False)
|
||||
params.declare("proj", 'Geographic projection', None)
|
||||
|
||||
|
@ -106,8 +96,8 @@ class ODMLoadDatasetCell(ecto.Cell):
|
|||
|
||||
photos = []
|
||||
with open(tree.dataset_list, 'w') as dataset_list:
|
||||
for files in path_files:
|
||||
photos += [make_odm_photo(self.params.force_focal, self.params.force_ccd, files)]
|
||||
for f in path_files:
|
||||
photos += [types.ODM_Photo(f)]
|
||||
dataset_list.write(photos[-1].filename + '\n')
|
||||
|
||||
# Save image database for faster restart
|
||||
|
|
|
@ -36,9 +36,7 @@ class ODMApp(ecto.BlackBox):
|
|||
Only cells from which something is forwarded have to be declared
|
||||
"""
|
||||
cells = {'args': ecto.Constant(value=p.args),
|
||||
'dataset': ODMLoadDatasetCell(force_focal=p.args.force_focal,
|
||||
force_ccd=p.args.force_ccd,
|
||||
verbose=p.args.verbose,
|
||||
'dataset': ODMLoadDatasetCell(verbose=p.args.verbose,
|
||||
proj=p.args.proj),
|
||||
'opensfm': ODMOpenSfMCell(use_exif_size=False,
|
||||
feature_process_size=p.args.resize_to,
|
||||
|
|
|
@ -33,7 +33,7 @@ def setup_module():
|
|||
|
||||
def teardown_module():
|
||||
# Delete generated test directories
|
||||
dirnames = ['images_resize', 'opensfm', 'pmvs', 'odm_meshing',
|
||||
dirnames = ['opensfm', 'odm_meshing',
|
||||
'odm_texturing', 'odm_georeferencing', 'odm_orthophoto']
|
||||
for n in dirnames:
|
||||
rmpath = os.path.join(context.tests_data_path, n)
|
||||
|
@ -41,30 +41,6 @@ def teardown_module():
|
|||
shutil.rmtree(rmpath)
|
||||
|
||||
|
||||
class TestResize(unittest.TestCase):
|
||||
"""
|
||||
Tests the resize function
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
# rerun resize cell and set params
|
||||
options.rerun = 'resize'
|
||||
options.resize_to = 1600
|
||||
# rebuild app
|
||||
self.app, self.plasm = appSetup(options)
|
||||
run_plasm(options, self.plasm)
|
||||
|
||||
|
||||
def test_resize(self):
|
||||
# assert each image is sized to the option.resize_to
|
||||
self.assertEquals(max(self.app.resize.outputs.photos[0].height, self.app.resize.outputs.photos[0].width),
|
||||
options.resize_to)
|
||||
|
||||
def test_all_resized(self):
|
||||
# assert the number of images in images == number of images in resize
|
||||
self.assertEquals(len(self.app.resize.outputs.photos), len(self.app.dataset.outputs.photos))
|
||||
|
||||
|
||||
class TestOpenSfM(unittest.TestCase):
|
||||
"""
|
||||
Tests the OpenSfM module
|
||||
|
@ -79,28 +55,6 @@ class TestOpenSfM(unittest.TestCase):
|
|||
self.assertTrue(os.path.isfile(self.app.opensfm.inputs.tree.opensfm_reconstruction))
|
||||
|
||||
|
||||
class TestCMVS(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
options.rerun = 'cmvs'
|
||||
self.app, self.plasm = appSetup(options)
|
||||
run_plasm(options, self.plasm)
|
||||
|
||||
def test_cmvs(self):
|
||||
self.assertTrue(os.path.isfile(self.app.cmvs.inputs.tree.pmvs_bundle))
|
||||
|
||||
|
||||
class TestPMVS(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
options.rerun = 'pmvs'
|
||||
self.app, self.plasm = appSetup(options)
|
||||
run_plasm(options, self.plasm)
|
||||
|
||||
def test_pmvs(self):
|
||||
self.assertTrue(os.path.isfile(self.app.pmvs.inputs.tree.pmvs_model))
|
||||
|
||||
|
||||
class TestMeshing(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
|
Ładowanie…
Reference in New Issue