Extract band indexes

Former-commit-id: 446b5338f3
pull/1161/head
Piero Toffanin 2019-12-13 10:58:37 -05:00
rodzic 494a441ef9
commit 5ec1b58a70
3 zmienionych plików z 57 dodań i 33 usunięć

Wyświetl plik

@ -17,7 +17,8 @@ class OSFMContext:
self.opensfm_project_path = opensfm_project_path
def run(self, command):
system.run('%s/bin/opensfm %s "%s"' %
# Use Python 2.x by default, otherwise OpenSfM uses Python 3.x
system.run('/usr/bin/env python2 %s/bin/opensfm %s "%s"' %
(context.opensfm_path, command, self.opensfm_project_path))
def is_reconstruction_done(self):

Wyświetl plik

@ -32,6 +32,7 @@ class ODM_Photo:
self.longitude = None
self.altitude = None
self.band_name = 'RGB'
self.band_index = 0
# parse values from metadata
self.parse_exif_values(path_file)
@ -41,9 +42,9 @@ class ODM_Photo:
def __str__(self):
return '{} | camera: {} {} | dimensions: {} x {} | lat: {} | lon: {} | alt: {} | band: {}'.format(
return '{} | camera: {} {} | dimensions: {} x {} | lat: {} | lon: {} | alt: {} | band: {} ({})'.format(
self.filename, self.camera_make, self.camera_model, self.width, self.height,
self.latitude, self.longitude, self.altitude, self.band_name)
self.latitude, self.longitude, self.altitude, self.band_name, self.band_index)
def parse_exif_values(self, _path_file):
# Disable exifread log
@ -72,13 +73,21 @@ class ODM_Photo:
f.seek(0)
xmp = self.get_xmp(f)
# Find band name (if available)
# Find band name and camera index (if available)
camera_index_tags = [
'DLS:SensorId', # Micasense
'@Camera:RigCameraIndex' # Parrot Sequoia
]
for tags in xmp:
if 'Camera:BandName' in tags:
self.band_name = str(tags['Camera:BandName']).replace(" ", "")
break
else:
for cit in camera_index_tags:
if cit in tags:
self.band_index = int(tags[cit])
self.width, self.height = get_image_size.get_image_size(_path_file)
print(self)
# From https://github.com/mapillary/OpenSfM/blob/master/opensfm/exif.py
def get_xmp(self, file):
@ -128,24 +137,36 @@ class ODM_Reconstruction(object):
Looks at the reconstruction photos and determines if this
is a single or multi-camera setup.
"""
mc = {}
band_photos = {}
band_indexes = {}
for p in self.photos:
if not p.band_name in mc:
mc[p.band_name] = []
mc[p.band_name].append(p)
if not p.band_name in band_photos:
band_photos[p.band_name] = []
if not p.band_name in band_indexes:
band_indexes[p.band_name] = p.band_index
band_photos[p.band_name].append(p)
bands_count = len(mc)
bands_count = len(band_photos)
if bands_count >= 2 and bands_count <= 8:
# Validate that all bands have the same number of images,
# otherwise this is not a multi-camera setup
img_per_band = len(mc[p.band_name])
for band in mc:
if len(mc[band]) != img_per_band:
log.ODM_ERROR("Multi-camera setup detected, but band \"%s\" (identified from \"%s\") has only %s images (instead of %s), perhaps images are missing or are corrupted. Please include all necessary files to process all bands and try again." % (band, mc[band][0].filename, len(mc[band]), img_per_band))
img_per_band = len(band_photos[p.band_name])
for band in band_photos:
if len(band_photos[band]) != img_per_band:
log.ODM_ERROR("Multi-camera setup detected, but band \"%s\" (identified from \"%s\") has only %s images (instead of %s), perhaps images are missing or are corrupted. Please include all necessary files to process all bands and try again." % (band, band_photos[band][0].filename, len(band_photos[band]), img_per_band))
raise RuntimeError("Invalid multi-camera images")
mc = []
for band_name in band_indexes:
mc.append({'name': band_name, 'photos': band_photos[band_name]})
# Sort by band index
mc.sort(key=lambda x: band_indexes[x['name']])
return mc
return None
def is_georeferenced(self):
@ -187,7 +208,7 @@ class ODM_Reconstruction(object):
log.ODM_INFO("GCP file already exist: %s" % output_gcp_file)
self.gcp = GCPFile(output_gcp_file)
self.georef = ODM_GeoRef.FromCoordsFile(output_coords_file)
self.georef = ODM_GeoRef.Froband_photosoordsFile(output_coords_file)
return self.georef
def georeference_with_gps(self, images_path, output_coords_file, rerun=False):
@ -197,7 +218,7 @@ class ODM_Reconstruction(object):
else:
log.ODM_INFO("Coordinates file already exist: %s" % output_coords_file)
self.georef = ODM_GeoRef.FromCoordsFile(output_coords_file)
self.georef = ODM_GeoRef.Froband_photosoordsFile(output_coords_file)
except:
log.ODM_WARNING('Could not generate coordinates file. An orthophoto will not be generated.')
@ -217,7 +238,7 @@ class ODM_GeoRef(object):
return ODM_GeoRef(CRS.from_proj4(projstring))
@staticmethod
def FromCoordsFile(coords_file):
def Froband_photosoordsFile(coords_file):
# check for coordinate file existence
if not io.file_exists(coords_file):
log.ODM_WARNING('Could not find file %s' % coords_file)

Wyświetl plik

@ -2,9 +2,10 @@ import unittest
from opendm import types
class ODMPhotoMock:
def __init__(self, filename, band_name):
def __init__(self, filename, band_name, band_index):
self.filename = filename
self.band_name = band_name
self.band_index = band_index
def __str__(self):
return "%s (%s)" % (self.filename, self.band_name)
@ -18,29 +19,30 @@ class TestTypes(unittest.TestCase):
def test_reconstruction(self):
# Multi camera setup
micasa_redsense_files = [('IMG_0298_1.tif', 'Red'), ('IMG_0298_2.tif', 'Green'), ('IMG_0298_3.tif', 'Blue'), ('IMG_0298_4.tif', 'NIR'), ('IMG_0298_5.tif', 'Rededge'),
('IMG_0299_1.tif', 'Red'), ('IMG_0299_2.tif', 'Green'), ('IMG_0299_3.tif', 'Blue'), ('IMG_0299_4.tif', 'NIR'), ('IMG_0299_5.tif', 'Rededge'),
('IMG_0300_1.tif', 'Red'), ('IMG_0300_2.tif', 'Green'), ('IMG_0300_3.tif', 'Blue'), ('IMG_0300_4.tif', 'NIR'), ('IMG_0300_5.tif', 'Rededge')]
photos = [ODMPhotoMock(f, b) for f, b in micasa_redsense_files]
micasa_redsense_files = [('IMG_0298_1.tif', 'Red', 1), ('IMG_0298_2.tif', 'Green', 2), ('IMG_0298_3.tif', 'Blue', 3), ('IMG_0298_4.tif', 'NIR', 4), ('IMG_0298_5.tif', 'Rededge', 5),
('IMG_0299_1.tif', 'Red', 1), ('IMG_0299_2.tif', 'Green', 2), ('IMG_0299_3.tif', 'Blue', 3), ('IMG_0299_4.tif', 'NIR', 4), ('IMG_0299_5.tif', 'Rededge', 5),
('IMG_0300_1.tif', 'Red', 1), ('IMG_0300_2.tif', 'Green', 2), ('IMG_0300_3.tif', 'Blue', 3), ('IMG_0300_4.tif', 'NIR', 4), ('IMG_0300_5.tif', 'Rededge', 5)]
photos = [ODMPhotoMock(f, b, i) for f, b, i in micasa_redsense_files]
recon = types.ODM_Reconstruction(photos)
self.assertTrue(recon.multi_camera is not None)
# Found all 5 bands
for b in ["Red", "Blue", "Green", "NIR", "Rededge"]:
self.assertTrue(b in recon.multi_camera)
self.assertTrue([p.filename for p in recon.multi_camera["Red"]] == ['IMG_0298_1.tif', 'IMG_0299_1.tif', 'IMG_0300_1.tif'])
bands = ["Red", "Green", "Blue", "NIR", "Rededge"]
for i in range(len(bands)):
self.assertEqual(bands[i], recon.multi_camera[i]['name'])
self.assertTrue([p.filename for p in recon.multi_camera[0]['photos']] == ['IMG_0298_1.tif', 'IMG_0299_1.tif', 'IMG_0300_1.tif'])
# Missing a file
micasa_redsense_files = [('IMG_0298_1.tif', 'Red'), ('IMG_0298_2.tif', 'Green'), ('IMG_0298_3.tif', 'Blue'), ('IMG_0298_4.tif', 'NIR'), ('IMG_0298_5.tif', 'Rededge'),
('IMG_0299_2.tif', 'Green'), ('IMG_0299_3.tif', 'Blue'), ('IMG_0299_4.tif', 'NIR'), ('IMG_0299_5.tif', 'Rededge'),
('IMG_0300_1.tif', 'Red'), ('IMG_0300_2.tif', 'Green'), ('IMG_0300_3.tif', 'Blue'), ('IMG_0300_4.tif', 'NIR'), ('IMG_0300_5.tif', 'Rededge')]
photos = [ODMPhotoMock(f, b) for f,b in micasa_redsense_files]
micasa_redsense_files = [('IMG_0298_1.tif', 'Red', 1), ('IMG_0298_2.tif', 'Green', 2), ('IMG_0298_3.tif', 'Blue', 3), ('IMG_0298_4.tif', 'NIR', 4), ('IMG_0298_5.tif', 'Rededge', 5),
('IMG_0299_2.tif', 'Green', 2), ('IMG_0299_3.tif', 'Blue', 3), ('IMG_0299_4.tif', 'NIR', 4), ('IMG_0299_5.tif', 'Rededge', 5),
('IMG_0300_1.tif', 'Red', 1), ('IMG_0300_2.tif', 'Green', 2), ('IMG_0300_3.tif', 'Blue', 3), ('IMG_0300_4.tif', 'NIR', 4), ('IMG_0300_5.tif', 'Rededge', 5)]
photos = [ODMPhotoMock(f, b, i) for f,b,i in micasa_redsense_files]
self.assertRaises(RuntimeError, types.ODM_Reconstruction, photos)
# Single camera
dji_files = ['DJI_0018.JPG','DJI_0019.JPG','DJI_0020.JPG','DJI_0021.JPG','DJI_0022.JPG','DJI_0023.JPG']
photos = [ODMPhotoMock(f, 'RGB') for f in dji_files]
photos = [ODMPhotoMock(f, 'RGB', 0) for f in dji_files]
recon = types.ODM_Reconstruction(photos)
self.assertTrue(recon.multi_camera is None)