mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-27 23:11:09 +00:00
584e743422
* fix yesqa hook * Remove redundant noqa * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
576 lines
19 KiB
Python
576 lines
19 KiB
Python
# Author: João Gustavo A. Amorim
|
||
# Author email: joaogustavoamorim@gmail.com
|
||
# Coding date: jan 2019
|
||
# python/black: True
|
||
|
||
# Imports
|
||
import numpy as np
|
||
|
||
|
||
# Class implemented to calculus the index
|
||
class IndexCalculation:
|
||
"""
|
||
# Class Summary
|
||
This algorithm consists in calculating vegetation indices, these
|
||
indices can be used for precision agriculture for example (or remote
|
||
sensing). There are functions to define the data and to calculate the
|
||
implemented indices.
|
||
|
||
# Vegetation index
|
||
https://en.wikipedia.org/wiki/Vegetation_Index
|
||
A Vegetation Index (VI) is a spectral transformation of two or more bands
|
||
designed to enhance the contribution of vegetation properties and allow
|
||
reliable spatial and temporal inter-comparisons of terrestrial
|
||
photosynthetic activity and canopy structural variations
|
||
|
||
# Information about channels (Wavelength range for each)
|
||
* nir - near-infrared
|
||
https://www.malvernpanalytical.com/br/products/technology/near-infrared-spectroscopy
|
||
Wavelength Range 700 nm to 2500 nm
|
||
* Red Edge
|
||
https://en.wikipedia.org/wiki/Red_edge
|
||
Wavelength Range 680 nm to 730 nm
|
||
* red
|
||
https://en.wikipedia.org/wiki/Color
|
||
Wavelength Range 635 nm to 700 nm
|
||
* blue
|
||
https://en.wikipedia.org/wiki/Color
|
||
Wavelength Range 450 nm to 490 nm
|
||
* green
|
||
https://en.wikipedia.org/wiki/Color
|
||
Wavelength Range 520 nm to 560 nm
|
||
|
||
|
||
# Implemented index list
|
||
#"abbreviationOfIndexName" -- list of channels used
|
||
|
||
#"ARVI2" -- red, nir
|
||
#"CCCI" -- red, redEdge, nir
|
||
#"CVI" -- red, green, nir
|
||
#"GLI" -- red, green, blue
|
||
#"NDVI" -- red, nir
|
||
#"BNDVI" -- blue, nir
|
||
#"redEdgeNDVI" -- red, redEdge
|
||
#"GNDVI" -- green, nir
|
||
#"GBNDVI" -- green, blue, nir
|
||
#"GRNDVI" -- red, green, nir
|
||
#"RBNDVI" -- red, blue, nir
|
||
#"PNDVI" -- red, green, blue, nir
|
||
#"ATSAVI" -- red, nir
|
||
#"BWDRVI" -- blue, nir
|
||
#"CIgreen" -- green, nir
|
||
#"CIrededge" -- redEdge, nir
|
||
#"CI" -- red, blue
|
||
#"CTVI" -- red, nir
|
||
#"GDVI" -- green, nir
|
||
#"EVI" -- red, blue, nir
|
||
#"GEMI" -- red, nir
|
||
#"GOSAVI" -- green, nir
|
||
#"GSAVI" -- green, nir
|
||
#"Hue" -- red, green, blue
|
||
#"IVI" -- red, nir
|
||
#"IPVI" -- red, nir
|
||
#"I" -- red, green, blue
|
||
#"RVI" -- red, nir
|
||
#"MRVI" -- red, nir
|
||
#"MSAVI" -- red, nir
|
||
#"NormG" -- red, green, nir
|
||
#"NormNIR" -- red, green, nir
|
||
#"NormR" -- red, green, nir
|
||
#"NGRDI" -- red, green
|
||
#"RI" -- red, green
|
||
#"S" -- red, green, blue
|
||
#"IF" -- red, green, blue
|
||
#"DVI" -- red, nir
|
||
#"TVI" -- red, nir
|
||
#"NDRE" -- redEdge, nir
|
||
|
||
#list of all index implemented
|
||
#allIndex = ["ARVI2", "CCCI", "CVI", "GLI", "NDVI", "BNDVI", "redEdgeNDVI",
|
||
"GNDVI", "GBNDVI", "GRNDVI", "RBNDVI", "PNDVI", "ATSAVI",
|
||
"BWDRVI", "CIgreen", "CIrededge", "CI", "CTVI", "GDVI", "EVI",
|
||
"GEMI", "GOSAVI", "GSAVI", "Hue", "IVI", "IPVI", "I", "RVI",
|
||
"MRVI", "MSAVI", "NormG", "NormNIR", "NormR", "NGRDI", "RI",
|
||
"S", "IF", "DVI", "TVI", "NDRE"]
|
||
|
||
#list of index with not blue channel
|
||
#notBlueIndex = ["ARVI2", "CCCI", "CVI", "NDVI", "redEdgeNDVI", "GNDVI",
|
||
"GRNDVI", "ATSAVI", "CIgreen", "CIrededge", "CTVI", "GDVI",
|
||
"GEMI", "GOSAVI", "GSAVI", "IVI", "IPVI", "RVI", "MRVI",
|
||
"MSAVI", "NormG", "NormNIR", "NormR", "NGRDI", "RI", "DVI",
|
||
"TVI", "NDRE"]
|
||
|
||
#list of index just with RGB channels
|
||
#RGBIndex = ["GLI", "CI", "Hue", "I", "NGRDI", "RI", "S", "IF"]
|
||
"""
|
||
|
||
def __init__(self, red=None, green=None, blue=None, red_edge=None, nir=None):
|
||
self.set_matricies(red=red, green=green, blue=blue, red_edge=red_edge, nir=nir)
|
||
|
||
def set_matricies(self, red=None, green=None, blue=None, red_edge=None, nir=None):
|
||
if red is not None:
|
||
self.red = red
|
||
if green is not None:
|
||
self.green = green
|
||
if blue is not None:
|
||
self.blue = blue
|
||
if red_edge is not None:
|
||
self.redEdge = red_edge
|
||
if nir is not None:
|
||
self.nir = nir
|
||
return True
|
||
|
||
def calculation(
|
||
self, index="", red=None, green=None, blue=None, red_edge=None, nir=None
|
||
):
|
||
"""
|
||
performs the calculation of the index with the values instantiated in the class
|
||
:str index: abbreviation of index name to perform
|
||
"""
|
||
self.set_matricies(red=red, green=green, blue=blue, red_edge=red_edge, nir=nir)
|
||
funcs = {
|
||
"ARVI2": self.arv12,
|
||
"CCCI": self.ccci,
|
||
"CVI": self.cvi,
|
||
"GLI": self.gli,
|
||
"NDVI": self.ndvi,
|
||
"BNDVI": self.bndvi,
|
||
"redEdgeNDVI": self.red_edge_ndvi,
|
||
"GNDVI": self.gndvi,
|
||
"GBNDVI": self.gbndvi,
|
||
"GRNDVI": self.grndvi,
|
||
"RBNDVI": self.rbndvi,
|
||
"PNDVI": self.pndvi,
|
||
"ATSAVI": self.atsavi,
|
||
"BWDRVI": self.bwdrvi,
|
||
"CIgreen": self.ci_green,
|
||
"CIrededge": self.ci_rededge,
|
||
"CI": self.ci,
|
||
"CTVI": self.ctvi,
|
||
"GDVI": self.gdvi,
|
||
"EVI": self.evi,
|
||
"GEMI": self.gemi,
|
||
"GOSAVI": self.gosavi,
|
||
"GSAVI": self.gsavi,
|
||
"Hue": self.hue,
|
||
"IVI": self.ivi,
|
||
"IPVI": self.ipvi,
|
||
"I": self.i,
|
||
"RVI": self.rvi,
|
||
"MRVI": self.mrvi,
|
||
"MSAVI": self.m_savi,
|
||
"NormG": self.norm_g,
|
||
"NormNIR": self.norm_nir,
|
||
"NormR": self.norm_r,
|
||
"NGRDI": self.ngrdi,
|
||
"RI": self.ri,
|
||
"S": self.s,
|
||
"IF": self._if,
|
||
"DVI": self.dvi,
|
||
"TVI": self.tvi,
|
||
"NDRE": self.ndre,
|
||
}
|
||
|
||
try:
|
||
return funcs[index]()
|
||
except KeyError:
|
||
print("Index not in the list!")
|
||
return False
|
||
|
||
def arv12(self):
|
||
"""
|
||
Atmospherically Resistant Vegetation Index 2
|
||
https://www.indexdatabase.de/db/i-single.php?id=396
|
||
:return: index
|
||
−0.18+1.17*(self.nir−self.red)/(self.nir+self.red)
|
||
"""
|
||
return -0.18 + (1.17 * ((self.nir - self.red) / (self.nir + self.red)))
|
||
|
||
def ccci(self):
|
||
"""
|
||
Canopy Chlorophyll Content Index
|
||
https://www.indexdatabase.de/db/i-single.php?id=224
|
||
:return: index
|
||
"""
|
||
return ((self.nir - self.redEdge) / (self.nir + self.redEdge)) / (
|
||
(self.nir - self.red) / (self.nir + self.red)
|
||
)
|
||
|
||
def cvi(self):
|
||
"""
|
||
Chlorophyll vegetation index
|
||
https://www.indexdatabase.de/db/i-single.php?id=391
|
||
:return: index
|
||
"""
|
||
return self.nir * (self.red / (self.green**2))
|
||
|
||
def gli(self):
|
||
"""
|
||
self.green leaf index
|
||
https://www.indexdatabase.de/db/i-single.php?id=375
|
||
:return: index
|
||
"""
|
||
return (2 * self.green - self.red - self.blue) / (
|
||
2 * self.green + self.red + self.blue
|
||
)
|
||
|
||
def ndvi(self):
|
||
"""
|
||
Normalized Difference self.nir/self.red Normalized Difference Vegetation
|
||
Index, Calibrated NDVI - CDVI
|
||
https://www.indexdatabase.de/db/i-single.php?id=58
|
||
:return: index
|
||
"""
|
||
return (self.nir - self.red) / (self.nir + self.red)
|
||
|
||
def bndvi(self):
|
||
"""
|
||
Normalized Difference self.nir/self.blue self.blue-normalized difference
|
||
vegetation index
|
||
https://www.indexdatabase.de/db/i-single.php?id=135
|
||
:return: index
|
||
"""
|
||
return (self.nir - self.blue) / (self.nir + self.blue)
|
||
|
||
def red_edge_ndvi(self):
|
||
"""
|
||
Normalized Difference self.rededge/self.red
|
||
https://www.indexdatabase.de/db/i-single.php?id=235
|
||
:return: index
|
||
"""
|
||
return (self.redEdge - self.red) / (self.redEdge + self.red)
|
||
|
||
def gndvi(self):
|
||
"""
|
||
Normalized Difference self.nir/self.green self.green NDVI
|
||
https://www.indexdatabase.de/db/i-single.php?id=401
|
||
:return: index
|
||
"""
|
||
return (self.nir - self.green) / (self.nir + self.green)
|
||
|
||
def gbndvi(self):
|
||
"""
|
||
self.green-self.blue NDVI
|
||
https://www.indexdatabase.de/db/i-single.php?id=186
|
||
:return: index
|
||
"""
|
||
return (self.nir - (self.green + self.blue)) / (
|
||
self.nir + (self.green + self.blue)
|
||
)
|
||
|
||
def grndvi(self):
|
||
"""
|
||
self.green-self.red NDVI
|
||
https://www.indexdatabase.de/db/i-single.php?id=185
|
||
:return: index
|
||
"""
|
||
return (self.nir - (self.green + self.red)) / (
|
||
self.nir + (self.green + self.red)
|
||
)
|
||
|
||
def rbndvi(self):
|
||
"""
|
||
self.red-self.blue NDVI
|
||
https://www.indexdatabase.de/db/i-single.php?id=187
|
||
:return: index
|
||
"""
|
||
return (self.nir - (self.blue + self.red)) / (self.nir + (self.blue + self.red))
|
||
|
||
def pndvi(self):
|
||
"""
|
||
Pan NDVI
|
||
https://www.indexdatabase.de/db/i-single.php?id=188
|
||
:return: index
|
||
"""
|
||
return (self.nir - (self.green + self.red + self.blue)) / (
|
||
self.nir + (self.green + self.red + self.blue)
|
||
)
|
||
|
||
def atsavi(self, x=0.08, a=1.22, b=0.03):
|
||
"""
|
||
Adjusted transformed soil-adjusted VI
|
||
https://www.indexdatabase.de/db/i-single.php?id=209
|
||
:return: index
|
||
"""
|
||
return a * (
|
||
(self.nir - a * self.red - b)
|
||
/ (a * self.nir + self.red - a * b + x * (1 + a**2))
|
||
)
|
||
|
||
def bwdrvi(self):
|
||
"""
|
||
self.blue-wide dynamic range vegetation index
|
||
https://www.indexdatabase.de/db/i-single.php?id=136
|
||
:return: index
|
||
"""
|
||
return (0.1 * self.nir - self.blue) / (0.1 * self.nir + self.blue)
|
||
|
||
def ci_green(self):
|
||
"""
|
||
Chlorophyll Index self.green
|
||
https://www.indexdatabase.de/db/i-single.php?id=128
|
||
:return: index
|
||
"""
|
||
return (self.nir / self.green) - 1
|
||
|
||
def ci_rededge(self):
|
||
"""
|
||
Chlorophyll Index self.redEdge
|
||
https://www.indexdatabase.de/db/i-single.php?id=131
|
||
:return: index
|
||
"""
|
||
return (self.nir / self.redEdge) - 1
|
||
|
||
def ci(self):
|
||
"""
|
||
Coloration Index
|
||
https://www.indexdatabase.de/db/i-single.php?id=11
|
||
:return: index
|
||
"""
|
||
return (self.red - self.blue) / self.red
|
||
|
||
def ctvi(self):
|
||
"""
|
||
Corrected Transformed Vegetation Index
|
||
https://www.indexdatabase.de/db/i-single.php?id=244
|
||
:return: index
|
||
"""
|
||
ndvi = self.ndvi()
|
||
return ((ndvi + 0.5) / (abs(ndvi + 0.5))) * (abs(ndvi + 0.5) ** (1 / 2))
|
||
|
||
def gdvi(self):
|
||
"""
|
||
Difference self.nir/self.green self.green Difference Vegetation Index
|
||
https://www.indexdatabase.de/db/i-single.php?id=27
|
||
:return: index
|
||
"""
|
||
return self.nir - self.green
|
||
|
||
def evi(self):
|
||
"""
|
||
Enhanced Vegetation Index
|
||
https://www.indexdatabase.de/db/i-single.php?id=16
|
||
:return: index
|
||
"""
|
||
return 2.5 * (
|
||
(self.nir - self.red) / (self.nir + 6 * self.red - 7.5 * self.blue + 1)
|
||
)
|
||
|
||
def gemi(self):
|
||
"""
|
||
Global Environment Monitoring Index
|
||
https://www.indexdatabase.de/db/i-single.php?id=25
|
||
:return: index
|
||
"""
|
||
n = (2 * (self.nir**2 - self.red**2) + 1.5 * self.nir + 0.5 * self.red) / (
|
||
self.nir + self.red + 0.5
|
||
)
|
||
return n * (1 - 0.25 * n) - (self.red - 0.125) / (1 - self.red)
|
||
|
||
def gosavi(self, y=0.16):
|
||
"""
|
||
self.green Optimized Soil Adjusted Vegetation Index
|
||
https://www.indexdatabase.de/db/i-single.php?id=29
|
||
mit Y = 0,16
|
||
:return: index
|
||
"""
|
||
return (self.nir - self.green) / (self.nir + self.green + y)
|
||
|
||
def gsavi(self, n=0.5):
|
||
"""
|
||
self.green Soil Adjusted Vegetation Index
|
||
https://www.indexdatabase.de/db/i-single.php?id=31
|
||
mit N = 0,5
|
||
:return: index
|
||
"""
|
||
return ((self.nir - self.green) / (self.nir + self.green + n)) * (1 + n)
|
||
|
||
def hue(self):
|
||
"""
|
||
Hue
|
||
https://www.indexdatabase.de/db/i-single.php?id=34
|
||
:return: index
|
||
"""
|
||
return np.arctan(
|
||
((2 * self.red - self.green - self.blue) / 30.5) * (self.green - self.blue)
|
||
)
|
||
|
||
def ivi(self, a=None, b=None):
|
||
"""
|
||
Ideal vegetation index
|
||
https://www.indexdatabase.de/db/i-single.php?id=276
|
||
b=intercept of vegetation line
|
||
a=soil line slope
|
||
:return: index
|
||
"""
|
||
return (self.nir - b) / (a * self.red)
|
||
|
||
def ipvi(self):
|
||
"""
|
||
Infraself.red percentage vegetation index
|
||
https://www.indexdatabase.de/db/i-single.php?id=35
|
||
:return: index
|
||
"""
|
||
return (self.nir / ((self.nir + self.red) / 2)) * (self.ndvi() + 1)
|
||
|
||
def i(self):
|
||
"""
|
||
Intensity
|
||
https://www.indexdatabase.de/db/i-single.php?id=36
|
||
:return: index
|
||
"""
|
||
return (self.red + self.green + self.blue) / 30.5
|
||
|
||
def rvi(self):
|
||
"""
|
||
Ratio-Vegetation-Index
|
||
http://www.seos-project.eu/modules/remotesensing/remotesensing-c03-s01-p01.html
|
||
:return: index
|
||
"""
|
||
return self.nir / self.red
|
||
|
||
def mrvi(self):
|
||
"""
|
||
Modified Normalized Difference Vegetation Index RVI
|
||
https://www.indexdatabase.de/db/i-single.php?id=275
|
||
:return: index
|
||
"""
|
||
return (self.rvi() - 1) / (self.rvi() + 1)
|
||
|
||
def m_savi(self):
|
||
"""
|
||
Modified Soil Adjusted Vegetation Index
|
||
https://www.indexdatabase.de/db/i-single.php?id=44
|
||
:return: index
|
||
"""
|
||
return (
|
||
(2 * self.nir + 1)
|
||
- ((2 * self.nir + 1) ** 2 - 8 * (self.nir - self.red)) ** (1 / 2)
|
||
) / 2
|
||
|
||
def norm_g(self):
|
||
"""
|
||
Norm G
|
||
https://www.indexdatabase.de/db/i-single.php?id=50
|
||
:return: index
|
||
"""
|
||
return self.green / (self.nir + self.red + self.green)
|
||
|
||
def norm_nir(self):
|
||
"""
|
||
Norm self.nir
|
||
https://www.indexdatabase.de/db/i-single.php?id=51
|
||
:return: index
|
||
"""
|
||
return self.nir / (self.nir + self.red + self.green)
|
||
|
||
def norm_r(self):
|
||
"""
|
||
Norm R
|
||
https://www.indexdatabase.de/db/i-single.php?id=52
|
||
:return: index
|
||
"""
|
||
return self.red / (self.nir + self.red + self.green)
|
||
|
||
def ngrdi(self):
|
||
"""
|
||
Normalized Difference self.green/self.red Normalized self.green self.red
|
||
difference index, Visible Atmospherically Resistant Indices self.green
|
||
(VIself.green)
|
||
https://www.indexdatabase.de/db/i-single.php?id=390
|
||
:return: index
|
||
"""
|
||
return (self.green - self.red) / (self.green + self.red)
|
||
|
||
def ri(self):
|
||
"""
|
||
Normalized Difference self.red/self.green self.redness Index
|
||
https://www.indexdatabase.de/db/i-single.php?id=74
|
||
:return: index
|
||
"""
|
||
return (self.red - self.green) / (self.red + self.green)
|
||
|
||
def s(self):
|
||
"""
|
||
Saturation
|
||
https://www.indexdatabase.de/db/i-single.php?id=77
|
||
:return: index
|
||
"""
|
||
max_value = np.max([np.max(self.red), np.max(self.green), np.max(self.blue)])
|
||
min_value = np.min([np.min(self.red), np.min(self.green), np.min(self.blue)])
|
||
return (max_value - min_value) / max_value
|
||
|
||
def _if(self):
|
||
"""
|
||
Shape Index
|
||
https://www.indexdatabase.de/db/i-single.php?id=79
|
||
:return: index
|
||
"""
|
||
return (2 * self.red - self.green - self.blue) / (self.green - self.blue)
|
||
|
||
def dvi(self):
|
||
"""
|
||
Simple Ratio self.nir/self.red Difference Vegetation Index, Vegetation Index
|
||
Number (VIN)
|
||
https://www.indexdatabase.de/db/i-single.php?id=12
|
||
:return: index
|
||
"""
|
||
return self.nir / self.red
|
||
|
||
def tvi(self):
|
||
"""
|
||
Transformed Vegetation Index
|
||
https://www.indexdatabase.de/db/i-single.php?id=98
|
||
:return: index
|
||
"""
|
||
return (self.ndvi() + 0.5) ** (1 / 2)
|
||
|
||
def ndre(self):
|
||
return (self.nir - self.redEdge) / (self.nir + self.redEdge)
|
||
|
||
|
||
"""
|
||
# genering a random matrices to test this class
|
||
red = np.ones((1000,1000, 1),dtype="float64") * 46787
|
||
green = np.ones((1000,1000, 1),dtype="float64") * 23487
|
||
blue = np.ones((1000,1000, 1),dtype="float64") * 14578
|
||
redEdge = np.ones((1000,1000, 1),dtype="float64") * 51045
|
||
nir = np.ones((1000,1000, 1),dtype="float64") * 52200
|
||
|
||
# Examples of how to use the class
|
||
|
||
# instantiating the class
|
||
cl = IndexCalculation()
|
||
|
||
# instantiating the class with the values
|
||
#cl = indexCalculation(red=red, green=green, blue=blue, redEdge=redEdge, nir=nir)
|
||
|
||
# how set the values after instantiate the class cl, (for update the data or when don't
|
||
# instantiating the class with the values)
|
||
cl.setMatrices(red=red, green=green, blue=blue, redEdge=redEdge, nir=nir)
|
||
|
||
# calculating the indices for the instantiated values in the class
|
||
# Note: the CCCI index can be changed to any index implemented in the class.
|
||
indexValue_form1 = cl.calculation("CCCI", red=red, green=green, blue=blue,
|
||
redEdge=redEdge, nir=nir).astype(np.float64)
|
||
indexValue_form2 = cl.CCCI()
|
||
|
||
# calculating the index with the values directly -- you can set just the values
|
||
# preferred note: the *calculation* function performs the function *setMatrices*
|
||
indexValue_form3 = cl.calculation("CCCI", red=red, green=green, blue=blue,
|
||
redEdge=redEdge, nir=nir).astype(np.float64)
|
||
|
||
print("Form 1: "+np.array2string(indexValue_form1, precision=20, separator=', ',
|
||
floatmode='maxprec_equal'))
|
||
print("Form 2: "+np.array2string(indexValue_form2, precision=20, separator=', ',
|
||
floatmode='maxprec_equal'))
|
||
print("Form 3: "+np.array2string(indexValue_form3, precision=20, separator=', ',
|
||
floatmode='maxprec_equal'))
|
||
|
||
# A list of examples results for different type of data at NDVI
|
||
# float16 -> 0.31567383 #NDVI (red = 50, nir = 100)
|
||
# float32 -> 0.31578946 #NDVI (red = 50, nir = 100)
|
||
# float64 -> 0.3157894736842105 #NDVI (red = 50, nir = 100)
|
||
# longdouble -> 0.3157894736842105 #NDVI (red = 50, nir = 100)
|
||
"""
|