Initial commit

This commit is contained in:
2026-04-10 16:46:45 +08:00
commit 4fd1b0a203
165 changed files with 25698 additions and 0 deletions

View File

@ -0,0 +1,27 @@
# -*- 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/>.
The :mod:`hytools.masks` module include functions image correction.
"""
from .masks import *
from .cloud import *
from .calc_apply import *

View File

@ -0,0 +1,109 @@
# -*- 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 contain functions for generating boolean masks specific to apply image corrections and
models.
"""
from scipy.ndimage.morphology import binary_erosion
import numpy as np
from .cloud import zhai_cloud
def ndi(hy_obj,args):
mask = hy_obj.ndi(args['band_1'],args['band_2'])
mask = (mask >= float(args['min'])) & (mask <= float(args['max']))
return mask
def ancillary(hy_obj,args):
''' Mask ancillary datasets based off min and max threshold
'''
if args['name'] == 'cosine_i':
mask= hy_obj.cosine_i()
else:
mask = hy_obj.get_anc(args['name'])
mask = (mask >= float(args['min'])) & (mask <= float(args['max']))
return mask
def neon_edge(hy_obj,args):
'''
Mask artifacts in NEON images around edges.
'''
radius =args['radius']
y_grid, x_grid = np.ogrid[-radius: radius + 1, -radius: radius + 1]
window = (x_grid**2 + y_grid**2 <= radius**2).astype(np.float32)
buffer_edge = binary_erosion(hy_obj.mask['no_data'], window).astype(bool)
return buffer_edge
def kernel_finite(hy_obj,args):
'''
Create NDVI bin class mask
'''
k_vol = hy_obj.volume_kernel(hy_obj.brdf['volume'])
k_geom = hy_obj.geom_kernel(hy_obj.brdf['geometric'],
b_r=hy_obj.brdf["b/r"],
h_b =hy_obj.brdf["h/b"])
mask = np.isfinite(k_vol) & np.isfinite(k_geom)
return mask
def cloud(hy_obj,args):
if args['method'] == 'zhai_2018':
mask = ~zhai_cloud(hy_obj,args['cloud'],args['shadow'],
args['T1'], args['t2'], args['t3'],
args['t4'], args['T7'], args['T8'])
return mask
def water(hy_obj,args):
'''
Create water mask using NDWI threshold
'''
mask = hy_obj.ndi(args['band_1'],args['band_2'])
mask = mask <= float(args['threshold'])
mask = binary_erosion(mask)
return mask
def external(hy_obj,args):
'''Load a mask from an external dataset
'''
hy_obj.anc_path['external_mask'] = [args['files'][hy_obj.file_name], 0]
mask = hy_obj.get_anc('external_mask') == args['class']
return mask
def band(hy_obj,args):
'''
Create mask using band thresholds
'''
mask = hy_obj.get_wave(args['band'])
mask = (mask >= float(args['min'])) & (mask <= float(args['max']))
return mask

View File

@ -0,0 +1,119 @@
# -*- 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/>.
Cloud masks
'''
from scipy.ndimage import median_filter
import numpy as np
def zhai_cloud(hy_obj,cloud,shadow,T1=0.01,t2=.1,t3=.25,t4=.5,T7= 9,T8= 9):
'''This function replicates the method of Zhai et al. (2018) for detecting clouds and shadows in
multispectral and hyperspectral imagery but does not apply shadow spatial refinement.
Suggested values for coefficients and params:
T1 : 0.01, 0.1, 1, 10, 100
t2 : 1/10, 1/9, 1/8, 1/7, 1/6, 1/5, 1/4, 1/3, 1/2
t3 : 1/4, 1/3, 1/2, 2/3, 3/4
t4 : 1/2, 2/3, 3/4, 4/5, 5/6
T7 : 3, 5, 7, 9, 11
T8 : 3, 5, 7, 9, 11
Zhai, H., Zhang, H., Zhang, L., & Li, P. (2018).
Cloud/shadow detection based on spectral indices for multi/hyperspectral optical remote sensing imagery.
ISPRS journal of photogrammetry and remote sensing, 144, 235-253.
https://doi.org/10.1016/j.isprsjprs.2018.07.006
Args:
hy_obj : HyTools data container object:
cloud (bool): Detect clouds.
shadow (bool): Detect clouds.
T1 (float): Threshold T1.
t2 (float): Adjusting coefficient t2.
t3 (float): Adjusting coefficient t3.
t4 (float): Adjusting coefficient t4.
T7 (float): Parameter T7.
T8 (float): Parameter T8.
Returns:
mask (nd.array): Boolean array where detected clouds and/or shadows = True.
'''
blue= hy_obj.get_wave(440)
green= hy_obj.get_wave(550)
red= hy_obj.get_wave(660)
nir = hy_obj.get_wave(850)
#If SWIR not available
if hy_obj.wavelengths.max() < 1570:
# Zhai et al. 2018 Eq. 1a,b
CI_1 = (3*nir)/(blue+green+red)
CI_2 = (blue+green+red+nir)/4
# Zhai et al. 2018 Eq. 3
CSI = nir
else:
swir1 = hy_obj.get_wave(1570)
swir2= hy_obj.get_wave(2110)
# Zhai et al. 2018 Eq. 1a,b
CI_1 = (nir+ 2*swir1)/(blue+green+red)
CI_2 = (blue+green+red+nir+swir1+swir2)/6
# Zhai et al. 2018 Eq. 3
CSI = (nir + swir1)/2
# Zhai et al. 2018 Eq.5
T2 = np.mean(CI_2[hy_obj.mask['no_data']]) + t2*(np.max(CI_2[hy_obj.mask['no_data']])-np.mean(CI_2[hy_obj.mask['no_data']]))
# Zhai et al. 2018 Eq.6
T3 = np.min(CSI[hy_obj.mask['no_data']]) + t3*(np.mean(CSI[hy_obj.mask['no_data']])-np.min(CSI[hy_obj.mask['no_data']]))
# Zhai et al. 2018 Eq.7
T4 = np.min(blue[hy_obj.mask['no_data']]) + t4*(np.mean(blue[hy_obj.mask['no_data']])-np.min(blue[hy_obj.mask['no_data']]))
mask = np.zeros((hy_obj.lines,hy_obj.columns)).astype(bool)
if cloud:
clouds = (np.abs(CI_1) < T1) | (CI_2 > T2)
clouds = median_filter(clouds, T7)
mask[clouds] = True
if shadow:
shadows = (CSI<T3) & (blue<T4)
shadows = median_filter(shadows,T8)
mask[shadows] = True
return mask

View File

@ -0,0 +1,42 @@
# -*- 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/>.
'''
from .calc_apply import *
from .cloud import *
mask_dict = {'ndi' : ndi,
'neon_edge' : neon_edge,
'kernel_finite': kernel_finite,
'ancillary': ancillary,
'cloud': cloud,
'water': water,
'band': band,
'external' : external}
def mask_create(hy_obj,masks):
''' Combine a series of boolean masks using an
and operator
'''
mask = np.copy(hy_obj.mask['no_data'])
for mask_name,args in masks:
mask &= mask_dict[mask_name](hy_obj,args)
return mask