-
Notifications
You must be signed in to change notification settings - Fork 26
/
MNF.py
executable file
·152 lines (130 loc) · 4.59 KB
/
MNF.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/python
# -*- coding: latin-1 -*-
########################################################################################################################
#
# MNF.py
# A python script to perform MNF transformation to remote sesning data.
#
# Info: The script perform MNF transformation to all raster images stored in a folder.
#
# Author: Javier Lopatin
# Email: javierlopatin@gmail.com
# Date: 09/08/2016
# Version: 2.0
# Last checked: 23/11/2020
#
# Usage:
#
# python MNF.py -i <Imput raster>
# -c <Number of components [default = inputRaster bands]>
# -p <Preprocessing: Brightness Normalization of Hyperspectral data [Optional]>
#
# # --preprop [-p]: Brightness Normalization presented in Feilhauer et al., 2010
#
# # examples:
# # Get the regular MNF transformation
# python MNF.py -i raster.tif
#
# # Get the regular MNF transformation of the first component
# python MNF.py -i raster.tif -c 1
#
# # with Brightness Normalization
# python MNF_cmd.py -i raster.tif -p
#
#
#
# Bibliography:
#
# Feilhauer, H., Asner, G. P., Martin, R. E., Schmidtlein, S. (2010): Brightness-normalized Partial Least Squares
# Regression for hyperspectral data. Journal of Quantitative Spectroscopy and Radiative Transfer 111(12-13),
# pp. 1947–1957. 10.1016/j.jqsrt.2010.03.007
#
# C-I Change and Q Du. 1999. Interference and Noise-Adjusted Principal Components Analysis.
# IEEE TGRS, Vol 36, No 5.
#
########################################################################################################################
from __future__ import division
import argparse
import numpy as np
from sklearn.decomposition import IncrementalPCA
import rasterio
try:
import pysptools.noise as ns
except ImportError:
print("ERROR: Could not import Pysptools Python library.")
print("Check if Pysptools is installed.")
#%%
################
### Functions
################
def _norm(X):
return X / np.sqrt( np.sum((X**2), 0) )
def brightNorm(X):
return np.apply_along_axis(_norm, 0, X)
#%%
### Run process
if __name__ == "__main__":
# create the arguments for the algorithm
parser = argparse.ArgumentParser()
parser.add_argument('-i','--inputRaster',
help='Input raster', type=str, required=True)
parser.add_argument('-c','--components',
help='Number of components.', type=int, default=10000)
parser.add_argument('-p','--preprop',
help='Preprocessing: Brightness Normalization of Hyperspectral data [Optional].',
action="store_true", default=False)
parser.add_argument('--version', action='version', version='%(prog)s 2.0')
args = vars(parser.parse_args())
# data imputps/outputs
#inRaster = 'forestSample3.tif'
inRaster = args["inputRaster"]
outMNF = inRaster[:-4] + "_MNF.tif"
# Normalization?
BrightnessNormalization = args["preprop"]
# load raster
with rasterio.open(inRaster) as r:
meta = r.profile # metadata
img = r.read() # read as numpy array
count = r.count # number of bands
width = r.width
height = r.height
# set number of components to retrive
if args['components'] == 10000:
n_components = count
else:
n_components = args['components']
# apply Brigthness Normalization if needed
if BrightnessNormalization==True:
print('Applying preprocessing...')
img = brightNorm(img)
outMNF = outMNF[:-4]+'_prepro.tif'
print('Done!')
#%%
# Apply NMF
img = np.transpose(img, [1,2,0])
img = img.reshape((width*height, count))
# check for nan and inf
if np.any(np.isinf(img))==True:
img[img == np.inf] = 0
if np.any(np.isnan(img))==True:
img[img == np.nan] = 0
# data whitenen
img=ns.whiten(img)
# PCA
print('Applying NMF transformation...')
pca = IncrementalPCA()
img = pca.fit_transform(img)
print('Done!')
var = np.cumsum(np.round(pca.explained_variance_ratio_, decimals=4)*100)
print("The explained variance per component is:")
print(pca.explained_variance_ratio_)
print("The accumulative explained variance per component is:")
print(var)
# save
np.savetxt(outMNF[:-4]+'_variance.txt', pca.explained_variance_ratio_)
np.savetxt(outMNF[:-4]+'_accVariance.txt', var)
img = img.reshape((height, width, count))
img = np.transpose(img, [2,0,1])
meta.update(count=n_components, dtype='float32')
with rasterio.open(outMNF, "w", **meta) as dst:
dst.write(img[:n_components, :, :])