kopia lustrzana https://github.com/OpenDroneMap/ODM
Sun sensor, DLS pose
rodzic
49d109199e
commit
f79df2fd36
|
@ -289,8 +289,7 @@ def config():
|
||||||
default=False,
|
default=False,
|
||||||
help='Skips dense reconstruction and 3D model generation. '
|
help='Skips dense reconstruction and 3D model generation. '
|
||||||
'It generates an orthophoto directly from the sparse reconstruction. '
|
'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. '
|
'If you just need an orthophoto and do not need a full 3D model, turn on this option.')
|
||||||
'Experimental.')
|
|
||||||
|
|
||||||
parser.add_argument('--crop',
|
parser.add_argument('--crop',
|
||||||
metavar='<positive float>',
|
metavar='<positive float>',
|
||||||
|
|
|
@ -14,7 +14,7 @@ def dn_to_radiance(photo, image):
|
||||||
:return numpy array with radiance image values
|
:return numpy array with radiance image values
|
||||||
"""
|
"""
|
||||||
|
|
||||||
image = image.astype(float)
|
image = image.astype("float32")
|
||||||
|
|
||||||
# Handle thermal bands (experimental)
|
# Handle thermal bands (experimental)
|
||||||
if photo.band_name == 'LWIR':
|
if photo.band_name == 'LWIR':
|
||||||
|
@ -133,12 +133,12 @@ def compute_irradiance(photo, use_sun_sensor=True):
|
||||||
|
|
||||||
# TODO: support for calibration panels
|
# TODO: support for calibration panels
|
||||||
|
|
||||||
if use_sun_sensor and photo.sun_sensor:
|
if use_sun_sensor and photo.get_sun_sensor():
|
||||||
# Estimate it
|
# Estimate it
|
||||||
dls_orientation_vector = np.array([0,0,-1])
|
dls_orientation_vector = np.array([0,0,-1])
|
||||||
sun_vector_ned, sensor_vector_ned, sun_sensor_angle, \
|
sun_vector_ned, sensor_vector_ned, sun_sensor_angle, \
|
||||||
solar_elevation, solar_azimuth = dls.compute_sun_angle([photo.latitude, photo.longitude],
|
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(),
|
photo.get_utc_time(),
|
||||||
dls_orientation_vector)
|
dls_orientation_vector)
|
||||||
|
|
||||||
|
@ -148,8 +148,8 @@ def compute_irradiance(photo, use_sun_sensor=True):
|
||||||
|
|
||||||
# TODO: support for direct and scattered irradiance
|
# TODO: support for direct and scattered irradiance
|
||||||
|
|
||||||
direct_to_diffuse_ratio = 6.0 # Assumption
|
direct_to_diffuse_ratio = 6.0 # Assumption, clear skies
|
||||||
spectral_irradiance = photo.sun_sensor
|
spectral_irradiance = photo.get_sun_sensor()
|
||||||
|
|
||||||
percent_diffuse = 1.0 / direct_to_diffuse_ratio
|
percent_diffuse = 1.0 / direct_to_diffuse_ratio
|
||||||
sensor_irradiance = spectral_irradiance / angular_correction
|
sensor_irradiance = spectral_irradiance / angular_correction
|
||||||
|
|
|
@ -46,12 +46,17 @@ class ODM_Photo:
|
||||||
self.bits_per_sample = None
|
self.bits_per_sample = None
|
||||||
self.vignetting_center = None
|
self.vignetting_center = None
|
||||||
self.vignetting_polynomial = None
|
self.vignetting_polynomial = None
|
||||||
# self.irradiance = None
|
self.spectral_irradiance = None
|
||||||
self.horizontal_irradiance = None
|
self.horizontal_irradiance = None
|
||||||
self.irradiance_scale_to_si = None
|
self.irradiance_scale_to_si = None
|
||||||
self.sun_sensor = None
|
|
||||||
self.utc_time = 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.center_wavelength = None
|
||||||
# self.bandwidth = None
|
# self.bandwidth = None
|
||||||
|
|
||||||
|
@ -86,7 +91,10 @@ class ODM_Photo:
|
||||||
self.latitude = self.dms_to_decimal(tags['GPS GPSLatitude'], tags['GPS GPSLatitudeRef'])
|
self.latitude = self.dms_to_decimal(tags['GPS GPSLatitude'], tags['GPS GPSLatitudeRef'])
|
||||||
if 'GPS GPSLongitude' in tags and 'GPS GPSLongitudeRef' in tags:
|
if 'GPS GPSLongitude' in tags and 'GPS GPSLongitudeRef' in tags:
|
||||||
self.longitude = self.dms_to_decimal(tags['GPS GPSLongitude'], tags['GPS GPSLongitudeRef'])
|
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:
|
if 'Image Tag 0xC61A' in tags:
|
||||||
self.black_level = self.list_values(tags['Image Tag 0xC61A'])
|
self.black_level = self.list_values(tags['Image Tag 0xC61A'])
|
||||||
elif 'BlackLevel' in tags:
|
elif 'BlackLevel' in tags:
|
||||||
|
@ -125,15 +133,16 @@ class ODM_Photo:
|
||||||
timezone = pytz.timezone('UTC')
|
timezone = pytz.timezone('UTC')
|
||||||
epoch = timezone.localize(datetime.utcfromtimestamp(0))
|
epoch = timezone.localize(datetime.utcfromtimestamp(0))
|
||||||
self.utc_time = (timezone.localize(utc_time) - epoch).total_seconds() * 1000.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
|
# Extract XMP tags
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
xmp = self.get_xmp(f)
|
xmp = self.get_xmp(f)
|
||||||
|
|
||||||
for tags in xmp:
|
for tags in xmp:
|
||||||
|
try:
|
||||||
band_name = self.get_xmp_tag(tags, 'Camera:BandName')
|
band_name = self.get_xmp_tag(tags, 'Camera:BandName')
|
||||||
if band_name is not None:
|
if band_name is not None:
|
||||||
self.band_name = band_name.replace(" ", "")
|
self.band_name = band_name.replace(" ", "")
|
||||||
|
@ -167,9 +176,21 @@ class ODM_Photo:
|
||||||
|
|
||||||
self.set_attr_from_xmp_tag('sun_sensor', tags, [
|
self.set_attr_from_xmp_tag('sun_sensor', tags, [
|
||||||
'Camera:SunSensor',
|
'Camera:SunSensor',
|
||||||
|
], float)
|
||||||
|
|
||||||
|
self.set_attr_from_xmp_tag('spectral_irradiance', tags, [
|
||||||
|
'Camera:SpectralIrradiance',
|
||||||
'Camera:Irradiance',
|
'Camera:Irradiance',
|
||||||
], float)
|
], 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('center_wavelength', tags, [
|
# self.set_attr_from_xmp_tag('center_wavelength', tags, [
|
||||||
# 'Camera:CentralWavelength'
|
# 'Camera:CentralWavelength'
|
||||||
# ], float)
|
# ], float)
|
||||||
|
@ -188,6 +209,10 @@ class ODM_Photo:
|
||||||
# print(self.vignetting_center)
|
# print(self.vignetting_center)
|
||||||
# print(self.sun_sensor)
|
# 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)
|
# exit(1)
|
||||||
self.width, self.height = get_image_size.get_image_size(_path_file)
|
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
|
scale = self.irradiance_scale_to_si
|
||||||
|
|
||||||
return self.horizontal_irradiance * scale
|
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]
|
Ładowanie…
Reference in New Issue