Initial commit
This commit is contained in:
140
Flexbrdf/hytools/topo/modminn.py
Normal file
140
Flexbrdf/hytools/topo/modminn.py
Normal file
@ -0,0 +1,140 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
HyTools: Hyperspectral image processing library
|
||||
Copyright (C) 2021 University of Wisconsin
|
||||
|
||||
Authors: Adam Chlus, Zhiwei Ye, Philip Townsend.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, version 3 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
This module contains functions to apply the Modified topographic correction (SCS+C)
|
||||
described in the following paper:
|
||||
|
||||
Richter, R., Kellenberger, T., & Kaufmann, H. (2009).
|
||||
Comparison of topographic correction methods.
|
||||
Remote Sensing, 1(3), 184-196.
|
||||
https://doi.org/10.3390/rs1030184
|
||||
|
||||
Topographic correction consists of the following steps:
|
||||
|
||||
|
||||
"""
|
||||
import numpy as np
|
||||
|
||||
def calc_modminn_coeffs(hy_obj,topo_dict):
|
||||
'''
|
||||
|
||||
Args:
|
||||
hy_obj (TYPE): DESCRIPTION.
|
||||
|
||||
Returns:
|
||||
None.
|
||||
|
||||
'''
|
||||
hy_obj.topo =topo_dict
|
||||
|
||||
cos_i = hy_obj.cosine_i()
|
||||
i = np.rad2deg(np.arccos(cos_i))
|
||||
solar_zn = hy_obj.get_anc('solar_zn',radians=False)
|
||||
|
||||
solar_zn_t = np.zeros(solar_zn.shape)
|
||||
solar_zn_t[solar_zn < 45] = solar_zn[solar_zn < 45] +20
|
||||
solar_zn_t[(solar_zn >= 45) & (solar_zn <= 55)] = solar_zn[(solar_zn >= 45) & (solar_zn <= 55)] +15
|
||||
solar_zn_t[solar_zn > 55] = solar_zn[solar_zn > 55] +10
|
||||
|
||||
#Create NDVI mask to seperate vegetation
|
||||
ir = hy_obj.get_wave(850)
|
||||
red = hy_obj.get_wave(660)
|
||||
ndvi = (ir-red)/(ir+red)
|
||||
veg_mask = ndvi > 0.2
|
||||
|
||||
c_factors = np.ones((2,hy_obj.lines,hy_obj.columns))
|
||||
c_factors[:] = cos_i/np.cos(np.radians(solar_zn_t))
|
||||
|
||||
# Non vegetation correction factor
|
||||
c_factors[0][~veg_mask] = c_factors[0][~veg_mask]**(1/2)
|
||||
c_factors[1][~veg_mask] = c_factors[1][~veg_mask]**(1/2)
|
||||
|
||||
# Vegetation correction factor
|
||||
c_factors[0][veg_mask] = c_factors[0][veg_mask]**(3/4)
|
||||
c_factors[1][veg_mask] = c_factors[1][veg_mask]**(1/3)
|
||||
|
||||
#Adjust correction factors to prevent too strong correction
|
||||
c_factors[c_factors <.25] = .25
|
||||
c_factors[c_factors > 1] = 1
|
||||
|
||||
#Correct pixels only where i > threshold
|
||||
c_factors[0][i < solar_zn_t] = 1
|
||||
c_factors[1][i < solar_zn_t] = 1
|
||||
|
||||
c_factors[0][ir == hy_obj.no_data] = 1
|
||||
c_factors[1][ir == hy_obj.no_data] = 1
|
||||
|
||||
hy_obj.ancillary['mm_c_factor'] = c_factors
|
||||
|
||||
def apply_modminn(hy_obj,data,dimension,index):
|
||||
''' Apply SCSS correction to a slice of the data
|
||||
|
||||
Args:
|
||||
hy_obj (TYPE): DESCRIPTION.
|
||||
band (TYPE): DESCRIPTION.
|
||||
index (TYPE): DESCRIPTION.
|
||||
|
||||
Returns:
|
||||
band (TYPE): DESCRIPTION.
|
||||
|
||||
'''
|
||||
|
||||
if 'mm_c_factor' not in hy_obj.ancillary.keys():
|
||||
calc_modminn_coeffs(hy_obj)
|
||||
|
||||
#Convert to float
|
||||
data = data.astype(np.float32)
|
||||
|
||||
wave_mask =hy_obj.wavelengths >=720
|
||||
|
||||
if dimension == 'line':
|
||||
#index= 3000
|
||||
#data = hy_obj.get_line(3000)
|
||||
data[:,wave_mask] = data[:,wave_mask]*hy_obj.ancillary['mm_c_factor'][1,index,:][:,np.newaxis]
|
||||
data[:,~wave_mask] = data[:,~wave_mask]*hy_obj.ancillary['mm_c_factor'][0,index,:][:,np.newaxis]
|
||||
|
||||
elif dimension == 'column':
|
||||
#index= 300
|
||||
#data = hy_obj.get_column(index)
|
||||
data[:,wave_mask] = data[:,wave_mask]*hy_obj.ancillary['mm_c_factor'][1,:,index][:,np.newaxis]
|
||||
data[:,~wave_mask] = data[:,~wave_mask]*hy_obj.ancillary['mm_c_factor'][0,:,index][:,np.newaxis]
|
||||
|
||||
elif dimension == 'band':
|
||||
#index= 50
|
||||
#data = hy_obj.get_band(index)
|
||||
if hy_obj.wavelengths[index] >=720:
|
||||
cf_index = 1
|
||||
else:
|
||||
cf_index = 0
|
||||
data = data * hy_obj.ancillary['mm_c_factor'][cf_index]
|
||||
|
||||
elif dimension == 'chunk':
|
||||
#index = 200,501,3000,3501
|
||||
x1,x2,y1,y2 = index
|
||||
#data = hy_obj.get_chunk(x1,x2,y1,y2)
|
||||
data[:,:,wave_mask] = data[:,:,wave_mask]*hy_obj.ancillary['mm_c_factor'][1,y1:y2,x1:x2][:,:,np.newaxis]
|
||||
data[:,:,~wave_mask] = data[:,:,~wave_mask]*hy_obj.ancillary['mm_c_factor'][0,y1:y2,x1:x2][:,:,np.newaxis]
|
||||
|
||||
elif dimension == 'pixels':
|
||||
#index = [[2000,2001],[200,501]]
|
||||
y,x = index
|
||||
#data = hy_obj.get_pixels(y,x)
|
||||
data[:,wave_mask] = data[:,wave_mask]*hy_obj.ancillary['mm_c_factor'][1,y,x][:, np.newaxis]
|
||||
data[:,~wave_mask] = data[:,~wave_mask]*hy_obj.ancillary['mm_c_factor'][0,y,x][:, np.newaxis]
|
||||
return data
|
||||
Reference in New Issue
Block a user