kopia lustrzana https://github.com/OpenDroneMap/ODM
Extract band indexes
rodzic
30f1570e05
commit
446b5338f3
tests
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue