kopia lustrzana https://github.com/OpenDroneMap/ODM
rodzic
a61b5b308a
commit
309c7751b3
|
|
@ -65,8 +65,6 @@ def dn_to_radiance(photo, image):
|
||||||
R = 1.0 / (1.0 + a2 * y / exposure_time - a3 * y)
|
R = 1.0 / (1.0 + a2 * y / exposure_time - a3 * y)
|
||||||
image *= R
|
image *= R
|
||||||
|
|
||||||
cv2.imwrite("/datasets/mica/R.tif", R)
|
|
||||||
|
|
||||||
print("Row gradient")
|
print("Row gradient")
|
||||||
|
|
||||||
# Floor any negative radiances to zero (can happend due to noise around blackLevel)
|
# Floor any negative radiances to zero (can happend due to noise around blackLevel)
|
||||||
|
|
@ -114,19 +112,28 @@ def vignette_map(photo):
|
||||||
|
|
||||||
def dn_to_reflectance(photo, image, use_sun_sensor=True):
|
def dn_to_reflectance(photo, image, use_sun_sensor=True):
|
||||||
radiance = dn_to_radiance(photo, image)
|
radiance = dn_to_radiance(photo, image)
|
||||||
irradiance_scale = compute_irradiance_scale_factor(photo, use_sun_sensor=use_sun_sensor)
|
|
||||||
return radiance * irradiance_scale
|
|
||||||
|
|
||||||
def compute_irradiance_scale_factor(photo, use_sun_sensor=True):
|
# TODO REMOVE
|
||||||
|
cv2.imwrite("/datasets/sentera-6x/radiance.tif", radiance)
|
||||||
|
|
||||||
|
|
||||||
|
irradiance = compute_irradiance(photo, use_sun_sensor=use_sun_sensor)
|
||||||
|
print(irradiance)
|
||||||
|
return radiance * math.pi / irradiance
|
||||||
|
|
||||||
|
def compute_irradiance(photo, use_sun_sensor=True):
|
||||||
# Thermal?
|
# Thermal?
|
||||||
if photo.band_name == "LWIR":
|
if photo.band_name == "LWIR":
|
||||||
return 1.0
|
return 1.0
|
||||||
|
|
||||||
if photo.irradiance is not None:
|
# Some cameras (Micasense) store the value (nice! just return)
|
||||||
horizontal_irradiance = photo.irradiance
|
hirradiance = photo.get_horizontal_irradiance()
|
||||||
return math.pi / horizontal_irradiance
|
if hirradiance is not None:
|
||||||
|
return hirradiance
|
||||||
|
|
||||||
if use_sun_sensor:
|
# TODO: support for calibration panels
|
||||||
|
|
||||||
|
if use_sun_sensor and photo.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, \
|
||||||
|
|
@ -137,21 +144,25 @@ def compute_irradiance_scale_factor(photo, use_sun_sensor=True):
|
||||||
|
|
||||||
angular_correction = dls.fresnel(sun_sensor_angle)
|
angular_correction = dls.fresnel(sun_sensor_angle)
|
||||||
|
|
||||||
|
print("Sun sensor")
|
||||||
|
|
||||||
# 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
|
||||||
spectral_irradiance = photo.sun_sensor # TODO: support for XMP:SpectralIrradiance
|
spectral_irradiance = photo.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
|
||||||
|
|
||||||
# find direct irradiance in the plane normal to the sun
|
# Find direct irradiance in the plane normal to the sun
|
||||||
untilted_direct_irr = sensor_irradiance / (percent_diffuse + np.cos(sun_sensor_angle))
|
untilted_direct_irr = sensor_irradiance / (percent_diffuse + np.cos(sun_sensor_angle))
|
||||||
direct_irradiance = untilted_direct_irr
|
direct_irradiance = untilted_direct_irr
|
||||||
scattered_irradiance = untilted_direct_irr*percent_diffuse
|
scattered_irradiance = untilted_direct_irr * percent_diffuse
|
||||||
|
|
||||||
# compute irradiance on the ground using the solar altitude angle
|
# compute irradiance on the ground using the solar altitude angle
|
||||||
horizontal_irradiance = direct_irradiance * np.sin(solar_elevation) + scattered_irradiance
|
horizontal_irradiance = direct_irradiance * np.sin(solar_elevation) + scattered_irradiance
|
||||||
return math.pi / horizontal_irradiance
|
return horizontal_irradiance
|
||||||
|
elif use_sun_sensor:
|
||||||
|
log.ODM_WARNING("No sun sensor values found for %s" % photo.filename)
|
||||||
|
|
||||||
return 1.0
|
return 1.0
|
||||||
|
|
@ -46,7 +46,9 @@ 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.irradiance = None
|
||||||
|
self.horizontal_irradiance = None
|
||||||
|
self.irradiance_scale_to_si = None
|
||||||
self.sun_sensor = None
|
self.sun_sensor = None
|
||||||
self.utc_time = None
|
self.utc_time = None
|
||||||
|
|
||||||
|
|
@ -155,12 +157,17 @@ class ODM_Photo:
|
||||||
'Sentera:VignettingPolynomial',
|
'Sentera:VignettingPolynomial',
|
||||||
])
|
])
|
||||||
|
|
||||||
self.set_attr_from_xmp_tag('irradiance', tags, [
|
self.set_attr_from_xmp_tag('horizontal_irradiance', tags, [
|
||||||
'Camera:Irradiance'
|
'Camera:HorizontalIrradiance'
|
||||||
|
], float)
|
||||||
|
|
||||||
|
self.set_attr_from_xmp_tag('irradiance_scale_to_si', tags, [
|
||||||
|
'Camera:IrradianceScaleToSIUnits'
|
||||||
], float)
|
], float)
|
||||||
|
|
||||||
self.set_attr_from_xmp_tag('sun_sensor', tags, [
|
self.set_attr_from_xmp_tag('sun_sensor', tags, [
|
||||||
'Camera:SunSensor'
|
'Camera:SunSensor',
|
||||||
|
'Camera:Irradiance',
|
||||||
], float)
|
], float)
|
||||||
|
|
||||||
# self.set_attr_from_xmp_tag('center_wavelength', tags, [
|
# self.set_attr_from_xmp_tag('center_wavelength', tags, [
|
||||||
|
|
@ -181,7 +188,7 @@ 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())
|
||||||
#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)
|
||||||
|
|
||||||
# Sanitize band name since we use it in folder paths
|
# Sanitize band name since we use it in folder paths
|
||||||
|
|
@ -313,3 +320,11 @@ class ODM_Photo:
|
||||||
# H ~= (exposure_time) / (f_number^2)
|
# H ~= (exposure_time) / (f_number^2)
|
||||||
if self.fnumber is not None and self.exposure_time > 0:
|
if self.fnumber is not None and self.exposure_time > 0:
|
||||||
return self.exposure_time / (self.fnumber * self.fnumber)
|
return self.exposure_time / (self.fnumber * self.fnumber)
|
||||||
|
|
||||||
|
def get_horizontal_irradiance(self):
|
||||||
|
if self.horizontal_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.horizontal_irradiance * scale
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,9 @@ class ODMOpenSfMStage(types.ODM_Stage):
|
||||||
if args.radiometric_calibration == "none":
|
if args.radiometric_calibration == "none":
|
||||||
octx.convert_and_undistort(self.rerun())
|
octx.convert_and_undistort(self.rerun())
|
||||||
else:
|
else:
|
||||||
|
|
||||||
|
# TODO: does this work for multi-band RGB images?
|
||||||
|
|
||||||
def radiometric_calibrate(shot_id, image):
|
def radiometric_calibrate(shot_id, image):
|
||||||
photo = reconstruction.get_photo(shot_id)
|
photo = reconstruction.get_photo(shot_id)
|
||||||
return multispectral.dn_to_reflectance(photo, image, use_sun_sensor=args.radiometric_calibration=="camera+sun")
|
return multispectral.dn_to_reflectance(photo, image, use_sun_sensor=args.radiometric_calibration=="camera+sun")
|
||||||
|
|
|
||||||
Ładowanie…
Reference in New Issue