Sun sensor, DLS pose

pull/1082/head
Piero Toffanin 2020-03-08 15:33:27 +00:00
rodzic 49d109199e
commit f79df2fd36
4 zmienionych plików z 88 dodań i 44 usunięć

Wyświetl plik

@ -289,8 +289,7 @@ def config():
default=False,
help='Skips dense reconstruction and 3D model generation. '
'It generates an orthophoto directly from the sparse reconstruction. '
'If you just need an orthophoto and do not need a full 3D model, turn on this option. '
'Experimental.')
'If you just need an orthophoto and do not need a full 3D model, turn on this option.')
parser.add_argument('--crop',
metavar='<positive float>',

Wyświetl plik

@ -14,7 +14,7 @@ def dn_to_radiance(photo, image):
:return numpy array with radiance image values
"""
image = image.astype(float)
image = image.astype("float32")
# Handle thermal bands (experimental)
if photo.band_name == 'LWIR':
@ -133,12 +133,12 @@ def compute_irradiance(photo, use_sun_sensor=True):
# TODO: support for calibration panels
if use_sun_sensor and photo.sun_sensor:
if use_sun_sensor and photo.get_sun_sensor():
# Estimate it
dls_orientation_vector = np.array([0,0,-1])
sun_vector_ned, sensor_vector_ned, sun_sensor_angle, \
solar_elevation, solar_azimuth = dls.compute_sun_angle([photo.latitude, photo.longitude],
(0,0,0), # TODO: add support for sun sensor pose
photo.get_dls_pose(),
photo.get_utc_time(),
dls_orientation_vector)
@ -148,8 +148,8 @@ def compute_irradiance(photo, use_sun_sensor=True):
# TODO: support for direct and scattered irradiance
direct_to_diffuse_ratio = 6.0 # Assumption
spectral_irradiance = photo.sun_sensor
direct_to_diffuse_ratio = 6.0 # Assumption, clear skies
spectral_irradiance = photo.get_sun_sensor()
percent_diffuse = 1.0 / direct_to_diffuse_ratio
sensor_irradiance = spectral_irradiance / angular_correction

Wyświetl plik

@ -46,12 +46,17 @@ class ODM_Photo:
self.bits_per_sample = None
self.vignetting_center = None
self.vignetting_polynomial = None
# self.irradiance = None
self.spectral_irradiance = None
self.horizontal_irradiance = None
self.irradiance_scale_to_si = None
self.sun_sensor = None
self.utc_time = None
# DLS
self.sun_sensor = None
self.dls_yaw = None
self.dls_pitch = None
self.dls_roll = None
# self.center_wavelength = None
# self.bandwidth = None
@ -86,7 +91,10 @@ class ODM_Photo:
self.latitude = self.dms_to_decimal(tags['GPS GPSLatitude'], tags['GPS GPSLatitudeRef'])
if 'GPS GPSLongitude' in tags and 'GPS GPSLongitudeRef' in tags:
self.longitude = self.dms_to_decimal(tags['GPS GPSLongitude'], tags['GPS GPSLongitudeRef'])
except IndexError as e:
log.ODM_WARNING("Cannot read basic EXIF tags for %s: %s" % (_path_file, e.message))
try:
if 'Image Tag 0xC61A' in tags:
self.black_level = self.list_values(tags['Image Tag 0xC61A'])
elif 'BlackLevel' in tags:
@ -125,50 +133,63 @@ class ODM_Photo:
timezone = pytz.timezone('UTC')
epoch = timezone.localize(datetime.utcfromtimestamp(0))
self.utc_time = (timezone.localize(utc_time) - epoch).total_seconds() * 1000.0
except Exception as e:
log.ODM_WARNING("Cannot read extended EXIF tags for %s: %s" % (_path_file, e.message))
except IndexError as e:
log.ODM_WARNING("Cannot read EXIF tags for %s: %s" % (_path_file, e.message))
# Extract XMP tags
f.seek(0)
xmp = self.get_xmp(f)
for tags in xmp:
band_name = self.get_xmp_tag(tags, 'Camera:BandName')
if band_name is not None:
self.band_name = band_name.replace(" ", "")
try:
band_name = self.get_xmp_tag(tags, 'Camera:BandName')
if band_name is not None:
self.band_name = band_name.replace(" ", "")
self.set_attr_from_xmp_tag('band_index', tags, [
'DLS:SensorId', # Micasense RedEdge
'@Camera:RigCameraIndex', # Parrot Sequoia, Sentera 21244-00_3.2MP-GS-0001
'Camera:RigCameraIndex', # MicaSense Altum
])
self.set_attr_from_xmp_tag('radiometric_calibration', tags, [
'MicaSense:RadiometricCalibration',
])
self.set_attr_from_xmp_tag('band_index', tags, [
'DLS:SensorId', # Micasense RedEdge
'@Camera:RigCameraIndex', # Parrot Sequoia, Sentera 21244-00_3.2MP-GS-0001
'Camera:RigCameraIndex', # MicaSense Altum
])
self.set_attr_from_xmp_tag('radiometric_calibration', tags, [
'MicaSense:RadiometricCalibration',
])
self.set_attr_from_xmp_tag('vignetting_center', tags, [
'Camera:VignettingCenter',
'Sentera:VignettingCenter',
])
self.set_attr_from_xmp_tag('vignetting_center', tags, [
'Camera:VignettingCenter',
'Sentera:VignettingCenter',
])
self.set_attr_from_xmp_tag('vignetting_polynomial', tags, [
'Camera:VignettingPolynomial',
'Sentera:VignettingPolynomial',
])
self.set_attr_from_xmp_tag('horizontal_irradiance', tags, [
'Camera:HorizontalIrradiance'
], float)
self.set_attr_from_xmp_tag('vignetting_polynomial', tags, [
'Camera:VignettingPolynomial',
'Sentera:VignettingPolynomial',
])
self.set_attr_from_xmp_tag('horizontal_irradiance', tags, [
'Camera:HorizontalIrradiance'
], float)
self.set_attr_from_xmp_tag('irradiance_scale_to_si', tags, [
'Camera:IrradianceScaleToSIUnits'
], float)
self.set_attr_from_xmp_tag('irradiance_scale_to_si', tags, [
'Camera:IrradianceScaleToSIUnits'
], float)
self.set_attr_from_xmp_tag('sun_sensor', tags, [
'Camera:SunSensor',
], float)
self.set_attr_from_xmp_tag('spectral_irradiance', tags, [
'Camera:SpectralIrradiance',
'Camera:Irradiance',
], float)
if 'DLS:Yaw' in tags:
self.set_attr_from_xmp_tag('dls_yaw', tags, ['DLS:Yaw'], float)
self.set_attr_from_xmp_tag('dls_pitch', tags, ['DLS:Pitch'], float)
self.set_attr_from_xmp_tag('dls_roll', tags, ['DLS:Roll'], float)
except Exception as e:
log.ODM_WARNING("Cannot read XMP tags for %s: %s" % (_path_file, e.message))
self.set_attr_from_xmp_tag('sun_sensor', tags, [
'Camera:SunSensor',
'Camera:Irradiance',
], float)
# self.set_attr_from_xmp_tag('center_wavelength', tags, [
# 'Camera:CentralWavelength'
@ -187,7 +208,11 @@ class ODM_Photo:
# print(self.bits_per_sample)
# print(self.vignetting_center)
# print(self.sun_sensor)
#print(self.get_vignetting_polynomial())
# print(self.get_vignetting_polynomial())
# print(self.dls_yaw)
# print(self.dls_pitch)
# print(self.fnumber)
# exit(1)
self.width, self.height = get_image_size.get_image_size(_path_file)
@ -328,3 +353,23 @@ class ODM_Photo:
scale = self.irradiance_scale_to_si
return self.horizontal_irradiance * scale
def get_sun_sensor(self):
if self.sun_sensor is not None:
# TODO: Presence of XMP:SunSensorExposureTime
# and XMP:SunSensorSensitivity might
# require additional logic. If these two tags are present,
# then sun_sensor is not in physical units?
return self.sun_sensor / 65535 # uint16 normalized (TODO: is this correct? Documentation from manufacturers is missing)
elif self.spectral_irradiance is not None:
scale = 1.0 # Assumed
if self.irradiance_scale_to_si is not None:
scale = self.irradiance_scale_to_si
return self.spectral_irradiance * scale
def get_dls_pose(self):
if self.dls_yaw is not None:
return [self.dls_yaw, self.dls_pitch, self.dls_roll]
return [0.0, 0.0, 0.0]

Wyświetl plik

@ -63,7 +63,7 @@ class ODMOpenSfMStage(types.ODM_Stage):
else:
# TODO: does this work for multi-band RGB images?
def radiometric_calibrate(shot_id, image):
photo = reconstruction.get_photo(shot_id)
return multispectral.dn_to_reflectance(photo, image, use_sun_sensor=args.radiometric_calibration=="camera+sun")