├── Front_End_GUI.py ├── Hyspeclib ├── HTMLS │ ├── 1.1+Preprocessing.html │ ├── 1.2-Prepapre_data.html │ ├── 1.3.+Band+Reduction+PCA.html │ ├── 1.4.Band+Reduction+using+ANN.html │ ├── 1.5.+ANN_Vs_PCA_Accuracy.html │ ├── 1.6.+Augmentation (1).html │ ├── 1.6.+Augmentation.html │ ├── 1.7.+separability_test.html │ └── 1.8.+DNN_Classification.html ├── __MACOSX │ ├── HTMLS │ │ ├── __1.1+Preprocessing.html │ │ ├── __1.2-Prepapre_data.html │ │ ├── __1.3.+Band+Reduction+PCA.html │ │ ├── __1.4.Band+Reduction+using+ANN.html │ │ ├── __1.5.+ANN_Vs_PCA_Accuracy.html │ │ ├── __1.6.+Augmentation (1).html │ │ ├── __1.6.+Augmentation.html │ │ ├── __1.7.+separability_test.html │ │ └── __1.8.+DNN_Classification.html │ └── hyspeclib │ │ └── __.DS_Store └── hyspeclib │ ├── README │ ├── _DS_Store │ ├── _DS_Store(1) │ ├── __init__.py │ ├── __main__.py │ ├── __pycache__ │ └── __init__.cpython-36.pyc │ ├── _gitignore │ ├── convolutional_network │ ├── _DS_Store │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── cnn_classifier.cpython-36.pyc │ │ └── convolutional_network.cpython-36.pyc │ ├── cnn_classifier.py │ └── convolutional_network.py │ ├── hyperspectral_image │ ├── _DS_Store │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── check_memory.cpython-36.pyc │ │ ├── image.cpython-36.pyc │ │ ├── read_image.cpython-36.pyc │ │ ├── view_classified_image.cpython-36.pyc │ │ └── view_image.cpython-36.pyc │ ├── check_memory.py │ ├── image.py │ ├── read_image.py │ ├── view_classified_image.py │ └── view_image.py │ ├── multilayer_perceptron │ ├── _DS_Store │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ └── multilayer_perceptron.cpython-36.pyc │ ├── dymlp.py │ └── multilayer_perceptron.py │ ├── pca_analysis │ ├── _DS_Store │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ └── pca_analysis.cpython-36.pyc │ └── pca_analysis.py │ ├── prepare_training_data │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ └── prepare_training_data.cpython-36.pyc │ └── prepare_training_data.py │ ├── preprocessing │ ├── _DS_Store │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── fit_in_memory.cpython-36.pyc │ │ ├── noise_removal.cpython-36.pyc │ │ └── preprocessing.cpython-36.pyc │ ├── fit_in_memory.py │ ├── noise_removal.py │ └── preprocessing.py │ ├── separability_analysis │ ├── _DS_Store │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ └── separability_analysis.cpython-36.pyc │ └── separability_analysis.py │ └── setup.py ├── Images ├── pic1.png └── pic2.png ├── Mini Project report.pdf ├── README.md ├── _config.yml ├── open_save.py └── requirements.txt /Front_End_GUI.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | import open_save as osf 3 | from tkinter.simpledialog import askstring, askinteger, askfloat 4 | import numpy as np 5 | import os 6 | from tkinter import * 7 | from tkinter import filedialog 8 | from tkinter import messagebox 9 | from spectral.io.envi import * 10 | import spectral.io.envi as envi 11 | from spectral import imshow 12 | import os 13 | import functools 14 | from Hyspeclib.hyspeclib.preprocessing import noise_removal 15 | 16 | 17 | def quit(): 18 | global top 19 | if messagebox.askyesno("Quit", message="Are you sure you want to quit?") == True: 20 | top.destroy() 21 | 22 | top = Tk() 23 | top.title("HyperImage") 24 | top.geometry("3900x1200") 25 | top.configure(bg="#37474f") 26 | 27 | canvas = Canvas(top, width=3900, height=1200) 28 | canvas.pack() 29 | 30 | # Software name 31 | 32 | widget = Label(canvas, text='HyperImage', fg='white', bg='#37474f', font='Ubuntu 50 bold italic', pady=595).pack() 33 | 34 | 35 | # Creating the navigation bar 36 | 37 | menubar = Menu(canvas) 38 | 39 | filemenu = Menu(menubar, tearoff=0) 40 | filemenu.add_command(label="Open", command=osf.open_file) 41 | filemenu.add_command(label="Save", command=osf.save) 42 | menubar.add_cascade(label="File", menu=filemenu) 43 | 44 | editmenu = Menu(menubar, tearoff=0) 45 | editmenu.add_command(label="Bands", command=osf.open_band) 46 | menubar.add_cascade(label="Edit", menu=editmenu) 47 | 48 | exitmenu = Menu(menubar, tearoff=0) 49 | exitmenu.add_command(label="Quit", command=quit) 50 | menubar.add_cascade(label="Quit", menu=exitmenu) 51 | 52 | top.config(menu=menubar) 53 | 54 | top.mainloop() -------------------------------------------------------------------------------- /Hyspeclib/__MACOSX/HTMLS/__1.1+Preprocessing.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/__MACOSX/HTMLS/__1.1+Preprocessing.html -------------------------------------------------------------------------------- /Hyspeclib/__MACOSX/HTMLS/__1.2-Prepapre_data.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/__MACOSX/HTMLS/__1.2-Prepapre_data.html -------------------------------------------------------------------------------- /Hyspeclib/__MACOSX/HTMLS/__1.3.+Band+Reduction+PCA.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/__MACOSX/HTMLS/__1.3.+Band+Reduction+PCA.html -------------------------------------------------------------------------------- /Hyspeclib/__MACOSX/HTMLS/__1.4.Band+Reduction+using+ANN.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/__MACOSX/HTMLS/__1.4.Band+Reduction+using+ANN.html -------------------------------------------------------------------------------- /Hyspeclib/__MACOSX/HTMLS/__1.5.+ANN_Vs_PCA_Accuracy.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/__MACOSX/HTMLS/__1.5.+ANN_Vs_PCA_Accuracy.html -------------------------------------------------------------------------------- /Hyspeclib/__MACOSX/HTMLS/__1.6.+Augmentation (1).html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/__MACOSX/HTMLS/__1.6.+Augmentation (1).html -------------------------------------------------------------------------------- /Hyspeclib/__MACOSX/HTMLS/__1.6.+Augmentation.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/__MACOSX/HTMLS/__1.6.+Augmentation.html -------------------------------------------------------------------------------- /Hyspeclib/__MACOSX/HTMLS/__1.7.+separability_test.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/__MACOSX/HTMLS/__1.7.+separability_test.html -------------------------------------------------------------------------------- /Hyspeclib/__MACOSX/HTMLS/__1.8.+DNN_Classification.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/__MACOSX/HTMLS/__1.8.+DNN_Classification.html -------------------------------------------------------------------------------- /Hyspeclib/__MACOSX/hyspeclib/__.DS_Store: -------------------------------------------------------------------------------- 1 | Mac OS X 2 F x @ ATTR x x -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/README: -------------------------------------------------------------------------------- 1 | This is README for hyspeclib -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/_DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/_DS_Store -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/_DS_Store(1): -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/_DS_Store(1) -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | 4 | from .prepare_training_data import prepare_training_data 5 | from .hyperspectral_image import read_image 6 | from .hyperspectral_image import check_memory 7 | from .hyperspectral_image import view_image 8 | from .hyperspectral_image import view_classified_image 9 | from .preprocessing import noise_removal 10 | from .preprocessing import preprocessing 11 | from .pca_analysis import pca_analysis 12 | from .multilayer_perceptron import multilayer_perceptron 13 | from .separability_analysis import separability_analysis 14 | from .convolutional_network import convolutional_network 15 | from .convolutional_network import cnn_classifier 16 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | 4 | import tests 5 | 6 | tests.run_all() 7 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/_gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | 3 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/convolutional_network/_DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/convolutional_network/_DS_Store -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/convolutional_network/__init__.py: -------------------------------------------------------------------------------- 1 | from .convolutional_network import convolutional_network 2 | from .cnn_classifier import cnn_classifier -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/convolutional_network/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/convolutional_network/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/convolutional_network/__pycache__/cnn_classifier.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/convolutional_network/__pycache__/cnn_classifier.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/convolutional_network/__pycache__/convolutional_network.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/convolutional_network/__pycache__/convolutional_network.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/convolutional_network/cnn_classifier.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import random as ran 4 | import matplotlib.pyplot as plt 5 | import sys 6 | import tensorflow as tf 7 | from sklearn.model_selection import train_test_split as ttspilt 8 | 9 | 10 | class cnn_classifier: 11 | 12 | def __init__(self, n_classes = 5, available_memory_gb=2, learning_rate=0.01, batch_size=32, n_iter=50): 13 | 14 | # Parameters 15 | self._batch_size = batch_size 16 | 17 | # Network Parameters 18 | self._n_input = 40 19 | self._n_classes = n_classes 20 | self._dropout = 0.5 21 | self._learning_rate = learning_rate 22 | 23 | self._x = tf.placeholder(dtype=np.float32, shape=(None, self._n_input), name='Batch_Input_Tensor') 24 | self._y = tf.placeholder(dtype=np.float32, shape=(None, self._n_classes), name='Batch_Prediction') 25 | self._keep_prob = tf.placeholder(dtype=np.float32, name='Dropout') #dropout (keep probability) 26 | 27 | self._weights = { 28 | # 1x3 conv, 1 input, 6 outputs 29 | #[filter_width, in_channels, out_channels], 30 | #40 - 2 = 38 / 2 = 19 31 | 'wc1': tf.Variable(tf.random_normal([3, 1, 6])), 32 | 33 | #19 - 3 = 16 / 2 = 8 34 | 'wc2': tf.Variable(tf.random_normal([4, 6, 12])), 35 | 36 | #8 - 2 = 6 37 | 'wc3': tf.Variable(tf.random_normal([3, 12, 24])), 38 | 39 | 40 | # fully connected, 6*24 inputs, 72 outputs 41 | 'wd1': tf.Variable(tf.random_normal([144, 100])), 42 | 43 | # 256 inputs, 8 outputs (class prediction) 44 | 'out': tf.Variable(tf.random_normal([100, n_classes])) 45 | 46 | } 47 | 48 | self._biases = { 49 | 'bc1': tf.Variable(tf.random_normal([6])), 50 | 'bc2': tf.Variable(tf.random_normal([12])), 51 | 'bc3': tf.Variable(tf.random_normal([24])), 52 | 'bd1': tf.Variable(tf.random_normal([100])), 53 | 'out': tf.Variable(tf.random_normal([n_classes])) 54 | } 55 | 56 | print('\n------- Parameters intialised. Check your model -------\n') 57 | 58 | self._build() 59 | 60 | # Create model 61 | def _conv1d(self,img, w, b, name): 62 | return tf.nn.relu(tf.nn.bias_add(tf.nn.conv1d(img, w,stride=1, 63 | padding='VALID'),b),name=name) 64 | 65 | def _max_pool(self,img, k, name, width, out_channel): 66 | #strides = [batch, height, width, channels]. 67 | #value: A 4-D `Tensor` with shape `[batch, height, width, channels]` and type `tf.float32`. 68 | 69 | #Adding additional dimention for max pooling 70 | img = tf.reshape(img, shape=[-1,1,width, out_channel]) 71 | 72 | return tf.squeeze(tf.nn.avg_pool(img, ksize=[1, 1, 2, 1], strides=[1, 1, 2,1], padding='SAME',name=name),[1]) 73 | 74 | def _conv_net(self,_X, _weights, _biases, _dropout , test=False, printme=False): 75 | 76 | #[batch, in_width, in_channels] 77 | _X = tf.reshape(_X, shape=(-1,self._n_input,1),name='Input') 78 | if printme == True: 79 | print(_X) 80 | 81 | # Convolution Layer 82 | conv1 = self._conv1d(_X, _weights['wc1'], _biases['bc1'],name='C1') 83 | if printme == True: 84 | print(conv1) 85 | # Max Pooling (down-sampling) 86 | conv1 = self._max_pool(conv1, k=2,name='M2', width=conv1.shape.as_list()[1], out_channel=_weights['wc1'].get_shape().as_list()[2]) 87 | if printme == True: 88 | print(conv1) 89 | 90 | 91 | # Convolution Layer 92 | conv2 = self._conv1d(conv1, _weights['wc2'], _biases['bc2'], name='C3') 93 | if printme == True: 94 | print(conv2) 95 | # Max Pooling (down-sampling) 96 | conv2 = self._max_pool(conv2, k=2,name='M4', width=conv2.shape.as_list()[1], out_channel=_weights['wc2'].get_shape().as_list()[2]) 97 | if printme == True: 98 | print(conv2) 99 | 100 | 101 | # Convolution Layer 102 | conv3 = self._conv1d(conv2, _weights['wc3'], _biases['bc3'], name='C5') 103 | if printme == True: 104 | print(conv3) 105 | # Max Pooling (down-sampling) 106 | #conv3 = max_pool(conv3, k=2,name='M6', width=conv3.shape.as_list()[1], out_channel=_weights['wc3'].get_shape().as_list()[2]) 107 | #print(conv3) 108 | 109 | # Fully connected layer 110 | # Reshape conv2 output to fit dense layer input 111 | dense1 = tf.reshape(conv3, [-1, _weights['wd1'].get_shape().as_list()[0]]) 112 | # Relu activation 113 | dense1 = tf.nn.relu(tf.add(tf.matmul(dense1, _weights['wd1']), _biases['bd1']),name='FC10') 114 | if printme == True: 115 | print(dense1) 116 | # Apply Dropout 117 | if test == False: 118 | dense1 = tf.nn.dropout(dense1, _dropout) # Apply Dropout 119 | 120 | # Output, class prediction 121 | out = tf.add(tf.matmul(dense1, _weights['out']), _biases['out'], name='Out') 122 | if printme == True: 123 | print(out) 124 | return out 125 | 126 | def _build(self): 127 | print('\n ----------- Architecture of CNN ----------- \n') 128 | self._pred = self._conv_net(self._x, self._weights, self._biases, self._dropout,test=False,printme=True) 129 | self._pred_test = self._conv_net(self._x, self._weights, self._biases, self._dropout, test=True) 130 | self._probability = 1+tf.nn.elu(features=self._pred_test,name='elu') 131 | 132 | 133 | # Define loss and optimizer 134 | self._cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=self._pred, labels=self._y)) 135 | self._optimizer = tf.train.AdamOptimizer(learning_rate=self._learning_rate).minimize(self._cost) 136 | 137 | # Evaluate model 138 | self._correct_pred = tf.equal(tf.argmax(self._pred_test,1), tf.argmax(self._y,1)) 139 | self._accuracy = tf.reduce_mean(tf.cast(self._correct_pred, np.float32)) 140 | self._conf_mat= tf.confusion_matrix(tf.argmax(self._pred,1),tf.argmax(self._y,1)) 141 | 142 | 143 | self._init = tf.global_variables_initializer() 144 | self._saver = tf.train.Saver() 145 | 146 | def train_testing_data(self,training_data_path,class_labels,test_size = 0.2,titles=[]): 147 | cols = list([str(i) for i in range(392)]) 148 | cols.append('label') 149 | 150 | all_data = pd.read_csv(training_data_path,names=cols) 151 | self._class_labels = class_labels 152 | dataset = all_data.loc[all_data['label'].isin(class_labels)] 153 | data_array = np.asarray(dataset) 154 | self._data_set_array, self._test_data_set_array= ttspilt(data_array,test_size=test_size, random_state=10) 155 | self._short_classes = titles 156 | 157 | #preparing testing dataset 158 | 159 | def _randomize_test_data(self,reduced_bands=False,selected=[]): 160 | 161 | cols = list([str(i) for i in range(392)]) 162 | cols.append('label') 163 | 164 | data = self._test_data_set_array 165 | class_num = self._n_classes 166 | 167 | np.random.shuffle(data) 168 | test_labels = np.asarray(pd.DataFrame(data,columns=cols)['label']) 169 | test_one_hot_vectors = np.zeros(shape=(len(data),class_num),dtype=np.float32) 170 | test_instances = np.asarray(pd.DataFrame(data,columns=cols).drop(labels=['label'],axis=1),dtype=np.float32) 171 | 172 | for count in range(len(test_labels)): 173 | test_one_hot_vectors[count][ self._class_labels.index(test_labels[count]) ] = 1.0 174 | 175 | if reduced_bands == True: 176 | test_instances = test_instances[:,selected] 177 | 178 | 179 | return test_instances, test_one_hot_vectors 180 | 181 | 182 | def _train_validation_split(self,train=0.7,reduced_bands = False,selected=[]): 183 | """ K fold cross validation data function """ 184 | 185 | cols = list([str(i) for i in range(392)]) 186 | cols.append('label') 187 | 188 | data_set_array = self._data_set_array 189 | np.random.shuffle(data_set_array) 190 | 191 | #training and validation_set 192 | training_data_set = data_set_array[ 0 : int(train*len(data_set_array)) ] 193 | validation_data_set = data_set_array[ int(train*len(data_set_array)) : len(data_set_array) ] 194 | 195 | # validation inputs 196 | validation_labels = np.asarray(pd.DataFrame(validation_data_set,columns=cols)['label']) 197 | validation_one_hot_vectors = np.zeros(shape=(len(validation_data_set),self._n_classes),dtype=np.float32) 198 | validation_instances = np.asarray(pd.DataFrame(validation_data_set,columns=cols).drop(labels=['label'],axis=1),dtype=np.float32) 199 | 200 | # training inputs 201 | train_labels = np.asarray(pd.DataFrame(training_data_set,columns=cols)['label']) 202 | train_one_hot_vectors = np.zeros(shape=(len(training_data_set),self._n_classes),dtype=np.float32) 203 | train_instances = np.asarray(pd.DataFrame(training_data_set,columns=cols).drop(labels=['label'],axis=1),dtype=np.float32) 204 | 205 | #generating one hot vectors 206 | for count in range(len(validation_labels)): 207 | validation_one_hot_vectors[count][ self._class_labels.index( validation_labels[count] ) ] = 1.0 208 | 209 | for count in range(len(train_labels)): 210 | train_one_hot_vectors[count][ self._class_labels.index( train_labels[count] ) ] = 1.0 211 | 212 | 213 | if reduced_bands == True: 214 | train_instances = train_instances[:,selected] 215 | validation_instances = validation_instances[:,selected] 216 | 217 | 218 | return train_instances, train_one_hot_vectors, validation_instances, validation_one_hot_vectors 219 | 220 | 221 | def train_model(self,best_model_path,iterations = 10,lr = 0.01,reduced_bands=False,selected=[],log=False): 222 | 223 | list_avg_training_accuracy = [] 224 | list_avg_validation_accuracy = [] 225 | 226 | for iters in range(iterations): 227 | 228 | 229 | highest_validation_accuracy = 0.0 230 | 231 | 232 | with tf.Session() as sess: 233 | sess.run(self._init) 234 | 235 | # Training cycle 236 | kfold_training_accuracy = 0.0 237 | kfold_validation_accuracy = 0.0 238 | 239 | old_validation_accuracy = 0.0 240 | 241 | # Loop over all batches 10 times 242 | for count in range(10): 243 | avg_cost = 0. 244 | 245 | new_train_instances, new_train_one_hot_vectors, new_validation_instances, new_validation_one_hot_vectors = self._train_validation_split(train=0.7,reduced_bands=True,selected=selected) 246 | 247 | 248 | total_batch = int(len(new_train_instances)/self._batch_size) 249 | 250 | 251 | for i in range(total_batch): 252 | batch_xs = new_train_instances[i*self._batch_size:(i+1)*self._batch_size] 253 | batch_ys = new_train_one_hot_vectors[i*self._batch_size:(i+1)*self._batch_size] 254 | # Fit training using batch data 255 | sess.run(self._optimizer, feed_dict={self._x: batch_xs, self._y: batch_ys}) 256 | 257 | 258 | # Calculate batch accuracy 259 | acc = sess.run(self._accuracy, feed_dict={self._x: batch_xs, self._y: batch_ys}) 260 | 261 | # Calculate batch loss 262 | loss = sess.run(self._cost, feed_dict={self._x: batch_xs, self._y: batch_ys}) 263 | 264 | 265 | # Calculate validation accuracy 266 | vec = sess.run(self._accuracy, feed_dict={self._x: new_validation_instances, 267 | self._y: new_validation_one_hot_vectors }) 268 | 269 | kfold_training_accuracy += acc 270 | kfold_validation_accuracy += vec 271 | 272 | 273 | if log == True: 274 | print ("Epoch:", '%04d' % (count+1) ,", Minibatch Loss= " + \ 275 | "{:.6f}".format(loss) + ", Training Accuracy= " + "{:.5f}".format(acc)) 276 | 277 | print ('Epoch :','%04d' %(count+1)," Validation Accuracy:", vec,'\n') 278 | 279 | #if np.abs(old_validation_accuracy-vec) < 0.000000001: 280 | # break 281 | #else: 282 | # old_validation_accuracy = vec 283 | old_validation_accuracy = vec 284 | 285 | avg_traing_acc = kfold_training_accuracy/10 286 | avg_validation_acc = kfold_validation_accuracy/10 287 | 288 | 289 | if old_validation_accuracy >= highest_validation_accuracy: 290 | highest_validation_accuracy = old_validation_accuracy 291 | self._saver.save(sess, best_model_path) 292 | 293 | 294 | list_avg_training_accuracy.append(avg_traing_acc) 295 | list_avg_validation_accuracy.append(avg_validation_acc) 296 | 297 | print("Run no. : {} | Training_acc. : {:.4f} | Validation acc. : {:.4f} | Highest val. acc. : {:.4f} ".format(iters+1,avg_traing_acc,avg_validation_acc,highest_validation_accuracy)) 298 | 299 | print('\nTraining is completed, best model is saved at: ',best_model_path) 300 | 301 | print('\n Overall training acc : {:.4f} | Overall validation acc : {:.4f}'.format(np.mean(list_avg_training_accuracy),np.mean(list_avg_validation_accuracy))) 302 | 303 | print('\n\n-------------------------------------------------------\n\n') 304 | 305 | 306 | def _kappa_evaluation(self,confusion_mat): 307 | 308 | N = np.sum(confusion_mat) 309 | nrows = confusion_mat.shape[0] 310 | nominator = 0 311 | denominator = 0 312 | for row in range(nrows): 313 | x = np.sum(confusion_mat[row])*np.sum(confusion_mat[:,row]) 314 | nominator += N * confusion_mat[row][row] - x 315 | denominator += x 316 | 317 | return nominator / (N*N - denominator) 318 | 319 | def training_validation(self,path,reduced_bands=False, selected=[]): 320 | """ Constructs confusion matrix by trained model for training sample""" 321 | 322 | short_classes = self._short_classes 323 | 324 | try: 325 | with tf.Session() as sess: 326 | self._saver.restore(sess,path) 327 | 328 | new_train_instances, new_train_one_hot_vectors, _, _ = self._train_validation_split(train=0.7,reduced_bands=reduced_bands,selected=selected) 329 | 330 | 331 | training_accuracy = sess.run(self._accuracy, feed_dict={self._x: new_train_instances, self._y: new_train_one_hot_vectors }) 332 | 333 | confusion_matrix = sess.run(self._conf_mat, feed_dict={self._x: new_train_instances, self._y: new_train_one_hot_vectors }) 334 | 335 | total_sample = [np.sum(confusion_matrix,axis=0)] 336 | 337 | 338 | print('\n----------Training site validation of model {}----------\n'.format(path.split('/')[-1])) 339 | 340 | print('Total training samples\n') 341 | #print(total_sample) 342 | print(pd.DataFrame(total_sample,columns=short_classes,index=['Total samples'])) 343 | 344 | print("\n1. Overall accuracy : {:.4f}\n".format(training_accuracy)) 345 | 346 | print('2. Confusion matrix: columns are prediction labels and the rows are the GT data\n') 347 | 348 | print(pd.DataFrame(confusion_matrix,columns=short_classes,index=short_classes)) 349 | 350 | class_wise_acc = list() 351 | 352 | for i in range(len(confusion_matrix)): 353 | producer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[:,i]),decimals=3) 354 | consumer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[i]),decimals=3) 355 | 356 | class_wise_acc.append([producer_acc,consumer_acc]) 357 | 358 | print('\n3. Producer accuracy and Consumer accuracy:\n') 359 | 360 | print(pd.DataFrame(class_wise_acc,columns=(['Producer/Class acc','Consumer acc']),index=short_classes)) 361 | 362 | print('\n4. Average accuracy : {:.4f}'.format(np.sum(np.array(class_wise_acc),axis=0)[0]/len(class_wise_acc))) 363 | try: 364 | print('\n5. Kapp cofficient : {:.4f}\n'.format( self._kappa_evaluation(confusion_matrix))) 365 | except: 366 | print('\n5. Kapp cofficient : undefined') 367 | except: 368 | print('Error : Please close any existing Tensorflow session and try again or restart Python Kernel') 369 | 370 | def blindsite_validation(self,path,reduced_bands=False, selected=[]): 371 | """ Constructs confusion matrix by trained model for blind sample""" 372 | 373 | short_classes = self._short_classes 374 | 375 | 376 | try: 377 | with tf.Session() as sess: 378 | self._saver.restore(sess,path) 379 | 380 | new_test_instances, new_test_one_hot_vectors = self._randomize_test_data(reduced_bands=reduced_bands,selected=selected) 381 | 382 | 383 | testing_accuracy = sess.run(self._accuracy, feed_dict={self._x: new_test_instances, self._y: new_test_one_hot_vectors }) 384 | 385 | confusion_matrix = sess.run(self._conf_mat, feed_dict={self._x: new_test_instances, self._y: new_test_one_hot_vectors }) 386 | 387 | total_sample = [np.sum(confusion_matrix,axis=0)] 388 | 389 | 390 | print('\n----------Blind site validation of model {}----------\n'.format(path.split('/')[-1])) 391 | 392 | print('Total blind site samples\n') 393 | print(pd.DataFrame(total_sample,columns=short_classes,index=['Total samples'])) 394 | 395 | print("\n1. Overall accuracy : {:.4f}\n".format(testing_accuracy)) 396 | 397 | print('2. Confusion matrix: columns are prediction labels and the rows are the GT data\n') 398 | 399 | print(pd.DataFrame(confusion_matrix,columns=short_classes,index=short_classes)) 400 | 401 | class_wise_acc = list() 402 | 403 | for i in range(len(confusion_matrix)): 404 | producer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[:,i]),decimals=3) 405 | consumer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[i]),decimals=3) 406 | 407 | class_wise_acc.append([producer_acc,consumer_acc]) 408 | 409 | print('\n3. Producer accuracy and Consumer accuracy:\n') 410 | 411 | print(pd.DataFrame(class_wise_acc,columns=(['Producer/Class acc','Consumer acc']),index=short_classes)) 412 | 413 | print('\n4. Average accuracy : {:.4f}'.format(np.sum(np.array(class_wise_acc),axis=0)[0]/len(class_wise_acc))) 414 | try: 415 | print('\n5. Kapp cofficient : {:.4f}\n'.format( self._kappa_evaluation(confusion_matrix))) 416 | except: 417 | print('\n5. Kapp cofficient : undefined') 418 | except: 419 | print('Error : Please close any existing Tensorflow session and try again or restart Python Kernel') 420 | 421 | def _combined_prediction(self,list_of_models,array_of_input,class_labels): 422 | 423 | list_of_model_predctions = list() 424 | 425 | combined_predictions = list() 426 | 427 | for index,model in enumerate(list_of_models): 428 | 429 | print(index+1, "\nModel Running ...\n") 430 | 431 | with tf.Session() as sess: 432 | self._saver.restore(sess,model) 433 | 434 | class_probabilities = sess.run(self._probability , feed_dict={self._x:array_of_input}) 435 | 436 | list_of_model_predctions.append(class_probabilities) 437 | 438 | list_of_model_predctions = np.array(list_of_model_predctions) 439 | 440 | for i in range(len(array_of_input)): 441 | combined_predictions.append(class_labels[np.argmax(list_of_model_predctions[:,i])]) 442 | 443 | def test_combined_acc(self,data_path,list_of_models,class_labels,titles): 444 | 445 | cols = list([str(i) for i in range(392)]) 446 | 447 | cols.append('label') 448 | 449 | data = pd.read_csv(data_path,names=cols) 450 | 451 | data_array = np.array(data.drop(['label'],axis=1)) 452 | 453 | y_actu = pd.Series(data.label,name='Actual') 454 | 455 | combined_preds = self._combined_prediction(list_of_models, data_array,class_labels) 456 | 457 | y_pred = pd.Series(combined_preds, name='Predicted') 458 | 459 | df_confusion = pd.crosstab(y_actu, y_pred) 460 | 461 | print(df_confusion) 462 | 463 | 464 | 465 | 466 | 467 | 468 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/convolutional_network/convolutional_network.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | import pandas as pd 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | from ..hyperspectral_image import read_image 6 | from ..preprocessing import _fit_in_memory 7 | from sklearn.model_selection import train_test_split as ttspilt 8 | 9 | 10 | class convolutional_network: 11 | 12 | def __init__(self, n_classes = 5 ,available_memory_gb=2,learning_rate=0.01,batch_size=32,n_iter=50): 13 | # Network Parameters 14 | 15 | self._max = available_memory_gb 16 | self._learning_rate = learning_rate 17 | self._dropout=0.1 18 | self._n_input = 80 # Number of Inputs here number of bands 19 | self._n_classes = n_classes # Classes in training Set 20 | self._batch_size = batch_size 21 | self._num_iteration = n_iter 22 | 23 | # tf Graph input 24 | self._x = tf.placeholder("float", [None, self._n_input],name='inputs') 25 | self._y = tf.placeholder("float", [None, self._n_classes],name='outputs') 26 | 27 | self._weights = { 28 | # 1x3 conv, 1 input, 6 outputs 29 | #[filter_width, in_channels, out_channels], 30 | #80 - 4 = 76 / 2 = 38 31 | 'wc1': tf.Variable(tf.random_normal([5, 1, 6])), 32 | 33 | #not 39 - 3 = 36 / 2 = 18 34 | #38 - 4 = 34 35 | 'wc2': tf.Variable(tf.random_normal([5, 6, 12])), 36 | 37 | #34 - 4 = 31 38 | 'wc3': tf.Variable(tf.random_normal([5, 12, 24])), 39 | 40 | 41 | # fully connected, 30*24 inputs=384, 256 outputs 42 | 'wd1': tf.Variable(tf.random_normal([720, 100])), 43 | 44 | # 256 inputs, 8 outputs (class prediction) 45 | 'out': tf.Variable(tf.random_normal([100, self._n_classes])) 46 | 47 | } 48 | 49 | self._biases = { 50 | 'bc1': tf.Variable(tf.random_normal([6])), 51 | 'bc2': tf.Variable(tf.random_normal([12])), 52 | 'bc3': tf.Variable(tf.random_normal([24])), 53 | 'bd1': tf.Variable(tf.random_normal([100])), 54 | 'out': tf.Variable(tf.random_normal([self._n_classes])) 55 | } 56 | 57 | print('\n------- Parameters intialised. Check your model -------\n') 58 | 59 | self._build_model() 60 | 61 | def _conv1d(self,img, w, b, name): 62 | 63 | return tf.nn.relu(tf.nn.bias_add(tf.nn.conv1d(img, w,stride=1, padding='VALID'),b),name=name) 64 | 65 | def _max_pool(self,img, k, name, width, out_channel): 66 | #strides = [batch, height, width, channels]. 67 | #value: A 4-D `Tensor` with shape `[batch, height, width, channels]` and type `tf.float32`. 68 | 69 | #Adding additional dimention for max pooling 70 | img = tf.reshape(img, shape=[-1,1,width, out_channel]) 71 | 72 | return tf.squeeze(tf.nn.avg_pool(img, ksize=[1, 1, 2, 1], strides=[1, 1, 2,1], padding='SAME',name=name),[1]) 73 | 74 | def _conv_net(self,_X, _weights, _biases, _dropout , test=False): 75 | # Reshape input picture 76 | #print('Here',_X) 77 | #[batch, in_width, in_channels] 78 | _X = tf.reshape(_X, shape=(-1,self._n_input,1),name='Input') 79 | print(_X) 80 | 81 | # Convolution Layer 82 | conv1 = self._conv1d(_X, _weights['wc1'], _biases['bc1'],name='C1') 83 | print(conv1) 84 | # Max Pooling (down-sampling) 85 | conv1 = self._max_pool(conv1, k=2,name='M2', width=conv1.shape.as_list()[1], out_channel=_weights['wc1'].get_shape().as_list()[2]) 86 | print(conv1) 87 | 88 | 89 | # Convolution Layer 90 | conv2 = self._conv1d(conv1, _weights['wc2'], _biases['bc2'], name='C3') 91 | print(conv2) 92 | # Max Pooling (down-sampling) 93 | #conv2 = self._max_pool(conv2, k=2,name='M4', width=conv2.shape.as_list()[1], out_channel=_weights['wc2'].get_shape().as_list()[2]) 94 | #print(conv2) 95 | 96 | 97 | # Convolution Layer 98 | conv3 = self._conv1d(conv2, _weights['wc3'], _biases['bc3'], name='C5') 99 | print(conv3) 100 | # Max Pooling (down-sampling) 101 | #conv3 = max_pool(conv3, k=2,name='M6', width=conv3.shape.as_list()[1], out_channel=_weights['wc3'].get_shape().as_list()[2]) 102 | #print(conv3) 103 | 104 | 105 | # Fully connected layer 106 | # Reshape conv2 output to fit dense layer input 107 | dense1 = tf.reshape(conv3, [-1, _weights['wd1'].get_shape().as_list()[0]]) 108 | # Relu activation 109 | dense1 = tf.nn.relu(tf.add(tf.matmul(dense1, _weights['wd1']), _biases['bd1']),name='FC10') 110 | print(dense1) 111 | # Apply Dropout 112 | if test == False: 113 | dense1 = tf.nn.dropout(dense1, _dropout) # Apply Dropout 114 | 115 | # Output, class prediction 116 | out = tf.add(tf.matmul(dense1, _weights['out']), _biases['out'], name='Out') 117 | print(out) 118 | return out 119 | 120 | def _build_model(self): 121 | 122 | # Construct model 123 | self._pred = self._conv_net(self._x, self._weights, self._biases, self._dropout) 124 | #self._pred_test = self._conv_net(self._x, self._weights, self._biases, self._dropout,test=True) 125 | self._probability = 1+tf.nn.elu(features=self._pred,name='elu') 126 | # Define loss and optimizer 127 | 128 | 129 | # Softmax loss 130 | self._cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=self._pred, labels=self._y)) 131 | # Adam Optimizer 132 | self._optimizer = tf.train.AdamOptimizer(learning_rate=self._learning_rate).minimize(self._cost) 133 | 134 | # Evaluate model 135 | self._correct_pred = tf.equal(tf.argmax(self._pred,1), tf.argmax(self._y,1)) 136 | self._accuracy = tf.reduce_mean(tf.cast(self._correct_pred, np.float32)) 137 | self._conf_mat= tf.confusion_matrix(tf.argmax(self._pred,1),tf.argmax(self._y,1)) 138 | 139 | 140 | self._init = tf.global_variables_initializer() 141 | self._saver = tf.train.Saver() 142 | 143 | def train_testing_data(self,dataset_path,class_labels,titles,test_size=0.10): 144 | 145 | all_data = pd.read_csv(dataset_path,header=None) 146 | self._class_labels = class_labels 147 | self._total_bands = all_data.shape[1]-1 148 | self._dataset = all_data.loc[all_data[self._total_bands].isin(class_labels)] 149 | print(self._dataset[self._total_bands].unique()) 150 | self._data_array = np.asarray(self._dataset) 151 | self._data_set_array, self._test_data_set_array= ttspilt(self._data_array,test_size=test_size, random_state=10) 152 | self._short_classes = titles 153 | self._n_classes = self._n_classes 154 | 155 | 156 | def _train_validation_split(self,train=0.7,reduced_bands=False,selected=[]): 157 | """ K fold cross validation data function """ 158 | 159 | cols = list([str(i) for i in range(self._total_bands)]) 160 | cols.append('label') 161 | 162 | np.random.shuffle( self._data_set_array) 163 | 164 | #training and validation_set 165 | training_data_set = self._data_set_array[ 0 : int(train*len( self._data_set_array)) ] 166 | validation_data_set = self._data_set_array[ int(train*len( self._data_set_array)) : len( self._data_set_array) ] 167 | 168 | # validation inputs 169 | validation_labels = np.asarray(pd.DataFrame(validation_data_set,columns=cols)['label']) 170 | validation_one_hot_vectors = np.zeros(shape=(len(validation_data_set),self._n_classes),dtype=np.float32) 171 | validation_instances = np.asarray(pd.DataFrame(validation_data_set,columns=cols).drop(labels=['label'],axis=1),dtype=np.float32) 172 | 173 | # training inputs 174 | train_labels = np.asarray(pd.DataFrame(training_data_set,columns=cols)['label']) 175 | train_one_hot_vectors = np.zeros(shape=(len(training_data_set),self._n_classes),dtype=np.float32) 176 | train_instances = np.asarray(pd.DataFrame(training_data_set,columns=cols).drop(labels=['label'],axis=1),dtype=np.float32) 177 | 178 | #generating one hot vectors 179 | for count in range(len(validation_labels)): 180 | validation_one_hot_vectors[count][ self._class_labels.index( validation_labels[count] ) ] = 1.0 181 | 182 | 183 | for count in range(len(train_labels)): 184 | train_one_hot_vectors[count][ self._class_labels.index( train_labels[count] ) ] = 1.0 185 | 186 | 187 | if reduced_bands == True: 188 | train_instances = train_instances[:,selected] 189 | validation_instances = validation_instances[:,selected] 190 | 191 | 192 | return train_instances, train_one_hot_vectors, validation_instances, validation_one_hot_vectors 193 | 194 | #preparing testing dataset 195 | 196 | def _randomize_test_data(self,reduced_bands=False,selected=[]): 197 | 198 | cols = list([str(i) for i in range(self._total_bands)]) 199 | cols.append('label') 200 | 201 | data = self._test_data_set_array 202 | class_num = self._n_classes 203 | 204 | np.random.shuffle(data) 205 | test_labels = np.asarray(pd.DataFrame(data,columns=cols)['label']) 206 | test_one_hot_vectors = np.zeros(shape=(len(data),class_num),dtype=np.float32) 207 | test_instances = np.asarray(pd.DataFrame(data,columns=cols).drop(labels=['label'],axis=1),dtype=np.float32) 208 | 209 | for count in range(len(test_labels)): 210 | test_one_hot_vectors[count][ self._class_labels.index(test_labels[count]) ] = 1.0 211 | 212 | if reduced_bands == True: 213 | test_instances = test_instances[:,selected] 214 | 215 | 216 | return test_instances, test_one_hot_vectors 217 | 218 | 219 | def train_model(self,best_model_path,selected,iterations = 10,lr = 0.01,early_stopping=False,log=False): 220 | 221 | list_avg_training_accuracy = [] 222 | list_avg_validation_accuracy = [] 223 | 224 | if len(selected) !=self._n_input: 225 | print('Only 80 Bands should be given as input but {} are given'.format(len(selected))) 226 | return 227 | 228 | print('\n\n--------------Training CNN------------------\n\n') 229 | for iteration in range(iterations): 230 | 231 | highest_validation_accuracy = 0.0 232 | 233 | with tf.Session() as sess: 234 | sess.run(self._init) 235 | 236 | # Training cycle 237 | kfold_training_accuracy = 0.0 238 | kfold_validation_accuracy = 0.0 239 | 240 | old_validation_accuracy = 0.0 241 | 242 | # Loop over all batches 10 times 243 | for count in range(10): 244 | avg_cost = 0. 245 | 246 | new_train_instances, new_train_one_hot_vectors, new_validation_instances, new_validation_one_hot_vectors = self._train_validation_split(train=0.7,reduced_bands=True,selected=selected) 247 | 248 | 249 | total_batch = int(len(new_train_instances)/self._batch_size) 250 | 251 | 252 | for i in range(total_batch): 253 | batch_xs = new_train_instances[i*self._batch_size:(i+1)*self._batch_size] 254 | batch_ys = new_train_one_hot_vectors[i*self._batch_size:(i+1)*self._batch_size] 255 | # Fit training using batch data 256 | sess.run(self._optimizer, feed_dict={self._x: batch_xs, self._y: batch_ys}) 257 | 258 | # Calculate batch accuracy 259 | 260 | acc = sess.run(self._accuracy, feed_dict={self._x: batch_xs, self._y: batch_ys}) 261 | 262 | # Calculate batch loss 263 | loss = sess.run(self._cost, feed_dict={self._x: batch_xs, self._y: batch_ys}) 264 | 265 | 266 | # Calculate validation accuracy 267 | vec = sess.run(self._accuracy, feed_dict={self._x: new_validation_instances, 268 | self._y: new_validation_one_hot_vectors }) 269 | 270 | kfold_training_accuracy += acc 271 | kfold_validation_accuracy += vec 272 | 273 | 274 | if log == True: 275 | print ("Epoch:", '%04d' % (count+1) ,", Minibatch Loss= " + \ 276 | "{:.6f}".format(loss) + ", Training Accuracy= " + "{:.5f}".format(acc)) 277 | 278 | print ('Epoch :','%04d' %(count+1)," Validation Accuracy:", vec,'\n') 279 | 280 | 281 | old_validation_accuracy = vec 282 | 283 | avg_traing_acc = kfold_training_accuracy/10 284 | avg_validation_acc = kfold_validation_accuracy/10 285 | 286 | if old_validation_accuracy >= highest_validation_accuracy: 287 | highest_validation_accuracy = old_validation_accuracy 288 | self._saver.save(sess, best_model_path) 289 | #print('Saving....') 290 | 291 | list_avg_training_accuracy.append(avg_traing_acc) 292 | list_avg_validation_accuracy.append(avg_validation_acc) 293 | 294 | print('Step : {} - Avg Train Acc. {:.4f} | Avg Validation Acc. {:.4f} | Highest Val Acc. {:.4f}'.format(iteration+1, avg_traing_acc, avg_validation_acc,highest_validation_accuracy)) 295 | 296 | 297 | print('\nTraining is completed, best model is saved at: ',best_model_path) 298 | print('\n\n-------------------------------------------------------\n\n') 299 | 300 | return {'Overall training acc : ' : np.mean(list_avg_training_accuracy),'Overall validation acc : ' : np.mean(list_avg_validation_accuracy)} 301 | 302 | def _kappa_evaluation(self,confusion_mat): 303 | 304 | N = np.sum(confusion_mat) 305 | nrows = confusion_mat.shape[0] 306 | nominator = 0 307 | denominator = 0 308 | for row in range(nrows): 309 | x = np.sum(confusion_mat[row])*np.sum(confusion_mat[:,row]) 310 | nominator += N * confusion_mat[row][row] - x 311 | denominator += x 312 | 313 | return nominator / (N*N - denominator) 314 | 315 | def training_validation(self,path,reduced_bands=False, selected=[]): 316 | """ Constructs confusion matrix by trained model for training sample""" 317 | 318 | short_classes = self._short_classes 319 | 320 | try: 321 | with tf.Session() as sess: 322 | self._saver.restore(sess,path) 323 | 324 | new_train_instances, new_train_one_hot_vectors, _, _ = self._train_validation_split(train=0.7,reduced_bands=reduced_bands,selected=selected) 325 | 326 | 327 | training_accuracy = sess.run(self._accuracy, feed_dict={self._x: new_train_instances, self._y: new_train_one_hot_vectors }) 328 | 329 | confusion_matrix = sess.run(self._conf_mat, feed_dict={self._x: new_train_instances, self._y: new_train_one_hot_vectors }) 330 | 331 | total_sample = [np.sum(confusion_matrix,axis=0)] 332 | 333 | 334 | print('\n----------Training site validation of model {}----------\n'.format(path.split('/')[-1])) 335 | 336 | print('Total training samples\n') 337 | #print(total_sample) 338 | print(pd.DataFrame(total_sample,columns=short_classes,index=['Total samples'])) 339 | 340 | print("\n1. Overall accuracy : {:.4f}\n".format(training_accuracy)) 341 | 342 | print('2. Confusion matrix: columns are prediction labels and the rows are the GT data\n') 343 | 344 | print(pd.DataFrame(confusion_matrix,columns=short_classes,index=short_classes)) 345 | 346 | class_wise_acc = list() 347 | 348 | for i in range(len(confusion_matrix)): 349 | producer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[:,i]),decimals=3) 350 | consumer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[i]),decimals=3) 351 | 352 | class_wise_acc.append([producer_acc,consumer_acc]) 353 | 354 | print('\n3. Producer accuracy and Consumer accuracy:\n') 355 | 356 | print(pd.DataFrame(class_wise_acc,columns=(['Producer/Class acc','Consumer acc']),index=short_classes)) 357 | 358 | print('\n4. Average accuracy : {:.4f}'.format(np.sum(np.array(class_wise_acc),axis=0)[0]/len(class_wise_acc))) 359 | try: 360 | print('\n5. Kapp cofficient : {:.4f}\n'.format( self._kappa_evaluation(confusion_matrix))) 361 | except: 362 | print('\n5. Kapp cofficient : undefined') 363 | except: 364 | print('Error : Please close any existing Tensorflow session and try again or restart Python Kernel') 365 | 366 | def blindsite_validation(self,path,reduced_bands=False, selected=[]): 367 | """ Constructs confusion matrix by trained model for blind sample""" 368 | 369 | short_classes = self._short_classes 370 | 371 | 372 | try: 373 | with tf.Session() as sess: 374 | self._saver.restore(sess,path) 375 | 376 | new_test_instances, new_test_one_hot_vectors = self._randomize_test_data(reduced_bands=reduced_bands,selected=selected) 377 | 378 | 379 | testing_accuracy = sess.run(self._accuracy, feed_dict={self._x: new_test_instances, self._y: new_test_one_hot_vectors }) 380 | 381 | confusion_matrix = sess.run(self._conf_mat, feed_dict={self._x: new_test_instances, self._y: new_test_one_hot_vectors }) 382 | 383 | total_sample = [np.sum(confusion_matrix,axis=0)] 384 | 385 | 386 | print('\n----------Blind site validation of model {}----------\n'.format(path.split('/')[-1])) 387 | 388 | print('Total blind site samples\n') 389 | print(pd.DataFrame(total_sample,columns=short_classes,index=['Total samples'])) 390 | 391 | print("\n1. Overall accuracy : {:.4f}\n".format(testing_accuracy)) 392 | 393 | print('2. Confusion matrix: columns are prediction labels and the rows are the GT data\n') 394 | 395 | print(pd.DataFrame(confusion_matrix,columns=short_classes,index=short_classes)) 396 | 397 | class_wise_acc = list() 398 | 399 | for i in range(len(confusion_matrix)): 400 | producer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[:,i]),decimals=3) 401 | consumer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[i]),decimals=3) 402 | 403 | class_wise_acc.append([producer_acc,consumer_acc]) 404 | 405 | print('\n3. Producer accuracy and Consumer accuracy:\n') 406 | 407 | print(pd.DataFrame(class_wise_acc,columns=(['Producer/Class acc','Consumer acc']),index=short_classes)) 408 | 409 | print('\n4. Average accuracy : {:.4f}'.format(np.sum(np.array(class_wise_acc),axis=0)[0]/len(class_wise_acc))) 410 | try: 411 | print('\n5. Kapp cofficient : {:.4f}\n'.format( self._kappa_evaluation(confusion_matrix))) 412 | except: 413 | print('\n5. Kapp cofficient : undefined') 414 | except: 415 | print('Error : Please close any existing Tensorflow session and try again or restart Python Kernel') 416 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/hyperspectral_image/_DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/hyperspectral_image/_DS_Store -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/hyperspectral_image/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | 4 | from Hyspeclib.hyspeclib.hyperspectral_image.read_image import read_image 5 | from Hyspeclib.hyspeclib.hyperspectral_image.check_memory import check_memory 6 | from Hyspeclib.hyspeclib.hyperspectral_image.view_image import view_image 7 | from Hyspeclib.hyspeclib.hyperspectral_image.view_classified_image import view_classified_image -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/hyperspectral_image/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/hyperspectral_image/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/hyperspectral_image/__pycache__/check_memory.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/hyperspectral_image/__pycache__/check_memory.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/hyperspectral_image/__pycache__/image.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/hyperspectral_image/__pycache__/image.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/hyperspectral_image/__pycache__/read_image.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/hyperspectral_image/__pycache__/read_image.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/hyperspectral_image/__pycache__/view_classified_image.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/hyperspectral_image/__pycache__/view_classified_image.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/hyperspectral_image/__pycache__/view_image.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/hyperspectral_image/__pycache__/view_image.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/hyperspectral_image/check_memory.py: -------------------------------------------------------------------------------- 1 | import psutil 2 | 3 | class check_memory: 4 | 5 | def check_image_before_load(self,image_dims): 6 | """ 7 | Check if image can be fit into memory or not without loading it. 8 | 9 | """ 10 | 11 | if image_dims[0]*image_dims[1]*image_dims[2]*4 < self.check_available_memory(): 12 | return True 13 | else: 14 | return False 15 | 16 | def check_available_memory(self,unit='B'): 17 | """ 18 | Returns available memory in RAM in desired unit. 19 | 20 | unit : 'MB' for mega bytes, 'GB' for giga bytes, default bytes. 21 | 22 | """ 23 | free = psutil.virtual_memory().available 24 | 25 | if unit == 'MB': 26 | 27 | return free/10**6 28 | 29 | elif unit == 'GB': 30 | 31 | return free/10**9 32 | 33 | else: 34 | 35 | return free -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/hyperspectral_image/image.py: -------------------------------------------------------------------------------- 1 | """ 2 | Image class is hyperspectral image. It has height, width and channels. 3 | """ 4 | import spectral.io.envi as envi 5 | import numpy as np 6 | from Hyspeclib.hyspeclib.hyperspectral_image.check_memory import check_memory 7 | 8 | 9 | class image: 10 | 11 | def __init__(self, img_path): 12 | """ 13 | Function locates hyperspectral image in disk. It does not load 14 | entire image into memory. 15 | 16 | img_path : path to IMAGE_NAME.hdr' file of aviris image 17 | 18 | """ 19 | self._read_only_image = envi.open(img_path + ".hdr", img_path) 20 | 21 | self._img_path = img_path 22 | 23 | self._img_height = self._read_only_image.nrows 24 | 25 | self._img_width = self._read_only_image.ncols 26 | 27 | self._img_bands = self._read_only_image.nbands 28 | 29 | 30 | def load_image(self): 31 | """ 32 | Function load hyperspectral data into memory. Image is loaded if enough memory is 33 | available otherwise not. 34 | 35 | """ 36 | 37 | mem = check_memory() 38 | 39 | if mem.check_image_before_load(self.size): 40 | 41 | try : 42 | del self._loaded_img 43 | except: 44 | pass 45 | 46 | self._loaded_img = envi.open(self.img_path + ".hdr", self.img_path).load() 47 | 48 | return self._loaded_img 49 | 50 | else: 51 | 52 | return 'Out of memory error. Free some space in memory or reduce image dimentions.' 53 | 54 | 55 | @property 56 | def img_height(self): 57 | return self._img_height 58 | 59 | @img_height.setter 60 | def img_height(self, value): 61 | self._img_height = value 62 | 63 | @property 64 | def img_width(self): 65 | return self._img_width 66 | 67 | @img_width.setter 68 | def img_width(self, value): 69 | self._img_width = value 70 | 71 | @property 72 | def img_bands(self): 73 | return self._img_bands 74 | 75 | @img_bands.setter 76 | def img_bands(self, value): 77 | self._img_bands = value 78 | 79 | 80 | @property 81 | def img_path(self): 82 | return self._img_path 83 | 84 | @property 85 | def size(self): 86 | """ 87 | Returns number of rows, columns and bands 88 | """ 89 | return (self._img_height, self._img_width, self._img_bands) 90 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/hyperspectral_image/read_image.py: -------------------------------------------------------------------------------- 1 | from Hyspeclib.hyspeclib.hyperspectral_image.image import image 2 | from Hyspeclib.hyspeclib.hyperspectral_image.check_memory import check_memory 3 | import matplotlib.pylab as pylab 4 | 5 | class read_image(image): 6 | 7 | def __init__(self, img_path): 8 | super().__init__(img_path) 9 | 10 | 11 | def sub_image(self): 12 | """ 13 | Function loads hyperspectral image as array into memory with specified rows , columns and bands. 14 | 15 | Examples: 16 | 17 | 1. img.sub_image()[ 0 : 10, 0 : 20, 0 : 10] loads first 10 rows, 10 columns and 10 bands 18 | 19 | 2. img.sub_image()[ :,:, [55,80] ] loads only 55th and 80th bands for entire image 20 | 21 | 22 | """ 23 | return self._read_only_image 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/hyperspectral_image/view_classified_image.py: -------------------------------------------------------------------------------- 1 | from spectral import imshow 2 | from Hyspeclib.hyspeclib.hyperspectral_image.read_image import read_image 3 | import numpy as np 4 | import pandas as pd 5 | import matplotlib as mt 6 | import matplotlib.pyplot as plt 7 | 8 | class view_classified_image: 9 | 10 | 11 | def __init__(self, classified_image_path, class_labels=None ,color_list=None): 12 | 13 | 14 | self._classified_img = np.array(pd.read_csv(classified_image_path, header=None)) 15 | 16 | self._max_class = np.max(self._classified_img) 17 | 18 | if color_list!=None: 19 | self._color_list = color_list 20 | else: 21 | tmp_list = ['#FFFFFF','#3BCBD5','#F7CD0A','#990033','#FF3399','#339900','#666600', 22 | '#000000','#0000FF','#CC7755','#FF8866','#FF9988','gray','#F48FB1', 23 | '#880E4F','#E1BEE7','#9FA8DA','#1E88E5','#26A69A', '#69F0AE','#FDD835', 24 | '#6D4C41','#546E7A','#B71C1C'] 25 | 26 | self._color_list = tmp_list[:self._max_class] 27 | self._color_list[self._max_class-1] = '#C0C0C0' 28 | 29 | 30 | self._color_rgb = self._color_rgb_list(self._color_list) 31 | 32 | 33 | if class_labels == None: 34 | class_labels = str(np.arange(self._max_class)) 35 | 36 | plt.figure(figsize=(self._max_class, 1), dpi=100) 37 | 38 | try: 39 | plt.bar(left=np.arange(self._max_class), height=[1 for i in range(self._max_class)], width=1, color = self._color_list, tick_label = class_labels, edgecolor='#000000') 40 | except: 41 | plt.bar(x=np.arange(self._max_class), height=1, width=1, color = self._color_list, tick_label = class_labels, edgecolor='#000000') 42 | 43 | 44 | plt.title('Color pallete for classes') 45 | plt.show() 46 | 47 | def _color_rgb_list(self,color_list): 48 | color_rgb = list() 49 | 50 | for color_hex in color_list: 51 | hex1, hex2, hex3 = color_hex[1:3], color_hex[3:5], color_hex[5:7] 52 | 53 | r, g, b = np.int(hex1, base=16), np.int(hex2, base=16), np.int(hex3, base=16) 54 | 55 | color_rgb.append([r, g, b]) 56 | 57 | return color_rgb 58 | 59 | 60 | def show_and_save(self, save_color_img_path): 61 | 62 | cmap, norm = mt.colors.from_levels_and_colors(levels=np.arange(1,self._max_class+1,1),colors=self._color_list[1:],extend='neither') 63 | 64 | plt.figure(figsize=(self._classified_img.shape[1]//50,self._classified_img.shape[0]//50)) 65 | plt.imshow(self._classified_img,cmap=cmap, norm=norm) 66 | plt.savefig(save_color_img_path,format='png') 67 | plt.show() 68 | 69 | def _helper(self, img_arr): 70 | 71 | unlabeled = self._max_class 72 | 73 | for i in range(img_arr.shape[0]): 74 | for j in range(img_arr.shape[1]): 75 | if img_arr[i, j] == unlabeled: 76 | img_arr[i, j] = 0 77 | 78 | return img_arr 79 | 80 | def overlay_on_raw_img(self, path_to_raw_img): 81 | 82 | raw_img = read_image(path_to_raw_img) 83 | 84 | v = imshow(raw_img.sub_image()[:, :, :], classes = self._helper(np.copy(self._classified_img)), colors = self._color_rgb) 85 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/hyperspectral_image/view_image.py: -------------------------------------------------------------------------------- 1 | from spectral import imshow 2 | 3 | class view_image(): 4 | 5 | def __init__(self, image, fcc=True): 6 | """ 7 | Plots image, make sure image is loaded into memory using img.load_image() function. 8 | 9 | fcc = true loads (98,56,36) for false color composite 10 | 11 | """ 12 | try: 13 | if fcc==False: 14 | imshow(image) 15 | else: 16 | imshow(image, (98, 56, 36)) 17 | except: 18 | print('Error : Load image first and try again.') 19 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/multilayer_perceptron/_DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/multilayer_perceptron/_DS_Store -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/multilayer_perceptron/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from Hyspeclib.hyspeclib.multilayer_perceptron import multilayer_perceptron 3 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/multilayer_perceptron/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/multilayer_perceptron/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/multilayer_perceptron/__pycache__/multilayer_perceptron.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/multilayer_perceptron/__pycache__/multilayer_perceptron.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/multilayer_perceptron/dymlp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Tue Apr 17 10:27:46 2018 5 | 6 | @author: hetul 7 | """ 8 | 9 | import tensorflow as tf 10 | import pandas as pd 11 | import numpy as np 12 | import matplotlib.pyplot as plt 13 | from spectral import open_image 14 | from sklearn.model_selection import train_test_split as ttspilt 15 | import os 16 | 17 | 18 | class make_model: 19 | 20 | def __init__(self, n_nodes=[392,150,100,50,11],learning_rate=0.01,batch_size=32,n_iter=50): 21 | 22 | # Network Parameters 23 | self._n_layer = len(n_nodes)-1 24 | 25 | if self._n_layer < 2 : 26 | print('Error : Minimum two layers are required for e.g input and output nodes.') 27 | 28 | self._n_nodes = n_nodes 29 | self._learning_rate = learning_rate 30 | self._dropout=0.1 31 | self._n_input = n_nodes[0] # Number of Inputs here number of bands 32 | self._n_classes = n_nodes[-1] # Classes in training Set 33 | self._batch_size = batch_size 34 | self._num_iteration = n_iter 35 | 36 | # tf Graph input 37 | self._x = tf.placeholder("float", [None, self._n_input],name='inputs') 38 | self._y = tf.placeholder("float", [None, self._n_classes],name='outputs') 39 | #learning_rate = tf.Variable(initial_value=0.01,name='learning_rate') 40 | 41 | self._weights = list() 42 | self._biases = list() 43 | 44 | for i in range(self._n_layer): 45 | self._weights.append(tf.Variable(tf.random_normal([self._n_nodes[i], self._n_nodes[i+1]]),name='L'+str(i))) 46 | self._biases.append(tf.Variable(tf.random_normal([self._n_nodes[i+1]]),name='B'+str(i))) 47 | # Store layers weight & bias 48 | 49 | print('Parameters intialised') 50 | 51 | self._build_model() 52 | 53 | 54 | 55 | def train_testing_data(self,dataset_path,titles,test_size=0.10): 56 | cols = list([str(i) for i in range(self._n_input)]) 57 | cols.append('label') 58 | 59 | self.dataset = pd.read_csv(dataset_path,names=cols) 60 | self.data_array = np.asarray(self.dataset) 61 | self.data_set_array, self.test_data_set_array= ttspilt(self.data_array,test_size=test_size, random_state=10) 62 | self.short_classes = titles 63 | self.n_classes = self._n_classes 64 | 65 | 66 | def train_validation_split(self,train=0.7,reduced_bands=False,not_selected=[]): 67 | """ K fold cross validation data function """ 68 | 69 | np.random.shuffle(self.data_set_array) 70 | 71 | #training and validation_set 72 | training_data_set = self.data_set_array[ 0 : int(train*len(self.data_set_array)) ] 73 | validation_data_set = self.data_set_array[ int(train*len(self.data_set_array)) : len(self.data_set_array) ] 74 | 75 | # validation inputs 76 | validation_labels = np.asarray(pd.DataFrame(validation_data_set)[self._n_input]) 77 | validation_one_hot_vectors = np.zeros(shape=(len(validation_data_set),self.n_classes),dtype=np.float32) 78 | validation_instances = np.asarray(pd.DataFrame(validation_data_set).drop(labels=[self._n_input],axis=1),dtype=np.float32) 79 | 80 | # training inputs 81 | train_labels = np.asarray(pd.DataFrame(training_data_set)[self._n_input]) 82 | train_one_hot_vectors = np.zeros(shape=(len(training_data_set),self.n_classes),dtype=np.float32) 83 | train_instances = np.asarray(pd.DataFrame(training_data_set).drop(labels=[self._n_input],axis=1),dtype=np.float32) 84 | 85 | #generating one hot vectors 86 | for count in range(len(validation_labels)): 87 | validation_one_hot_vectors[count][ int(validation_labels[count]) - 1] = 1.0 88 | 89 | for count in range(len(train_labels)): 90 | train_one_hot_vectors[count][ int(train_labels[count]) - 1] = 1.0 91 | 92 | 93 | if reduced_bands == True: 94 | train_instances[:,not_selected] = 0. 95 | validation_instances[:,not_selected] = 0. 96 | 97 | 98 | return train_instances, train_one_hot_vectors, validation_instances, validation_one_hot_vectors 99 | 100 | def randomize_test_data(self,all_class=False,reduced_bands=False,not_selected=[]): 101 | 102 | data = self.test_data_set_array 103 | class_num = self.n_classes 104 | 105 | np.random.shuffle(data) 106 | test_labels = np.asarray(pd.DataFrame(data)[self._n_input]) 107 | test_one_hot_vectors = np.zeros(shape=(len(data),class_num),dtype=np.float32) 108 | test_instances = np.asarray(pd.DataFrame(data).drop(labels=[self._n_input],axis=1),dtype=np.float32) 109 | 110 | for count in range(len(test_labels)): 111 | test_one_hot_vectors[count][ int(test_labels[count]) - 1] = 1.0 112 | 113 | if reduced_bands == True: 114 | test_instances[:,not_selected] = 0. 115 | 116 | 117 | return test_instances, test_one_hot_vectors 118 | 119 | # Create model 120 | def multilayer_perceptron(self,_X, _weights, _biases, _dropout): 121 | print(_X) 122 | 123 | layers = list() 124 | 125 | layers.append(tf.nn.relu(tf.add(tf.matmul(_X, _weights[0]), _biases[0]),name='hidden_1')) 126 | 127 | for i in range(1, self._n_layer-1): 128 | layers.append(tf.nn.relu(tf.add(tf.matmul(layers[i-1], _weights[i]), _biases[i]),name='hidden_'+str(i+1))) 129 | 130 | layers.append(tf.add(tf.matmul(layers[-1], _weights[-1]) , _biases[-1],name='out_layer')) 131 | 132 | for layer in layers: 133 | print(layer) 134 | 135 | return layers[-1] 136 | 137 | def _build_model(self): 138 | 139 | # Construct model 140 | self.pred = self.multilayer_perceptron(self._x, self._weights, self._biases, self._dropout) 141 | self.pred_prob = tf.nn.softmax(self.pred) 142 | # Define loss and optimizer 143 | 144 | # Softmax loss 145 | self.cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=self.pred, labels=self._y)) 146 | # Adam Optimizer 147 | self.optimizer = tf.train.AdamOptimizer(learning_rate=self._learning_rate).minimize(self.cost) 148 | 149 | # Evaluate model 150 | self.correct_pred = tf.equal(tf.argmax(self.pred,1), tf.argmax(self._y,1)) 151 | self.accuracy = tf.reduce_mean(tf.cast(self.correct_pred, np.float32)) 152 | self.conf_mat= tf.confusion_matrix(tf.argmax(self.pred,1),tf.argmax(self._y,1)) 153 | 154 | #use model for classifying image 155 | threshold_classification = lambda v : tf.argmax(v,1) if (np.array(v)[tf.argmax(v,1)] > 0.5) else self.n_classes 156 | 157 | self.classified = threshold_classification(self.pred_prob) 158 | 159 | self.init = tf.global_variables_initializer() 160 | self.saver = tf.train.Saver() 161 | 162 | 163 | 164 | def train_model(self,iterations = 10,lr = 0.01,reduced_bands=False,not_selected=[],early_stopping=False,best_model_path="best_model/1500_model.ckpt"): 165 | 166 | 167 | avg_train = 0 168 | avg_validation = 0 169 | cost_list = [] 170 | overall_old = 0. 171 | 172 | 173 | for iteration in range(iterations): 174 | 175 | 176 | with tf.Session() as sess: 177 | sess.run(self.init) 178 | 179 | #9 Fold Validation run 9 times, 8/9 training and 1/9 testing 180 | 181 | cnt = 0 182 | flag = True 183 | old_val_acc = 0. 184 | 185 | for i in range(9): 186 | 187 | #Getting new Instances 188 | new_train_instances, new_train_one_hot_vectors, new_validation_instances, new_validation_one_hot_vectors = self.train_validation_split(train=0.7,reduced_bands=reduced_bands,not_selected=not_selected) 189 | 190 | total_batch = len(new_train_instances) // self._batch_size 191 | 192 | #print(i+1,' total batch : ',total_batch) 193 | 194 | 195 | for batch in range(total_batch): 196 | 197 | #Preparing batches 198 | batch_xs = new_train_instances[batch*self._batch_size:(batch+1)*self._batch_size] 199 | batch_ys = new_train_one_hot_vectors[batch*self._batch_size:(batch+1)*self._batch_size] 200 | 201 | # Fit training using batch data 202 | sess.run(self.optimizer, feed_dict={self._x: batch_xs, self._y: batch_ys}) 203 | 204 | if batch%(self._batch_size-1) == 0: 205 | 206 | 207 | loss = sess.run(self.cost,feed_dict={self._x: batch_xs, self._y: batch_ys}) 208 | 209 | cost_list.append(loss) 210 | 211 | if early_stopping == True: 212 | 213 | validation_acc = sess.run(self.accuracy,feed_dict={self._x: new_validation_instances, self._y: new_validation_one_hot_vectors}) 214 | 215 | increase = validation_acc - old_val_acc 216 | old_val_acc = validation_acc 217 | 218 | #print("Step: {} | Fold : {} | Batch : {} | Training acc: {:.4f} | Validation acc: {:.4f} | Increase : {:.4f}".format(i*total_batch + batch,i+1,batch+1, mini_batch_acc, validation_acc,increase)) 219 | 220 | if increase <= 0.0 and cnt < 4: 221 | cnt += 1 222 | elif increase <= 0.0 and cnt >= 4: 223 | flag = False 224 | break 225 | else: 226 | cnt = 0 227 | 228 | if early_stopping == True and flag == False: 229 | break 230 | 231 | new_test_instances, new_test_one_hot_vectors = self.randomize_test_data(reduced_bands=reduced_bands,not_selected=not_selected) 232 | new_train_instances, new_train_one_hot_vectors, new_validation_instances, new_validation_one_hot_vectors = self.train_validation_split(train=0.7,reduced_bands=reduced_bands,not_selected=not_selected) 233 | 234 | 235 | training_accuracy = sess.run(self.accuracy, feed_dict={self._x: new_train_instances, 236 | self._y: new_train_one_hot_vectors }) 237 | 238 | validation_accuracy = sess.run(self.accuracy, feed_dict={self._x: new_validation_instances, 239 | self._y: new_validation_one_hot_vectors }) 240 | 241 | 242 | #testing_accuracy = sess.run(self.accuracy, feed_dict={self._x: new_test_instances, 243 | # self._y: new_test_one_hot_vectors }) 244 | 245 | 246 | 247 | avg_train += training_accuracy 248 | avg_validation += validation_accuracy 249 | 250 | 251 | #print("step : {} | Training_acc: {:.4f} | Validation acc: {:.4f} | Old Vec: {:.4f} | Testing acc: {:.4f}".format(iteration+1,training_accuracy,validation_accuracy,overall_old,testing_accuracy)) 252 | print("step : {} | Training_acc. : {:.4f} | Validation acc. : {:.4f} | Highest val. acc. : {:.4f} ".format(iteration+1,training_accuracy,validation_accuracy,overall_old)) 253 | 254 | if validation_accuracy > overall_old: 255 | if reduced_bands==False: 256 | self.saver.save(sess, best_model_path) 257 | print('Saving....') 258 | else: 259 | print('Saving....') 260 | self.saver.save(sess, best_model_path) 261 | 262 | overall_old = validation_accuracy 263 | 264 | 265 | return {'Overall training acc : ' : avg_train/iterations,'Overall validation acc : ' : avg_validation/iterations} 266 | 267 | def kappa_evaluation(self,confusion_mat): 268 | 269 | N = np.sum(confusion_mat) 270 | nrows = confusion_mat.shape[0] 271 | nominator = 0 272 | denominator = 0 273 | for row in range(nrows): 274 | x = np.sum(confusion_mat[row])*np.sum(confusion_mat[:,row]) 275 | nominator += N * confusion_mat[row][row] - x 276 | denominator += x 277 | 278 | return nominator / (N*N - denominator) 279 | 280 | 281 | def training_validation(self,path,reduced_bands=False,not_selected=[]): 282 | """ Constructs confusion matrix by trained model for training sample""" 283 | 284 | short_classes = self.short_classes 285 | 286 | #try: 287 | with tf.Session() as sess: 288 | self.saver.restore(sess,path) 289 | 290 | new_train_instances, new_train_one_hot_vectors, _, _ = self.train_validation_split(train=0.7,reduced_bands=reduced_bands,not_selected=not_selected) 291 | 292 | 293 | training_accuracy = sess.run(self.accuracy, feed_dict={self._x: new_train_instances, self._y: new_train_one_hot_vectors }) 294 | 295 | confusion_matrix = sess.run(self.conf_mat, feed_dict={self._x: new_train_instances, self._y: new_train_one_hot_vectors }) 296 | 297 | total_sample = [np.sum(confusion_matrix,axis=0)] 298 | 299 | 300 | print('\n----------Training site validation of model {}----------\n'.format(path.split('/')[-1])) 301 | 302 | print('Total training samples\n') 303 | #print(total_sample) 304 | print(pd.DataFrame(total_sample,columns=short_classes)) 305 | 306 | print("\n1. Overall accuracy : {:.4f}\n".format(training_accuracy)) 307 | 308 | print('2. Confusion matrix: columns are prediction labels and the rows are the GT data\n') 309 | 310 | print(pd.DataFrame(confusion_matrix,columns=short_classes,index=short_classes)) 311 | 312 | class_wise_acc = list() 313 | 314 | for i in range(len(confusion_matrix)): 315 | producer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[:,i]),decimals=3) 316 | consumer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[i]),decimals=3) 317 | 318 | class_wise_acc.append([producer_acc,consumer_acc]) 319 | 320 | print('\n3. Producer accuracy and Consumer accuracy:\n') 321 | 322 | print(pd.DataFrame(class_wise_acc,columns=(['Producer/Class acc','Consumer acc']),index=short_classes)) 323 | 324 | print('\n4. Average accuracy : {:.4f}'.format(np.sum(np.array(class_wise_acc),axis=0)[0]/len(class_wise_acc))) 325 | try: 326 | print('\n5. Kapp cofficient : {:.4f}'.format( self.kappa_evaluation(confusion_matrix))) 327 | except: 328 | print('\n5. Kapp cofficient : undefined') 329 | #except: 330 | #print('Please close any existing Tensorflow session and try again or restart Python Kernel') 331 | 332 | def blindsite_validation(self,path,reduced_bands=False,not_selected=[]): 333 | """ Constructs confusion matrix by trained model for blind sample""" 334 | 335 | short_classes = self.short_classes 336 | 337 | try: 338 | with tf.Session() as sess: 339 | self.saver.restore(sess,path) 340 | 341 | new_test_instances, new_test_one_hot_vectors = self.randomize_test_data(reduced_bands=reduced_bands,not_selected=not_selected) 342 | 343 | 344 | testing_accuracy = sess.run(self.accuracy, feed_dict={self._x: new_test_instances, self._y: new_test_one_hot_vectors }) 345 | 346 | confusion_matrix = sess.run(self.conf_mat, feed_dict={self._x: new_test_instances, self._y: new_test_one_hot_vectors }) 347 | 348 | total_sample = [np.sum(confusion_matrix,axis=0)] 349 | 350 | 351 | print('\n----------Blind site validation of model {}----------\n'.format(path.split('/')[-1])) 352 | 353 | print('Total blind site samples\n') 354 | print(pd.DataFrame(total_sample,columns=short_classes)) 355 | 356 | print("\n1. Overall accuracy : {:.4f}\n".format(testing_accuracy)) 357 | 358 | print('2. Confusion matrix: columns are prediction labels and the rows are the GT data\n') 359 | 360 | print(pd.DataFrame(confusion_matrix,columns=short_classes,index=short_classes)) 361 | 362 | class_wise_acc = list() 363 | 364 | for i in range(len(confusion_matrix)): 365 | producer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[:,i]),decimals=3) 366 | consumer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[i]),decimals=3) 367 | 368 | class_wise_acc.append([producer_acc,consumer_acc]) 369 | 370 | print('\n3. Producer accuracy and Consumer accuracy:\n') 371 | 372 | print(pd.DataFrame(class_wise_acc,columns=(['Producer/Class acc','Consumer acc']),index=short_classes)) 373 | 374 | print('\n4. Average accuracy : {:.4f}'.format(np.sum(np.array(class_wise_acc),axis=0)[0]/len(class_wise_acc))) 375 | try: 376 | print('\n5. Kapp cofficient : {:.4f}'.format( self.kappa_evaluation(confusion_matrix))) 377 | except: 378 | print('\n5. Kapp cofficient : undefined') 379 | except: 380 | print('Please close any existing Tensorflow session and try again or restart Python Kernel') 381 | 382 | 383 | def make_a_list(self,limit): 384 | list_of_numbers = list() 385 | 386 | for i in range(limit): 387 | list_of_numbers.append(i) 388 | 389 | return list_of_numbers 390 | 391 | 392 | 393 | def reduction_function(self,array_of_weights, in_array, out_array,red_per=0.30,printing=True): 394 | """This function returns fraction of neurons only, reduced from original input neurons 395 | Sum of the weight approach""" 396 | 397 | 398 | dtype_of_dict = [('input_neuron',int),('aggregate',float)] 399 | 400 | index_weight_map = [ [] for i in range(len(in_array))] 401 | #reduced_index_weight_map = [ [] for i in range(len(in_array))] 402 | #reduced_indexes = [ [] for i in range(len(in_array))] 403 | sum_of_weights = [] 404 | 405 | for i in in_array: 406 | count = 0 407 | for j in out_array: 408 | index_weight_map[i].append((i,j,abs(array_of_weights[i][j]))) 409 | count += abs(array_of_weights[i][j]) 410 | sum_of_weights.append((i,count)) 411 | 412 | array = np.array(sum_of_weights,dtype=dtype_of_dict) 413 | sorted_aggregate = np.sort(array,order='aggregate') 414 | 415 | if printing == True: 416 | 417 | #Printing the aggregate score 418 | df = pd.DataFrame(sorted_aggregate) 419 | print(df['aggregate'].describe()) 420 | 421 | df['aggregate'].plot() 422 | plt.grid() 423 | plt.legend('Score',loc=2) 424 | plt.title('Band wise Aggegate Scores') 425 | 426 | plt.show() 427 | 428 | top_bands = list() 429 | 430 | for i in range(int((1-red_per)*len(in_array)),len(in_array)): 431 | top_bands.append(sorted_aggregate[i][0]) 432 | 433 | 434 | return list(np.sort(top_bands)) 435 | 436 | 437 | def select_best_bands(self,model_path,reduction_percentage = 0.21): 438 | """ Returns selected, not selected bands """ 439 | 440 | weights_saved = None 441 | with tf.Session() as sess: 442 | self.saver.restore(sess,model_path) 443 | weights_saved = sess.run(self._weights) 444 | 445 | red_per_inter = 0.3 446 | 447 | for i in range(len(weights_saved)-1,0,-1): 448 | temp_weights = weights_saved[i] 449 | temp_bands = self.reduction_function(temp_weights, self.make_a_list(temp_weights.shape[0]),self.make_a_list(temp_weights.shape[1]),printing=False,red_per=red_per_inter) 450 | 451 | 452 | h1 = weights_saved[0] 453 | selected = self.reduction_function(h1, self.make_a_list(h1.shape[0]),temp_bands,red_per=reduction_percentage,printing=False) 454 | 455 | not_selected = list(set(np.arange(self._n_input)) - set(selected)) 456 | 457 | return selected, not_selected 458 | 459 | def validation(self,instance, mean, t = 0.05): 460 | 461 | if np.mean(instance) == 0: 462 | return False 463 | 464 | 465 | distance = np.sqrt(np.sum(np.square(np.subtract(instance,mean)))) 466 | 467 | if distance <= t: 468 | return True 469 | else: 470 | return False 471 | 472 | def save_data_to_file(self,file,pixel,class_index): 473 | """Save a newly identified pixel to file""" 474 | 475 | for i in range(self._n_input): 476 | 477 | file.write(str(pixel[i])+',') 478 | 479 | file.write(str(class_index+1)+'\n') 480 | 481 | def _augmentation_mask(self, file, class_index, img_cols): 482 | 483 | if self._tmp_count % (img_cols-1) or self._tmp_count == 0: 484 | file.write(str(class_index+1)+',') 485 | self._tmp_count += 1 486 | else: 487 | file.write(str(class_index+1)+'\n') 488 | self._tmp_count = 0 489 | 490 | 491 | #def train_augmentation(self,image_path, model_path, correct_array, new_trainig_data_set, threshold = 0.05, non_selected = [], rows_at_time = 80): 492 | def train_augmentation(self,image_path, model_path, correct_array, rows_at_time = 80, threshold=0.05, not_selected = [], save_data=False,save_directory=''): 493 | 494 | img = open_image(image_path) 495 | 496 | image_name = image_path.split('/')[-1].split('.')[0] 497 | 498 | self._tmp_count = 0 499 | 500 | img_cols = img.ncols 501 | last_block_row_count = img.nrows%rows_at_time 502 | total_blocks = int(np.ceil(img.nrows/rows_at_time)) 503 | 504 | if save_data==True: 505 | out_file = open(save_directory+'augmented_dataset.csv','a') 506 | augmentation_mask_file = open(save_directory+image_name+'augmentation_mask.csv','w') 507 | 508 | print('Image : {} divided into {} blocks..'.format(image_path.split('/')[-1],total_blocks)) 509 | 510 | 511 | self.sess = tf.Session() 512 | 513 | try: 514 | self.saver.restore(self.sess,model_path) 515 | 516 | 517 | for block in range(total_blocks): 518 | 519 | print('Currently {} / {}'.format(block+1,total_blocks)) 520 | 521 | start_row = block*rows_at_time 522 | 523 | block_rows_count = rows_at_time 524 | if block == total_blocks-1: 525 | block_rows_count = last_block_row_count 526 | 527 | end_row = start_row + block_rows_count 528 | 529 | img_block = img[start_row:end_row,:] 530 | 531 | masked_block = np.reshape(np.copy(img_block),newshape=(block_rows_count*img_cols,-1)) 532 | 533 | img_block = np.reshape(img_block,newshape=(block_rows_count*img_cols,-1)) 534 | 535 | masked_block[:,not_selected] = 0. 536 | 537 | 538 | classified_block = self.sess.run(self.classified, feed_dict={self._x: masked_block} ) 539 | 540 | 541 | for index,pixel in enumerate(masked_block): 542 | if np.sum(pixel) == 0 : 543 | classified_block[index] = self.n_classes 544 | 545 | 546 | for i in range(len(masked_block)): 547 | 548 | if np.mean(masked_block[i]) > 0 and self.validation(masked_block[i],self.class_wise_mean[classified_block[i]],t=threshold) == True: 549 | correct_array[classified_block[i]] +=1 550 | 551 | if save_data == True: 552 | #self.save_data_to_file(out_file,img_block[i],classified_block[i]) 553 | self._augmentation_mask(augmentation_mask_file,classified_block[i],img_cols) 554 | elif save_data == True: 555 | self._augmentation_mask(augmentation_mask_file,-1,img_cols) 556 | 557 | 558 | del img_block 559 | del masked_block 560 | 561 | self.sess.close() 562 | 563 | print('Image : {} classified..'.format(image_path.split('/')[-1])) 564 | 565 | if save_data == True: 566 | out_file.close() 567 | augmentation_mask_file.close() 568 | 569 | del img 570 | 571 | return correct_array 572 | 573 | except: 574 | self.sess.close() 575 | print('Error : Try again after restrating kernel') 576 | return correct_array 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | def increase_train_data(self,images,model_path,threshold,save_data=False,save_directory='',not_selected=[],rows_at_time=80): 586 | 587 | self.class_wise_mean = np.array(self.dataset.groupby(['label']).mean()) 588 | self.class_wise_mean[:,not_selected] = 0. 589 | 590 | 591 | correct_array = [0 for i in range(self.n_classes)] 592 | 593 | for image in images: 594 | correct_array = self.train_augmentation( image,model_path, 595 | correct_array,rows_at_time, 596 | threshold,not_selected, 597 | save_data=save_data, 598 | save_directory=save_directory) 599 | 600 | 601 | 602 | return correct_array 603 | 604 | def classify_image(self,image_path,model_path,save_path,not_selected=[],rows_at_time = 80): 605 | 606 | #level = [1,2,3,4,5,6,7,8,9,10,11,12] 607 | #color_list = ['#3BCBD5','#F7CD0A','#990033','#FF3399','#339900','#666600', 608 | # '#000000','#0000FF','#CC7755','#FF8866','#FF9988'] 609 | 610 | img = open_image(image_path) 611 | 612 | 613 | img_cols = img.ncols 614 | last_block_row_count = img.nrows%rows_at_time 615 | total_blocks = int(np.ceil(img.nrows/rows_at_time)) 616 | 617 | 618 | out_file = open(save_path,'w') 619 | 620 | print('Image : {} divided into {} blocks..'.format(image_path.split('/')[-1],total_blocks)) 621 | 622 | 623 | self.sess = tf.Session() 624 | 625 | try: 626 | self.saver.restore(self.sess,model_path) 627 | 628 | 629 | for block in range(total_blocks): 630 | 631 | print('Currently {} / {}'.format(block+1,total_blocks)) 632 | 633 | start_row = block*rows_at_time 634 | 635 | block_rows_count = rows_at_time 636 | if block == total_blocks-1: 637 | block_rows_count = last_block_row_count 638 | 639 | end_row = start_row + block_rows_count 640 | 641 | img_block = img[start_row:end_row,:] 642 | 643 | masked_block = np.reshape(np.copy(img_block),newshape=(block_rows_count*img_cols,-1)) 644 | 645 | img_block = np.reshape(img_block,newshape=(block_rows_count*img_cols,-1)) 646 | 647 | masked_block[:,not_selected] = 0. 648 | 649 | 650 | classified_block = self.sess.run(self.classified, feed_dict={self._x: masked_block} ) 651 | 652 | 653 | for index,pixel in enumerate(masked_block): 654 | if np.sum(pixel) == 0 : 655 | classified_block[index] = self.n_classes 656 | 657 | for row in range(block_rows_count): 658 | for column in range(img_cols-1): 659 | out_file.write(str(classified_block[column + row*img_cols]+1)+',') 660 | out_file.write(str(classified_block[column+1 + row*img_cols]+1)+'\n') 661 | 662 | 663 | 664 | del img_block 665 | del masked_block 666 | 667 | self.sess.close() 668 | except: 669 | print('Error in tensorflow: close any existing sessions') 670 | self.sess.close() 671 | return 672 | 673 | del img 674 | 675 | print('Image : {} classified and saved to :'.format(image_path.split('/')[-1]),save_path) 676 | 677 | 678 | 679 | 680 | 681 | 682 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/multilayer_perceptron/multilayer_perceptron.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | import pandas as pd 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | from Hyspeclib.hyspeclib.hyperspectral_image.read_image import read_image 6 | from Hyspeclib.hyspeclib.preprocessing.fit_in_memory import _fit_in_memory 7 | from sklearn.model_selection import train_test_split as ttspilt 8 | 9 | 10 | class multilayer_perceptron: 11 | """docstring for multilayer_perceptron.""" 12 | def __init__(self, n_nodes=None,available_memory_gb=2,learning_rate=0.01,batch_size=32,n_iter=50): 13 | # Network Parameters 14 | self._n_layer = len(n_nodes)-1 15 | 16 | if self._n_layer < 2 : 17 | print('Error : Minimum two layers are required for e.g input and output nodes.') 18 | 19 | self._n_nodes = n_nodes 20 | self._max = available_memory_gb 21 | self._learning_rate = learning_rate 22 | self._dropout=0.1 23 | self._n_input = n_nodes[0] # Number of Inputs here number of bands 24 | self._n_classes = n_nodes[-1] # Classes in training Set 25 | self._batch_size = batch_size 26 | self._num_iteration = n_iter 27 | 28 | # tf Graph input 29 | self._x = tf.placeholder("float", [None, self._n_input],name='inputs') 30 | self._y = tf.placeholder("float", [None, self._n_classes],name='outputs') 31 | #learning_rate = tf.Variable(initial_value=0.01,name='learning_rate') 32 | 33 | self._weights = list() 34 | self._biases = list() 35 | 36 | for i in range(self._n_layer): 37 | self._weights.append(tf.Variable(tf.random_normal([self._n_nodes[i], self._n_nodes[i+1]]),name='L'+str(i))) 38 | self._biases.append(tf.Variable(tf.random_normal([self._n_nodes[i+1]]),name='B'+str(i))) 39 | # Store layers weight & bias 40 | 41 | print('\n------- Parameters intialised. Check your model -------\n') 42 | 43 | self._build_model() 44 | 45 | # Create model 46 | def _multilayer_perceptron(self,_X, _weights, _biases, _dropout): 47 | print(_X) 48 | 49 | layers = list() 50 | 51 | layers.append(tf.nn.relu(tf.add(tf.matmul(_X, _weights[0]), _biases[0]),name='hidden_1')) 52 | 53 | for i in range(1, self._n_layer-1): 54 | layers.append(tf.nn.relu(tf.add(tf.matmul(layers[i-1], _weights[i]), _biases[i]),name='hidden_'+str(i+1))) 55 | 56 | layers.append(tf.add(tf.matmul(layers[-1], _weights[-1]) , _biases[-1],name='out_layer')) 57 | 58 | for layer in layers: 59 | print(layer) 60 | 61 | return layers[-1] 62 | 63 | def _build_model(self): 64 | 65 | # Construct model 66 | self._pred = self._multilayer_perceptron(self._x, self._weights, self._biases, self._dropout) 67 | self._pred_prob = tf.nn.softmax(self._pred) 68 | # Define loss and optimizer 69 | 70 | # Softmax loss 71 | self._cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=self._pred, labels=self._y)) 72 | # Adam Optimizer 73 | self._optimizer = tf.train.AdamOptimizer(learning_rate=self._learning_rate).minimize(self._cost) 74 | 75 | # Evaluate model 76 | self._correct_pred = tf.equal(tf.argmax(self._pred,1), tf.argmax(self._y,1)) 77 | self._accuracy = tf.reduce_mean(tf.cast(self._correct_pred, np.float32)) 78 | self._conf_mat= tf.confusion_matrix(tf.argmax(self._pred,1),tf.argmax(self._y,1)) 79 | 80 | # Classification 81 | self._classified = self._pred_prob 82 | self._classified_aug = tf.argmax(self._pred,1) 83 | 84 | 85 | self._init = tf.global_variables_initializer() 86 | self._saver = tf.train.Saver() 87 | 88 | def train_testing_data(self,dataset_path,titles,test_size=0.10): 89 | cols = list([str(i) for i in range(self._n_input)]) 90 | cols.append('label') 91 | 92 | self._dataset = pd.read_csv(dataset_path,names=cols) 93 | self._data_array = np.asarray(self._dataset) 94 | self._data_set_array, self._test_data_set_array= ttspilt(self._data_array,test_size=test_size, random_state=10) 95 | self._short_classes = titles 96 | self._n_classes = self._n_classes 97 | 98 | def train_test_balanced_data(self, dataset_path, titles, array_of_pixels_per_class = []): 99 | 100 | if len(array_of_pixels_per_class) < self._n_classes: 101 | print('Please specify count of training site pixels for each class.') 102 | return 103 | 104 | x = array_of_pixels_per_class 105 | 106 | cols = list([str(i) for i in range(self._n_input)]) 107 | cols.append('label') 108 | 109 | self._dataset = pd.read_csv(dataset_path,names=cols) 110 | 111 | self._data_set_array = list() 112 | 113 | self._test_data_set_array = list() 114 | 115 | for i in range(self._dataset.shape[0]): 116 | 117 | pixel = self._dataset.iloc[i] 118 | 119 | if x[int(pixel[self._n_input])-1] > 0 : 120 | x[int(pixel[self._n_input])-1] -= 1 121 | 122 | self._data_set_array.append(np.array(pixel)) 123 | else: 124 | self._test_data_set_array.append(np.array(pixel)) 125 | 126 | self._short_classes = titles 127 | self._n_classes = self._n_classes 128 | 129 | 130 | 131 | def _train_validation_split( self, train=0.7, reduced_bands=False, not_selected=[] ): 132 | 133 | """ K fold cross validation data function """ 134 | 135 | np.random.seed(0) 136 | np.random.shuffle(self._data_set_array) 137 | 138 | #training and validation_set 139 | training_data_set = np.array(self._data_set_array[ 0 : int(train*len(self._data_set_array)) ]) 140 | validation_data_set = np.array(self._data_set_array[ int(train*len(self._data_set_array)) : len(self._data_set_array) ]) 141 | 142 | # validation inputs 143 | validation_labels = np.asarray(pd.DataFrame(validation_data_set)[self._n_input]) 144 | validation_one_hot_vectors = np.zeros(shape=(len(validation_data_set),self._n_classes),dtype=np.float32) 145 | validation_instances = np.asarray(pd.DataFrame(validation_data_set).drop(labels=[self._n_input],axis=1),dtype=np.float32) 146 | 147 | # training inputs 148 | train_labels = np.asarray(pd.DataFrame(training_data_set)[self._n_input]) 149 | train_one_hot_vectors = np.zeros(shape=(len(training_data_set),self._n_classes),dtype=np.float32) 150 | train_instances = np.asarray(pd.DataFrame(training_data_set).drop(labels=[self._n_input],axis=1),dtype=np.float32) 151 | 152 | #generating one hot vectors 153 | for count in range(len(validation_labels)): 154 | validation_one_hot_vectors[count][ int(validation_labels[count]) - 1] = 1.0 155 | 156 | for count in range(len(train_labels)): 157 | train_one_hot_vectors[count][ int(train_labels[count]) - 1] = 1.0 158 | 159 | 160 | if reduced_bands == True: 161 | train_instances[:,not_selected] = 0. 162 | validation_instances[:,not_selected] = 0. 163 | 164 | 165 | return train_instances, train_one_hot_vectors, validation_instances, validation_one_hot_vectors 166 | 167 | def _randomize_test_data(self,reduced_bands=False,not_selected=[]): 168 | 169 | np.random.seed(0) 170 | 171 | data = self._test_data_set_array 172 | class_num = self._n_classes 173 | 174 | np.random.shuffle(data) 175 | test_labels = np.asarray(pd.DataFrame(data)[self._n_input]) 176 | test_one_hot_vectors = np.zeros(shape=(len(data),class_num),dtype=np.float32) 177 | test_instances = np.asarray(pd.DataFrame(data).drop(labels=[self._n_input],axis=1),dtype=np.float32) 178 | 179 | for count in range(len(test_labels)): 180 | test_one_hot_vectors[count][ int(test_labels[count]) - 1] = 1.0 181 | 182 | if reduced_bands == True: 183 | test_instances[:,not_selected] = 0. 184 | 185 | 186 | return test_instances, test_one_hot_vectors 187 | 188 | def train_model(self,best_model_path,iterations = 10,lr = 0.01,reduced_bands=False,selected=[],early_stopping=False): 189 | 190 | 191 | avg_train = 0 192 | avg_validation = 0 193 | cost_list = [] 194 | overall_old = 0. 195 | not_selected = list(set(np.arange(self._n_input)) - set(selected)) 196 | 197 | 198 | print('\n\n--------------Training Neural Network------------------\n\n') 199 | for iteration in range(iterations): 200 | 201 | 202 | with tf.Session() as sess: 203 | sess.run(self._init) 204 | 205 | #9 Fold Validation run 9 times, 8/9 training and 1/9 testing 206 | 207 | cnt = 0 208 | flag = True 209 | old_val_acc = 0. 210 | 211 | for i in range(9): 212 | 213 | #Getting new Instances 214 | new_train_instances, new_train_one_hot_vectors, new_validation_instances, new_validation_one_hot_vectors = self._train_validation_split(train=0.7,reduced_bands=reduced_bands,not_selected=not_selected) 215 | 216 | total_batch = len(new_train_instances) // self._batch_size 217 | 218 | #print(i+1,' total batch : ',total_batch) 219 | 220 | 221 | for batch in range(total_batch): 222 | 223 | #Preparing batches 224 | batch_xs = new_train_instances[batch*self._batch_size:(batch+1)*self._batch_size] 225 | batch_ys = new_train_one_hot_vectors[batch*self._batch_size:(batch+1)*self._batch_size] 226 | 227 | # Fit training using batch data 228 | sess.run(self._optimizer, feed_dict={self._x: batch_xs, self._y: batch_ys}) 229 | 230 | if batch%(self._batch_size-1) == 0: 231 | 232 | 233 | loss = sess.run(self._cost,feed_dict={self._x: batch_xs, self._y: batch_ys}) 234 | 235 | cost_list.append(loss) 236 | 237 | if early_stopping == True: 238 | 239 | validation_acc = sess.run(self._accuracy,feed_dict={self._x: new_validation_instances, self._y: new_validation_one_hot_vectors}) 240 | 241 | increase = validation_acc - old_val_acc 242 | old_val_acc = validation_acc 243 | 244 | #print("Step: {} | Fold : {} | Batch : {} | Training acc: {:.4f} | Validation acc: {:.4f} | Increase : {:.4f}".format(i*total_batch + batch,i+1,batch+1, mini_batch_acc, validation_acc,increase)) 245 | 246 | if increase <= 0.0 and cnt < 4: 247 | cnt += 1 248 | elif increase <= 0.0 and cnt >= 4: 249 | flag = False 250 | break 251 | else: 252 | cnt = 0 253 | 254 | if early_stopping == True and flag == False: 255 | break 256 | 257 | #new_test_instances, new_test_one_hot_vectors = self._randomize_test_data(reduced_bands=reduced_bands,not_selected=not_selected) 258 | new_train_instances, new_train_one_hot_vectors, new_validation_instances, new_validation_one_hot_vectors = self._train_validation_split(train=0.7,reduced_bands=reduced_bands,not_selected=not_selected) 259 | 260 | 261 | training_accuracy = sess.run(self._accuracy, feed_dict={self._x: new_train_instances, 262 | self._y: new_train_one_hot_vectors }) 263 | 264 | validation_accuracy = sess.run(self._accuracy, feed_dict={self._x: new_validation_instances, 265 | self._y: new_validation_one_hot_vectors }) 266 | 267 | 268 | #testing_accuracy = sess.run(self.accuracy, feed_dict={self._x: new_test_instances, 269 | # self._y: new_test_one_hot_vectors }) 270 | 271 | 272 | 273 | avg_train += training_accuracy 274 | avg_validation += validation_accuracy 275 | 276 | 277 | print("Run no. : {} | Training_acc. : {:.4f} | Validation acc. : {:.4f} | Highest val. acc. : {:.4f} ".format(iteration+1,training_accuracy,validation_accuracy,overall_old)) 278 | 279 | if validation_accuracy > overall_old: 280 | if reduced_bands==False: 281 | self._saver.save(sess, best_model_path) 282 | #print('Saving....') 283 | else: 284 | #print('Saving....') 285 | self._saver.save(sess, best_model_path) 286 | 287 | overall_old = validation_accuracy 288 | 289 | 290 | print('\nTraining is completed, best model is saved at: ',best_model_path) 291 | 292 | print('\n Overall training acc : {:.4f} | Overall validation acc : {:.4f}'.format(avg_train/iterations,avg_validation/iterations)) 293 | 294 | print('\n\n-------------------------------------------------------\n\n') 295 | 296 | def _kappa_evaluation(self,confusion_mat): 297 | 298 | N = np.sum(confusion_mat) 299 | nrows = confusion_mat.shape[0] 300 | nominator = 0 301 | denominator = 0 302 | for row in range(nrows): 303 | x = np.sum(confusion_mat[row])*np.sum(confusion_mat[:,row]) 304 | nominator += N * confusion_mat[row][row] - x 305 | denominator += x 306 | 307 | return nominator / (N*N - denominator) 308 | 309 | def training_validation(self,path,reduced_bands=False, selected=[]): 310 | """ Constructs confusion matrix by trained model for training sample""" 311 | 312 | short_classes = self._short_classes 313 | not_selected = list(set(np.arange(self._n_input)) - set(selected)) 314 | 315 | #try: 316 | with tf.Session() as sess: 317 | self._saver.restore(sess,path) 318 | 319 | new_train_instances, new_train_one_hot_vectors, _, _ = self._train_validation_split(train=0.7,reduced_bands=reduced_bands,not_selected=not_selected) 320 | 321 | 322 | training_accuracy = sess.run(self._accuracy, feed_dict={self._x: new_train_instances, self._y: new_train_one_hot_vectors }) 323 | 324 | confusion_matrix = sess.run(self._conf_mat, feed_dict={self._x: new_train_instances, self._y: new_train_one_hot_vectors }) 325 | 326 | total_sample = [np.sum(confusion_matrix,axis=0)] 327 | 328 | 329 | print('\n----------Training site validation of model {}----------\n'.format(path.split('/')[-1])) 330 | 331 | print('Total training samples\n') 332 | #print(total_sample) 333 | print(pd.DataFrame(total_sample,columns=short_classes,index=['Total samples'])) 334 | 335 | print("\n1. Overall accuracy : {:.4f}\n".format(training_accuracy)) 336 | 337 | print('2. Confusion matrix: columns are prediction labels and the rows are the GT data\n') 338 | 339 | print(pd.DataFrame(confusion_matrix,columns=short_classes,index=short_classes)) 340 | 341 | class_wise_acc = list() 342 | 343 | for i in range(len(confusion_matrix)): 344 | if np.sum(confusion_matrix[:,i]) == 0: 345 | producer_acc = 1 346 | else: 347 | producer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[:,i]),decimals=3) 348 | if np.sum(confusion_matrix[i]) == 0: 349 | consumer_acc = 0 350 | else: 351 | consumer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[i]),decimals=3) 352 | 353 | class_wise_acc.append([producer_acc,consumer_acc]) 354 | print('\n3. Producer accuracy and Consumer accuracy:\n') 355 | 356 | print(pd.DataFrame(class_wise_acc,columns=(['Producer/Class acc','Consumer acc']),index=short_classes)) 357 | 358 | print('\n4. Average accuracy : {:.4f}'.format(np.sum(np.array(class_wise_acc),axis=0)[0]/len(class_wise_acc))) 359 | try: 360 | print('\n5. Kapp cofficient : {:.4f}\n'.format( self._kappa_evaluation(confusion_matrix))) 361 | except: 362 | print('\n5. Kapp cofficient : undefined') 363 | #except: 364 | #print('Error : Please close any existing Tensorflow session and try again or restart Python Kernel') 365 | 366 | def blindsite_validation(self,path,reduced_bands=False, selected=[]): 367 | """ Constructs confusion matrix by trained model for blind sample""" 368 | 369 | short_classes = self._short_classes 370 | not_selected = list(set(np.arange(self._n_input)) - set(selected)) 371 | 372 | 373 | try: 374 | with tf.Session() as sess: 375 | self._saver.restore(sess,path) 376 | 377 | new_test_instances, new_test_one_hot_vectors = self._randomize_test_data(reduced_bands=reduced_bands,not_selected=not_selected) 378 | 379 | 380 | testing_accuracy = sess.run(self._accuracy, feed_dict={self._x: new_test_instances, self._y: new_test_one_hot_vectors }) 381 | 382 | confusion_matrix = sess.run(self._conf_mat, feed_dict={self._x: new_test_instances, self._y: new_test_one_hot_vectors }) 383 | 384 | total_sample = [np.sum(confusion_matrix,axis=0)] 385 | 386 | 387 | print('\n----------Blind site validation of model {}----------\n'.format(path.split('/')[-1])) 388 | 389 | print('Total blind site samples\n') 390 | print(pd.DataFrame(total_sample,columns=short_classes,index=['Total samples'])) 391 | 392 | print("\n1. Overall accuracy : {:.4f}\n".format(testing_accuracy)) 393 | 394 | print('2. Confusion matrix: columns are prediction labels and the rows are the GT data\n') 395 | 396 | print(pd.DataFrame(confusion_matrix,columns=short_classes,index=short_classes)) 397 | 398 | class_wise_acc = list() 399 | 400 | for i in range(len(confusion_matrix)): 401 | if np.sum(confusion_matrix[:,i]) == 0: 402 | producer_acc = 1 403 | else: 404 | producer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[:,i]),decimals=3) 405 | if np.sum(confusion_matrix[i]) == 0: 406 | consumer_acc = 0 407 | else: 408 | consumer_acc = np.round(confusion_matrix[i][i] / np.sum(confusion_matrix[i]),decimals=3) 409 | 410 | class_wise_acc.append([producer_acc,consumer_acc]) 411 | 412 | print('\n3. Producer accuracy and Consumer accuracy:\n') 413 | 414 | print(pd.DataFrame(class_wise_acc,columns=(['Producer/Class acc','Consumer acc']),index=short_classes)) 415 | 416 | print('\n4. Average accuracy : {:.4f}'.format(np.sum(np.array(class_wise_acc),axis=0)[0]/len(class_wise_acc))) 417 | try: 418 | print('\n5. Kapp cofficient : {:.4f}\n'.format( self._kappa_evaluation(confusion_matrix))) 419 | except: 420 | print('\n5. Kapp cofficient : undefined') 421 | except: 422 | print('Error : Please close any existing Tensorflow session and try again or restart Python Kernel') 423 | 424 | def _make_a_list(self,limit): 425 | list_of_numbers = list() 426 | 427 | for i in range(limit): 428 | list_of_numbers.append(i) 429 | 430 | return list_of_numbers 431 | 432 | def _reduction_function(self,array_of_weights, in_array, out_array,red_per=0.30,printing=True): 433 | """This function returns fraction of neurons only, reduced from original input neurons 434 | Sum of the weight approach""" 435 | 436 | 437 | dtype_of_dict = [('input_neuron',int),('aggregate',float)] 438 | 439 | index_weight_map = [ [] for i in range(len(in_array))] 440 | #reduced_index_weight_map = [ [] for i in range(len(in_array))] 441 | #reduced_indexes = [ [] for i in range(len(in_array))] 442 | sum_of_weights = [] 443 | 444 | for i in in_array: 445 | count = 0 446 | for j in out_array: 447 | index_weight_map[i].append((i,j,abs(array_of_weights[i][j]))) 448 | count += abs(array_of_weights[i][j]) 449 | sum_of_weights.append((i,count)) 450 | 451 | array = np.array(sum_of_weights,dtype=dtype_of_dict) 452 | sorted_aggregate = np.sort(array,order='aggregate') 453 | 454 | if printing == True: 455 | 456 | #Printing the aggregate score 457 | df = pd.DataFrame(sorted_aggregate) 458 | print(df['aggregate'].describe()) 459 | 460 | df['aggregate'].plot() 461 | plt.grid() 462 | plt.legend('Score',loc=2) 463 | plt.title('Band wise Aggegate Scores') 464 | 465 | plt.show() 466 | 467 | top_bands = list() 468 | 469 | for i in range(int((1-red_per)*len(in_array)),len(in_array)): 470 | top_bands.append(sorted_aggregate[i][0]) 471 | 472 | 473 | return list(np.sort(top_bands)) 474 | 475 | def select_best_bands(self,model_path, reduced_bands = 40): 476 | """ Returns selected, not selected bands """ 477 | 478 | reduction_percentage = reduced_bands / self._n_input 479 | 480 | weights_saved = None 481 | with tf.Session() as sess: 482 | self._saver.restore(sess,model_path) 483 | weights_saved = sess.run(self._weights) 484 | 485 | red_per_inter = 0.3 486 | 487 | for i in range(len(weights_saved)-1,0,-1): 488 | temp_weights = weights_saved[i] 489 | temp_bands = self._reduction_function(temp_weights, self._make_a_list(temp_weights.shape[0]),self._make_a_list(temp_weights.shape[1]),printing=False,red_per=red_per_inter) 490 | 491 | 492 | h1 = weights_saved[0] 493 | selected = self._reduction_function(h1, self._make_a_list(h1.shape[0]),temp_bands,red_per=reduction_percentage,printing=False) 494 | 495 | not_selected = list(set(np.arange(self._n_input)) - set(selected)) 496 | 497 | return selected, not_selected 498 | 499 | def _validation(self,instance, mean, t = 0.05): 500 | 501 | if np.mean(instance) == 0: 502 | return False 503 | 504 | 505 | distance = np.sqrt(np.sum(np.square(np.subtract(instance,mean)))) 506 | 507 | if distance <= t: 508 | return True 509 | else: 510 | return False 511 | 512 | def _save_data_to_file(self,file,pixel,class_index): 513 | """Save a newly identified pixel to file""" 514 | 515 | for i in range(self._n_input): 516 | 517 | file.write(str(pixel[i])+',') 518 | 519 | file.write(str(int(class_index+1))+'\n') 520 | 521 | def _augmentation_mask(self, file, class_index, img_cols): 522 | 523 | if self._tmp_count % (img_cols-1) or self._tmp_count == 0: 524 | file.write(str(class_index+1)+',') 525 | self._tmp_count += 1 526 | else: 527 | file.write(str(class_index+1)+'\n') 528 | self._tmp_count = 0 529 | 530 | def _assign_class(self, prediction): 531 | 532 | max_value = np.max(prediction) 533 | if max_value > self._min_prob: 534 | return np.argmax(prediction) 535 | else: 536 | return self._n_classes 537 | 538 | def _train_augmentation(self,image_path, model_path, correct_array, threshold=0.05, not_selected = [], save_data=False,save_directory=''): 539 | 540 | img = read_image(image_path) 541 | 542 | image_name = image_path.split('/')[-1].split('.')[0] 543 | 544 | self._tmp_count = 0 545 | 546 | ## Based on fit_in_memory 547 | partition = _fit_in_memory(image_path, available_memory_gb=self._max) 548 | 549 | self._list_of_partitions = partition.patitions() 550 | self._total_partitions = len(self._list_of_partitions) 551 | 552 | del partition 553 | 554 | img_cols = img.img_width 555 | 556 | if save_data==True: 557 | out_file =self._outfile 558 | augmentation_mask_file = open(save_directory+image_name+'augmentation_mask.csv','w') 559 | 560 | print('\n--> Image : {} divided into {} partitions..\n'.format(image_path.split('/')[-1],self._total_partitions)) 561 | 562 | self._sess = tf.Session() 563 | 564 | try: 565 | self._saver.restore(self._sess,model_path) 566 | 567 | for index,each_partion in enumerate(self._list_of_partitions): 568 | 569 | cnt = 0 570 | 571 | print('\n---> Partition : {} / {} running... '.format(index+1, self._total_partitions)) 572 | 573 | block_rows_count = each_partion[1]-each_partion[0] 574 | 575 | img_block = img.sub_image()[each_partion[0]:each_partion[1],:,:] 576 | 577 | masked_block = np.reshape(np.copy(img_block),newshape=(block_rows_count*img_cols,-1)) 578 | 579 | img_block = np.reshape(img_block,newshape=(block_rows_count*img_cols,-1)) 580 | 581 | masked_block[:,not_selected] = 0. 582 | 583 | classified_block = self._sess.run(self._classified_aug, feed_dict={self._x: masked_block} ) 584 | 585 | for index,pixel in enumerate(masked_block): 586 | if np.sum(pixel) == 0 : 587 | classified_block[index] = self._n_classes 588 | 589 | 590 | for i in range(len(classified_block)): 591 | 592 | if np.mean(masked_block[i]) > 0 : 593 | if self._validation(masked_block[i],self._class_wise_mean[classified_block[i]],t=threshold) == True: 594 | correct_array[classified_block[i]] +=1 595 | 596 | if save_data == True: 597 | self._save_data_to_file(out_file,img_block[i],classified_block[i]) 598 | self._augmentation_mask(augmentation_mask_file,classified_block[i],img_cols) 599 | elif save_data == True: 600 | if cnt <= 1000: 601 | cnt +=1 602 | self._save_data_to_file(out_file,img_block[i],self._n_classes) 603 | self._augmentation_mask(augmentation_mask_file,self._n_classes,img_cols) 604 | else: 605 | self._augmentation_mask(augmentation_mask_file,self._n_classes+1,img_cols) 606 | 607 | del img_block 608 | del masked_block 609 | 610 | 611 | self._sess.close() 612 | 613 | if save_data == True: 614 | print('\n--> Image : {} completed and training data is augmented.\n'.format(image_path.split('/')[-1])) 615 | augmentation_mask_file.close() 616 | 617 | del img 618 | 619 | return correct_array 620 | 621 | except: 622 | self._sess.close() 623 | print('Error : Try again after restrating kernel or try changing "Available Memory" ') 624 | return correct_array 625 | 626 | 627 | def increase_train_data(self,images,model_path,threshold,save_data=False,save_directory='', selected=[],merge_with_original=False): 628 | 629 | not_selected = list(set(np.arange(self._n_input)) - set(selected)) 630 | 631 | self._class_wise_mean = np.array(self._dataset.groupby(['label']).mean()) 632 | self._class_wise_mean[:,not_selected] = 0. 633 | 634 | self._outfile = open(save_directory+'augmented_dataset.csv','w') 635 | 636 | 637 | 638 | 639 | correct_array = [0 for i in range(self._n_classes)] 640 | 641 | print('-------------- Training Data Augmentation -----------------\n\n') 642 | 643 | for image in images: 644 | correct_array = self._train_augmentation( image,model_path, 645 | correct_array, 646 | threshold,not_selected, 647 | save_data=save_data, 648 | save_directory=save_directory) 649 | 650 | print('-----------------------------------------------------------\n\n') 651 | 652 | self._outfile.close() 653 | 654 | if merge_with_original == True: 655 | with open(save_directory+'augmented_dataset.csv', 'a') as f: 656 | self._dataset.to_csv(f, header=False,index=False) 657 | 658 | print('Dataset is saved at: ',save_directory+'augmented_dataset.csv\n') 659 | print('Classified images are saved in {} ending with augmentation_mask.csv\n'.format(save_directory)) 660 | 661 | return correct_array 662 | 663 | def classify_image(self,image_path,model_path,save_path, min_probability=0,selected=[]): 664 | 665 | print('-------------- Image classification is in pregress-----------------\n\n') 666 | 667 | img = read_image(image_path) 668 | 669 | self._min_prob = min_probability 670 | 671 | image_name = image_path.split('/')[-1].split('.')[0] 672 | 673 | self._tmp_count = 0 674 | 675 | not_selected = list(set(np.arange(self._n_input)) - set(selected)) 676 | 677 | 678 | ## Based on fit_in_memory 679 | partition = _fit_in_memory(image_path, available_memory_gb=self._max) 680 | 681 | self._list_of_partitions = partition.patitions() 682 | self._total_partitions = len(self._list_of_partitions) 683 | 684 | del partition 685 | 686 | img_cols = img.img_width 687 | 688 | out_file = open(save_path,'w') 689 | 690 | print('Image : {} divided into {} partitions..'.format(image_path.split('/')[-1],self._total_partitions)) 691 | 692 | # Classification starts here.. 693 | 694 | self._sess = tf.Session() 695 | 696 | try: 697 | self._saver.restore(self._sess,model_path) 698 | 699 | 700 | for index,each_partion in enumerate(self._list_of_partitions): 701 | 702 | print('\n---> Partition : {} / {} being classified... '.format(index+1, self._total_partitions)) 703 | 704 | block_rows_count = each_partion[1]-each_partion[0] 705 | 706 | img_block = img.sub_image()[each_partion[0]:each_partion[1],:,:] 707 | 708 | masked_block = np.reshape(np.copy(img_block),newshape=(block_rows_count*img_cols,-1)) 709 | 710 | img_block = np.reshape(img_block,newshape=(block_rows_count*img_cols,-1)) 711 | 712 | masked_block[:,not_selected] = 0. 713 | 714 | #classified_block = self._sess.run(self._classified, feed_dict={self._x: masked_block} ) 715 | 716 | pred_block = self._sess.run(self._classified, feed_dict={self._x: masked_block} ) 717 | 718 | classified_block = np.zeros(shape=(block_rows_count*img_cols),dtype=np.int32) 719 | 720 | for i in range(len(classified_block)): 721 | classified_block[i] = self._assign_class(pred_block[i]) 722 | #if i%100 == 0: 723 | #print(pred_block[i],self._assign_class(pred_block[i]) ) 724 | 725 | del pred_block 726 | 727 | for index,pixel in enumerate(masked_block): 728 | if np.sum(pixel) == 0 : 729 | classified_block[index] = self._n_classes 730 | 731 | for row in range(block_rows_count): 732 | for column in range(img_cols-1): 733 | out_file.write(str(classified_block[column + row*img_cols]+1)+',') 734 | out_file.write(str(classified_block[column+1 + row*img_cols]+1)+'\n') 735 | 736 | 737 | del img_block 738 | del masked_block 739 | 740 | self._sess.close() 741 | except: 742 | print('Error in tensorflow: close any existing sessions') 743 | self._sess.close() 744 | return 745 | 746 | del img 747 | 748 | print('\n\nImage : {} classified and saved to :'.format(image_path.split('/')[-1]),save_path) 749 | 750 | print('-------------------------------------------------------------------\n\n') 751 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/pca_analysis/_DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/pca_analysis/_DS_Store -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/pca_analysis/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from .pca_analysis import pca_analysis -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/pca_analysis/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/pca_analysis/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/pca_analysis/__pycache__/pca_analysis.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/pca_analysis/__pycache__/pca_analysis.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/pca_analysis/pca_analysis.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from spectral import principal_components 5 | import matplotlib.pyplot as plt 6 | from spectral import open_image 7 | import glob 8 | import numpy as np 9 | import time 10 | import pandas as pd 11 | 12 | 13 | class pca_analysis: 14 | 15 | def __init__(self, image_directory_path=None, save_dir = None ): 16 | 17 | if image_directory_path!=None: 18 | self._image_directory_path = image_directory_path 19 | self._processed_images = glob.glob(image_directory_path+'**/**.hdr',recursive=True) 20 | self._total_images = len(self._processed_images) 21 | self._save_dir = save_dir 22 | print('Total {} images found in directory.'.format(self._total_images)) 23 | 24 | def _fetch_pca(self, image_path): 25 | 26 | t1 = time.time() 27 | print("Fetching file : " + image_path) 28 | img = open_image(image_path) 29 | 30 | nbands = img.nbands 31 | 32 | pc = principal_components(img) 33 | 34 | t2 = time.time() - t1 35 | print('\nTook {:.4f} seconds / {:.4f} min to run.\n'.format(t2, t2/60)) 36 | return nbands, pc 37 | 38 | 39 | def _write_to_file(self, image_name, nbands, principal_component_analysis): 40 | 41 | t1 = time.time() 42 | 43 | eigen_vectors = principal_component_analysis.eigenvectors 44 | eigen_values = principal_component_analysis.eigenvalues 45 | 46 | 47 | with open(self._save_dir + image_name + '_pca.csv', mode='w') as file: 48 | 49 | for pc_number in range(nbands): 50 | 51 | file.write( str(pc_number+1)) 52 | file.write(','+str(eigen_values[pc_number])) 53 | for component in eigen_vectors[pc_number]: 54 | file.write(',' + str(np.round(np.real(component), decimals=4))) 55 | file.write('\n') 56 | 57 | t2 = time.time() - t1 58 | print('Writing to disk complete... took {} seconds'.format(t2)) 59 | 60 | def perform(self): 61 | 62 | try : 63 | 64 | print('\n\n---------------- Computing PCA Statistics -------------------\n') 65 | 66 | for index, image in enumerate(self._processed_images): 67 | 68 | print('\nCurrent image {}/{}\n'.format( index+1, self._total_images )) 69 | 70 | image_name = image.split('/')[-1].split('.')[0] 71 | 72 | nbands, temp_pca_analysis = self._fetch_pca(image) 73 | 74 | self._write_to_file(image_name, nbands, temp_pca_analysis) 75 | 76 | del temp_pca_analysis 77 | 78 | print('Eigen Values and Eigen Vectors are saved successfully at : ' + self._save_dir) 79 | 80 | print('\n\n-------------------------------------------------------------\n') 81 | except: 82 | print('Please pass preprocessed images directory in pca_analysis(?) as parameter\nor try again.' ) 83 | print('\n\n-------------------------------------------------------------\n') 84 | 85 | 86 | # Exploration 87 | 88 | def _fetch_array(self, image_stat): 89 | vectors = image_stat.drop(labels=[0,1], axis=1) 90 | return np.asarray(vectors), np.asarray(image_stat[1]) 91 | 92 | def _cumulative_sum_of_percentage(self, array_of_eigen_values, filepath): 93 | 94 | cumulative_percentage = 0 95 | more_than_zero = True 96 | count = 0 97 | sum_of_eigen_value = np.sum(array_of_eigen_values) 98 | filename = filepath.split('/')[-1].split('.')[0] 99 | 100 | out = list() 101 | 102 | print('\nEigen Values for partition : {} \n'.format(filename)) 103 | 104 | while more_than_zero: 105 | eigen_value = array_of_eigen_values[count] 106 | percent = eigen_value*100/sum_of_eigen_value 107 | cumulative_percentage += percent 108 | count += 1 109 | out.append([count,np.round(eigen_value, decimals=3), np.round(percent, decimals=3), np.round(cumulative_percentage,decimals=3)]) 110 | 111 | if np.round(eigen_value, decimals=3) == 0.0: 112 | more_than_zero = False 113 | 114 | out_df = pd.DataFrame(out, columns=['PC', 'E.V', 'Percentage', 'Cumulative Percent']) 115 | 116 | print(out_df) 117 | 118 | def show_eigen_values(self, pca_result_directory): 119 | 120 | files = glob.glob(pca_result_directory+'**/**.csv',recursive=True) 121 | 122 | for file in files: 123 | 124 | stat = pd.read_csv(file, header=None) 125 | 126 | _, eigen_values = self._fetch_array(stat) 127 | 128 | self._cumulative_sum_of_percentage(eigen_values, file) 129 | 130 | def _eigen_component_contribution(self,vectors, eigen_values, top, max_pc = 2): 131 | 132 | sorted_bands = list() 133 | 134 | mydtype = [('band', int), ('total', float)] 135 | 136 | vectors = vectors[:max_pc] 137 | 138 | contribution = zip(np.arange(len(vectors[0])), np.sum(vectors**2, axis=0)) 139 | 140 | for item in contribution: 141 | sorted_bands.append(item) 142 | 143 | sorted_bands = np.asarray(sorted_bands, dtype=mydtype) 144 | sorted_bands = np.sort(sorted_bands, order='total') 145 | 146 | x = sorted_bands[-1*top:] 147 | #print(x) 148 | 149 | bands = [] 150 | for band in x: 151 | #print(band[0]) 152 | bands.append(band[0]) 153 | 154 | return np.sort(bands) 155 | 156 | 157 | def _band_frequency_map(self,bands): 158 | sorted_bands = np.sort(bands, axis=None) 159 | 160 | bands_occurences = dict() 161 | 162 | for band in sorted_bands: 163 | if bands_occurences.get(band) == None: 164 | bands_occurences.update({band:1}) 165 | else: 166 | bands_occurences.update({band:bands_occurences.get(band)+1}) 167 | return bands_occurences 168 | 169 | def plot_band_frequncy(self,pca_result_directory, top, max_pc = 2, min_frequency=None): 170 | 171 | files = glob.glob(pca_result_directory+'**/**.csv',recursive=True) 172 | 173 | list_of_bands = list() 174 | 175 | for file in files: 176 | 177 | stat = pd.read_csv(file, header=None) 178 | 179 | vectors, eigen_values = self._fetch_array(stat) 180 | 181 | list_of_bands.append(self._eigen_component_contribution(vectors,eigen_values,top,max_pc)) 182 | 183 | band_occurances = self._band_frequency_map(list_of_bands) 184 | 185 | if min_frequency!=None: 186 | filtered_dictionary = {} 187 | for band in band_occurances: 188 | if band_occurances[band] >= min_frequency: 189 | filtered_dictionary.update({band:band_occurances[band]}) 190 | band_occurances = filtered_dictionary 191 | 192 | 193 | fig = plt.figure() 194 | fig.set_figwidth(30) 195 | fig.set_figheight(5) 196 | plt.bar(list(band_occurances.keys()),list(band_occurances.values()),align='center',width=0.6) 197 | plt.xticks( np.arange(max(list(band_occurances.keys()))+1),rotation=90) 198 | plt.grid(axis='y') 199 | plt.xlabel('Band Number') 200 | plt.ylabel('Number of occurences') 201 | plt.title('Total number of occurances in top {} bands for all {} images'.format(top,len(files))) 202 | plt.show() 203 | 204 | 205 | # Actutal Reduction 206 | 207 | 208 | def band_reduction(self,pca_result_directory,top,min_frequency, max_pc = 2): 209 | 210 | files = glob.glob(pca_result_directory+'**/**.csv',recursive=True) 211 | 212 | list_of_bands = list() 213 | 214 | for file in files: 215 | 216 | stat = pd.read_csv(file, header=None) 217 | 218 | vectors, eigen_values = self._fetch_array(stat) 219 | 220 | list_of_bands.append(self._eigen_component_contribution(vectors,eigen_values,top,max_pc)) 221 | 222 | band_occurances = self._band_frequency_map(list_of_bands) 223 | 224 | frequent_bands = [] 225 | 226 | for band in band_occurances: 227 | if band_occurances.get(band) >= min_frequency: 228 | #print(band,':',bands_occurences.get(band)) 229 | frequent_bands.append(band) 230 | 231 | return frequent_bands 232 | 233 | 234 | 235 | 236 | 237 | 238 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/prepare_training_data/__init__.py: -------------------------------------------------------------------------------- 1 | from .prepare_training_data import prepare_training_data 2 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/prepare_training_data/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/prepare_training_data/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/prepare_training_data/__pycache__/prepare_training_data.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/prepare_training_data/__pycache__/prepare_training_data.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/prepare_training_data/prepare_training_data.py: -------------------------------------------------------------------------------- 1 | from spectral import open_image 2 | import pandas as pd 3 | import spectral.io.aviris as aviris 4 | import numpy as np 5 | import matplotlib.pyplot as plt 6 | import sys 7 | import glob 8 | import matplotlib.colors 9 | import matplotlib as mt 10 | import numpy.linalg as lin 11 | 12 | class prepare_training_data: 13 | 14 | def __init__(self,img_source_dir="",save_path="",noisy_bands=None): 15 | 16 | self._img_source = img_source_dir 17 | self._save_path = save_path 18 | self._noisy_bands = noisy_bands 19 | 20 | 21 | def extract(self): 22 | 23 | if self._img_source =="": 24 | print('Please give path to extracted crops directory.\n') 25 | if self._save_path == "": 26 | print('Please give path to save tranin') 27 | 28 | crop_list = sorted(glob.glob(self._img_source+'*.hdr')) 29 | crop_names = list() 30 | 31 | print('\n------------------Preparing training dataset---------------------\n\n') 32 | 33 | print('Total {} crops are found in directory\n\n'.format(len(crop_list))) 34 | 35 | fw_w = open(self._save_path,'w') 36 | 37 | for index,path in enumerate(crop_list): 38 | 39 | crop_name = path.split('/')[-1].split('.')[0] 40 | 41 | crop_names.append(crop_name) 42 | 43 | if self._noisy_bands is not None: 44 | 45 | img = open_image(path) 46 | all_bands = set(np.arange(img.nbands)) 47 | img = img[:,:,list(all_bands-set(self._noisy_bands))] 48 | 49 | else: 50 | 51 | img = open_image(path) 52 | 53 | height = img.shape[0] 54 | width = img.shape[1] 55 | 56 | count = 0 57 | 58 | for i in range(height): 59 | for j in range(width): 60 | temp = img[i,j] 61 | if(np.mean(temp)>0): 62 | count += 1 63 | for band in range(temp.size): 64 | fw_w.write(str(temp[band])+",") 65 | fw_w.write(str(index+1)+'\n') 66 | print("Crop No. : {} \t| Name : {} \t\t| Tota samples : {}".format(index+1, crop_name, count)) 67 | 68 | print('\n\nProcess completed. File saved at : ',self._save_path) 69 | 70 | print('\n\nCrop List : ',crop_names) 71 | print('\n\n---------------------------------------------------------\n\n') 72 | 73 | fw_w.close() 74 | 75 | def outlier_analysis(self,data_path,class_labels): 76 | 77 | self._class_labels = class_labels 78 | 79 | train_data = pd.read_csv(data_path,header=None) 80 | self._train_data_array = np.asarray(train_data) 81 | 82 | low_dimentional = self._train_data_array[:,[57,85]] 83 | 84 | #Prepare a dictionary using train data for classwise array 85 | self._total_bands = train_data.shape[1]-1 86 | self._class_wise_data_array = dict() 87 | self._class_wise_data_array_full_dim = dict() 88 | 89 | for index,pixel in enumerate(low_dimentional): 90 | class_number = int(self._train_data_array[index,self._total_bands]) 91 | 92 | if self._class_wise_data_array.get(class_number) != None: 93 | self._class_wise_data_array[class_number].append(pixel) 94 | self._class_wise_data_array_full_dim[class_number].append(self._train_data_array[index,:self._total_bands]) 95 | else: 96 | self._class_wise_data_array.update({class_number:[]}) 97 | self._class_wise_data_array[class_number].append(pixel) 98 | 99 | self._class_wise_data_array_full_dim.update({class_number:[]}) 100 | self._class_wise_data_array_full_dim[class_number].append(self._train_data_array[index,:self._total_bands]) 101 | 102 | self._size = len(self._class_wise_data_array) 103 | 104 | mean_vector = [] 105 | cov_vector = [] 106 | 107 | for i in range(self._size): 108 | sum_vector = np.zeros(shape=(1,2)) 109 | total_class_sample = len(self._class_wise_data_array[i+1]) 110 | for j in range(total_class_sample): 111 | sum_vector += self._class_wise_data_array[i+1][j] 112 | 113 | mean_vector.append(np.divide(sum_vector,len(self._class_wise_data_array[i+1])) ) 114 | 115 | 116 | self._mean_vector = np.array(mean_vector).reshape(len(self._class_wise_data_array),2) 117 | 118 | print('\n\n------------------- Instructions -------------------\n\n') 119 | 120 | print('1. Use the visualise() method to plot two dimention representation of crops.\n') 121 | 122 | print('2. Use the remove_outliers() method to remove outliers. You can pass external limits with\n') 123 | 124 | print(""" rules = { 1:[0,0,0,0],2:[0,0,0,0]} as argument.\n\n You can pass Left, Right, Top, Bottom limits for manually remove outliers for any crop.\n """) 125 | 126 | print("\n3. Use save() method to save data after outlier removal.") 127 | 128 | 129 | def visualise(self): 130 | 131 | 132 | self._color = ['#FFFFFF','#3BCBD5','#F7CD0A','#990033','#FF3399','#339900','#666600', 133 | '#000000','#0000FF','#CC7755','#FF8866','#FF9988','#EF5350','#F48FB1', 134 | '#880E4F','#E1BEE7','#9FA8DA','#1E88E5','#26A69A', '#69F0AE','#FDD835', 135 | '#6D4C41','#546E7A','#B71C1C'] 136 | 137 | self._level = np.arange(len(self._color)+1) 138 | 139 | 140 | cmap , norm = matplotlib.colors.from_levels_and_colors(levels=self._level,colors=self._color) 141 | 142 | fig = plt.figure(figsize=(15,10),dpi=250) 143 | for index,crop in enumerate(self._mean_vector): 144 | label = str(index + 1)+' - '+ self._class_labels[index] +' : '+ str(len(self._class_wise_data_array[index+1])) 145 | plt.scatter(x=crop[0],y=crop[1],label=label,color=self._color[index+1],marker='o') 146 | 147 | for i in range(self._size): 148 | plt.scatter(x=np.array(self._class_wise_data_array[i+1])[:,0],y=np.array(self._class_wise_data_array[i+1])[:,1],color=self._color[i+1],marker='.',alpha=1) 149 | 150 | 151 | plt.legend(loc=1) 152 | plt.title('Visualization of crops in 2D') 153 | plt.xlabel('RED BAND - 57') 154 | plt.ylabel('NIR BAND - 85') 155 | plt.show() 156 | 157 | def _outlier_removal(self,class_num,arr,ext_left=0,ext_right=0,ext_top=0,ext_bottom=0): 158 | 159 | full_dim = self._class_wise_data_array_full_dim[class_num] 160 | 161 | Q1 = np.percentile(arr,25,axis=0) 162 | Q3 = np.percentile(arr,75,axis=0) 163 | 164 | IQR = Q3-Q1 165 | 166 | Upper_threshold = Q3 + IQR*1.5 167 | Lower_threshold = Q1 - IQR*1.5 168 | 169 | if ext_left >0: 170 | Lower_threshold[0] = ext_left 171 | if ext_bottom >0: 172 | Lower_threshold[1] = ext_bottom 173 | if ext_right >0: 174 | Upper_threshold[0] = ext_right 175 | if ext_top >0: 176 | Upper_threshold[1] = ext_top 177 | 178 | 179 | clean_arr = [] 180 | full_dim_arr = [] 181 | 182 | for index,pixel in enumerate(arr): 183 | if (pixel[0] <= Upper_threshold[0]) and (pixel[0] >= Lower_threshold[0]) and (pixel[1] <= Upper_threshold[1]) and (pixel[1] >= Lower_threshold[1]): 184 | clean_arr.append(pixel) 185 | full_dim_arr.append(full_dim[index]) 186 | 187 | return clean_arr, full_dim_arr 188 | 189 | def remove_outlier(self,rules=[]): 190 | 191 | external_rules = dict() 192 | 193 | for index in self._class_wise_data_array.keys(): 194 | external_rules.update({index:[0,0,0,0]}) 195 | 196 | for item in rules: 197 | external_rules.update({item:rules[item]}) 198 | 199 | 200 | self._clean_classwise_data = {} 201 | self._clean_fulldim_data = {} 202 | 203 | for index in self._class_wise_data_array.keys(): 204 | 205 | extern = external_rules[index] 206 | 207 | pc_arr,full_arr = self._outlier_removal(index,self._class_wise_data_array[index],extern[0],extern[1],extern[2],extern[3]) 208 | 209 | self._clean_classwise_data.update({index:np.array(pc_arr)}) 210 | 211 | self._clean_fulldim_data.update({index:np.array(full_arr)}) 212 | 213 | fig = plt.figure(figsize=(15,10),dpi=250) 214 | 215 | for index,crop in enumerate(self._mean_vector): 216 | label = str(index + 1)+'-'+ self._class_labels[index] +' : '+ str(len(self._clean_classwise_data[index+1])) 217 | plt.scatter(x=crop[0],y=crop[1],label=label,color=self._color[index+1],marker='o') 218 | 219 | for i in range(len(self._clean_classwise_data)): 220 | plt.scatter(x=np.array(self._clean_classwise_data[i+1])[:,0],y=np.array(self._clean_classwise_data[i+1])[:,1],color=self._color[i+1],marker='.',alpha=1) 221 | 222 | plt.legend(loc=1) 223 | plt.title('Visualization of crops in 2D') 224 | plt.xlabel('RED BAND - 57') 225 | plt.ylabel('NIR BAND - 85') 226 | plt.show() 227 | 228 | def save(self, path_to_save): 229 | 230 | fw_w = open(path_to_save,'w') 231 | 232 | for crop in self._clean_fulldim_data.keys(): 233 | for pixel in self._clean_fulldim_data[crop]: 234 | for i in range(self._total_bands): 235 | fw_w.write(str(pixel[i])+",") 236 | fw_w.write(str(crop)+"\n") 237 | 238 | fw_w.close() 239 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/preprocessing/_DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/preprocessing/_DS_Store -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/preprocessing/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | 4 | from .noise_removal import noise_removal 5 | from .preprocessing import preprocessing 6 | from .fit_in_memory import _fit_in_memory -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/preprocessing/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/preprocessing/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/preprocessing/__pycache__/fit_in_memory.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/preprocessing/__pycache__/fit_in_memory.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/preprocessing/__pycache__/noise_removal.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/preprocessing/__pycache__/noise_removal.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/preprocessing/__pycache__/preprocessing.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/preprocessing/__pycache__/preprocessing.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/preprocessing/fit_in_memory.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from spectral import open_image 5 | import numpy as np 6 | 7 | 8 | class _fit_in_memory: 9 | 10 | def __init__(self,img_path, available_memory_gb = 2 ): 11 | 12 | self._img = open_image(img_path) 13 | self._available_memory_bytes = available_memory_gb * 10**9 14 | self._nrows = self._img.nrows 15 | self._ncols = self._img.ncols 16 | self._nbands = self._img.nbands 17 | self._sample_size = self._img.sample_size 18 | 19 | 20 | def patitions(self): 21 | 22 | size_of_row_bytes = self._ncols * self._nbands * self._sample_size 23 | 24 | max_number_of_rows = self._available_memory_bytes // size_of_row_bytes 25 | 26 | last_block_row_count = self._nrows%max_number_of_rows 27 | 28 | total_blocks = int(np.ceil(self._nrows/max_number_of_rows)) 29 | 30 | if total_blocks == 1: 31 | list_of_partition = list([[0,self._nrows]]) 32 | return list_of_partition 33 | 34 | list_of_partition = list() 35 | 36 | for block in range(total_blocks): 37 | 38 | start_row = int(block*max_number_of_rows) 39 | 40 | block_rows_count = max_number_of_rows 41 | 42 | if block == total_blocks-1: 43 | block_rows_count = last_block_row_count 44 | 45 | end_row = int(start_row + block_rows_count) 46 | 47 | list_of_partition.append([start_row,end_row]) 48 | 49 | return list_of_partition -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/preprocessing/noise_removal.py: -------------------------------------------------------------------------------- 1 | from Hyspeclib.hyspeclib.hyperspectral_image import read_image 2 | import spectral.io.envi as envi 3 | import matplotlib.pyplot as plt 4 | import random as r 5 | import numpy as np 6 | 7 | 8 | 9 | class noise_removal: 10 | 11 | def __init__(self, image, ndvi_threshold = 125, NIR = 90 , RED = 55, min_threshold = 0, max_threshold = 1, data_ignore_value=-9999.0): 12 | 13 | self._image = read_image(image) 14 | 15 | self._height = self._image.img_height 16 | 17 | self._width = self._image.img_width 18 | 19 | self._bands = self._image.img_bands 20 | 21 | self._min_threshold = min_threshold 22 | 23 | self._max_threshold = max_threshold 24 | 25 | self._data_ignore_value = data_ignore_value 26 | 27 | self._NIR = NIR 28 | 29 | self._RED = RED 30 | 31 | self._ndvi_threshold = ndvi_threshold 32 | 33 | self._bands_list = np.arange(self._bands) 34 | 35 | 36 | 37 | def _only_vegetation(self, arr_reflectance): 38 | 39 | output_array = list() 40 | 41 | for each_pixel in arr_reflectance: 42 | 43 | if (each_pixel[0] != self._data_ignore_value) and (self._calculate_ndvi(each_pixel[self._NIR], each_pixel[self._RED]) >= self._ndvi_threshold) : 44 | 45 | output_array.append(np.array(each_pixel)) 46 | 47 | return np.array(output_array) 48 | 49 | 50 | def _random(self): 51 | 52 | r.seed(0) 53 | 54 | return list(map(lambda _: [r.randint(0,self._height-1),r.randint(0, self._width-1)], range(1000))) 55 | 56 | def _reflectance_stat(self): 57 | 58 | indices = self._random() 59 | 60 | arr_reflectance = [ self._image.sub_image()[index] for index in indices ] 61 | 62 | arr_reflectance_veg = self._only_vegetation(arr_reflectance) 63 | 64 | max_reflectance = np.max(arr_reflectance_veg,axis=0) 65 | 66 | min_reflectance = np.min(arr_reflectance_veg,axis=0) 67 | 68 | return min_reflectance, max_reflectance 69 | 70 | def _calculate_ndvi(self, NIR, RED): 71 | 72 | if NIR - RED == 0 : 73 | ndvi = 0 74 | else: 75 | ndvi = ( NIR - RED ) / ( NIR + RED ) 76 | ndvi = 100 + ndvi * 100 77 | 78 | return ndvi 79 | 80 | 81 | def mean_stat(self): 82 | 83 | indices = self._random() 84 | 85 | arr_reflectance = [ self._image.sub_image()[index] for index in indices ] 86 | 87 | arr_reflectance_veg = self._only_vegetation(arr_reflectance) 88 | 89 | noisy_bands = self.show_noisy_bands() 90 | 91 | good_bands = list(set(self._bands_list) - set(noisy_bands)) 92 | 93 | mean_val = np.mean(arr_reflectance_veg[:,good_bands]) 94 | 95 | max_value = np.max(arr_reflectance_veg[:,good_bands]) 96 | 97 | min_value = np.min(arr_reflectance_veg[:,good_bands]) 98 | 99 | stdv = np.std(arr_reflectance_veg[:][good_bands]) 100 | 101 | upper_bound = mean_val + 2*stdv 102 | 103 | lower_bound = mean_val - 2*stdv 104 | 105 | return {'mean':mean_val, "mean + 2*sigma":upper_bound, "mean - 2*sigma":lower_bound,"stdv":stdv,"max":max_value,"min":min_value} 106 | 107 | 108 | 109 | def reflectance_plot(self): 110 | 111 | min_reflectance, max_reflectance = self._reflectance_stat() 112 | 113 | for index,val in enumerate(max_reflectance): 114 | if val >= self._max_threshold: 115 | max_reflectance[index] = self._max_threshold + 0.1 116 | 117 | 118 | for index,val in enumerate(min_reflectance): 119 | if val <= self._min_threshold: 120 | min_reflectance[index] = self._min_threshold - 0.1 121 | 122 | 123 | plt.figure(figsize=(16,9),dpi=150) 124 | plt.scatter(self._bands_list,min_reflectance,color='r',label='Minimum value',marker='.') 125 | plt.scatter(self._bands_list,max_reflectance,color='b',label='Maximum value',marker='.') 126 | plt.hlines([self._min_threshold,self._max_threshold],0,self._bands,colors='grey',linestyles='dashed') 127 | plt.title('Minimum and Maximum reflectance - band wise') 128 | plt.xticks(np.arange(0,425,10), np.arange(0,425,10), rotation=90) 129 | plt.xlabel('Band number') 130 | plt.ylabel('Reflectance') 131 | plt.legend() 132 | plt.show() 133 | 134 | def show_noisy_bands_with_min_max(self): 135 | 136 | min_reflectance, max_reflectance = self._reflectance_stat() 137 | 138 | noisy_bands_min_max = [ (i,min_reflectance[i],max_reflectance[i]) for i in range(self._bands) if min_reflectance[i] < self._min_threshold or max_reflectance[i] > self._max_threshold ] 139 | 140 | return noisy_bands_min_max 141 | 142 | def show_noisy_bands(self): 143 | 144 | min_reflectance, max_reflectance = self._reflectance_stat() 145 | 146 | noisy_bands = [ i for i in range(self._bands) if min_reflectance[i] < self._min_threshold or max_reflectance[i] > self._max_threshold ] 147 | 148 | return noisy_bands 149 | 150 | 151 | def remove_bands(self, hdr_file, list_of_noisy_bands=None): 152 | """ 153 | Saves an image to disk. 154 | 155 | Arguments: 156 | 157 | `hdr_file` (str): 158 | 159 | Header file (with ".hdr" extension) name with path. 160 | 161 | `list_of_noisy_bands` (list) optional: 162 | 163 | If passed, bands specified in `list_of_noisy_bands` will be removed 164 | , otherwise noisy bands will be detected and removed automatically. 165 | 166 | 167 | """ 168 | 169 | if list_of_noisy_bands == None: 170 | discarded_bands = self.show_noisy_bands() 171 | else: 172 | discarded_bands = list_of_noisy_bands 173 | 174 | retained_bands = list(set(np.arange(self._bands)) - set(discarded_bands)) 175 | 176 | envi.save_image(hdr_file, self._image.sub_image()[:, :, retained_bands], interleave='bil', force=True, ext=None) 177 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/preprocessing/preprocessing.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from .fit_in_memory import _fit_in_memory 5 | from .noise_removal import noise_removal 6 | import spectral.io.envi as envi 7 | from ..hyperspectral_image import read_image 8 | import numpy as np 9 | import os 10 | 11 | 12 | 13 | class preprocessing: 14 | 15 | def __init__(self, img_path, save_directory, available_memory_gb): 16 | 17 | self._max = available_memory_gb 18 | self._img_path = img_path.split(".")[0] 19 | self._save_path = save_directory 20 | self._image_name = self._img_path.split('/')[-1].split('.')[0] 21 | 22 | partition = _fit_in_memory(self._img_path, available_memory_gb=self._max) 23 | 24 | self._list_of_partitions = partition.patitions() 25 | self._total_partitions = len(self._list_of_partitions) 26 | 27 | del partition 28 | 29 | print('Image will be saved in {} partitions.'.format(self._total_partitions)) 30 | 31 | def _calculate_ndvi(self, NIR, RED): 32 | 33 | if NIR - RED == 0 : 34 | ndvi = 0 35 | else: 36 | ndvi = ( NIR - RED ) / ( NIR + RED ) 37 | ndvi = 100 + ndvi * 100 38 | 39 | return ndvi 40 | 41 | def _get_retained_bands(self, noisy_bands, total_bands): 42 | 43 | return list(set(np.arange(total_bands)) - set(noisy_bands)) 44 | 45 | def perform(self, ndvi_threshold = 125, data_ignore_value = -9999. , NIR = 90 , RED = 55, min_threshold = 0, max_threshold = 1, noisy_bands=None): 46 | 47 | img = read_image(self._img_path) 48 | 49 | if noisy_bands == None: 50 | 51 | noise_rem = noise_removal(img,min_threshold=min_threshold, max_threshold=max_threshold) 52 | 53 | noisy_bands = noise_rem.show_noisy_bands() 54 | 55 | retained_bands = self._get_retained_bands(noisy_bands, img.img_bands) 56 | 57 | masking_pixel = [0.0 for i in range(len(retained_bands))] 58 | 59 | print('--------------- Performing Preprocessing ---------------\n') 60 | 61 | for index,each_partion in enumerate(self._list_of_partitions): 62 | 63 | print('\nPartition : {} / {} running...\n'.format(index+1, self._total_partitions)) 64 | 65 | sub_image = img.sub_image()[each_partion[0]:each_partion[1], :, retained_bands] 66 | 67 | sub_image[:, noisy_bands] = 0 68 | 69 | for index_row, each_row in enumerate(sub_image): 70 | 71 | for index_pixel, each_pixel in enumerate(each_row): 72 | 73 | 74 | if (each_pixel[0] == data_ignore_value) or (self._calculate_ndvi(each_pixel[NIR],each_pixel[RED]) < ndvi_threshold) : 75 | sub_image[index_row, index_pixel] = masking_pixel 76 | 77 | 78 | if not os.path.exists(self._save_path): 79 | os.makedirs(self._save_path) 80 | 81 | envi.save_image(self._save_path + self._image_name + '_part_' + str(index+1)+'.hdr', sub_image,force=True,interleave='bil',ext=None) 82 | 83 | del sub_image 84 | 85 | 86 | print('\nPreprocessing completed. Output directory : '+self._save_path) 87 | print('\n\n---------------------------------------------------------') 88 | 89 | 90 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/separability_analysis/_DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/separability_analysis/_DS_Store -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/separability_analysis/__init__.py: -------------------------------------------------------------------------------- 1 | from .separability_analysis import separability_analysis -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/separability_analysis/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/separability_analysis/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/separability_analysis/__pycache__/separability_analysis.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Hyspeclib/hyspeclib/separability_analysis/__pycache__/separability_analysis.cpython-36.pyc -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/separability_analysis/separability_analysis.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import numpy.linalg as lin 4 | import matplotlib.pyplot as plt 5 | 6 | 7 | class separability_analysis: 8 | 9 | def __init__(self,dataset_path): 10 | 11 | self._data = pd.read_csv(dataset_path, header=None) 12 | 13 | self._total_bands = self._data.shape[1] - 1 14 | 15 | self._classwise_groups = self._data.groupby([self._total_bands]) 16 | 17 | self._mean_vectors = np.array(self._classwise_groups.mean()) 18 | 19 | self._cov_vectors = list() 20 | 21 | self._n_classes = len(self._data[self._total_bands].unique()) 22 | 23 | for i in range(self._n_classes): 24 | self._cov_vectors.append(np.array(self._classwise_groups.get_group(i+1).cov())) 25 | 26 | self._corr_vectors = list() 27 | 28 | for i in range(self._n_classes): 29 | self._corr_vectors.append(np.array(self._classwise_groups.get_group(i+1).corr())) 30 | 31 | def _uncorrelated_bands(self,class_one, class_two, bands): 32 | 33 | freq = np.zeros((self._total_bands),dtype=np.int) 34 | 35 | for i in range(self._total_bands): 36 | for j in range(i,self._total_bands,1): 37 | if i!=j: 38 | if self._corr_vectors[class_one][i,j] > 0.99 : 39 | freq[i]+=1 40 | freq[j]+=1 41 | if self._corr_vectors[class_two][i,j] > 0.99 : 42 | freq[i]+=1 43 | freq[j]+=1 44 | 45 | bands_to_remove = [i for i in range(len(freq)) if freq[i] > 1] 46 | new_bands = list(set(bands) - set(bands_to_remove)) 47 | 48 | return new_bands 49 | 50 | def _jm(self,class_1, class_2, reduced_bands): 51 | 52 | bands = self._uncorrelated_bands(class_1,class_2,reduced_bands) 53 | 54 | mean_1 = self._mean_vectors[class_1][bands] 55 | mean_2 = self._mean_vectors[class_2][bands] 56 | cov_1 = self._cov_vectors[class_1][bands][:,bands] 57 | cov_2 = self._cov_vectors[class_2][bands][:,bands] 58 | 59 | mean_diff = mean_1 - mean_2 60 | mean_cov = ( cov_1 + cov_2 ) / 2 61 | 62 | jm_mean_dist = 0.125 * np.dot( np.dot(mean_diff.T , lin.inv(mean_cov)), mean_diff ) 63 | 64 | np.seterr(divide='ignore') 65 | 66 | jm_cov_dist = 0.5*np.log( lin.det(mean_cov) / np.sqrt(lin.det(cov_1)*lin.det(cov_2) )) 67 | 68 | alpha = jm_mean_dist + jm_cov_dist 69 | 70 | jm_dist = np.sqrt(2*(1-np.exp(-1*alpha))) 71 | 72 | return jm_dist 73 | 74 | def JM_distance_mat(self, bands): 75 | 76 | size = self._n_classes 77 | 78 | jm_mat = np.zeros(shape=(size,size),dtype=np.float) 79 | 80 | for i in range(size): 81 | for j in range(size): 82 | if i!=j: 83 | jm_mat[i,j] = self._jm(i,j,bands) 84 | else: 85 | jm_mat[i,j] = 0 86 | 87 | # Sorting inorder of JM Distance 88 | dtype = [('c1',int),('c2',int),('sep',float)] 89 | pairwise = [] 90 | avg = 0 91 | cnt = 0 92 | 93 | for i in range(size): 94 | for j in range(i+1,size): 95 | pairwise.append((i+1,j+1,jm_mat[i,j])) 96 | avg += jm_mat[i,j] 97 | cnt += 1 98 | avg = avg / cnt 99 | 100 | print("\nAverage JM Distance : ",avg,'\n\n') 101 | 102 | pairwise = np.array(pairwise, dtype=dtype) 103 | pairwise_sorted = np.sort(pairwise, order='sep') 104 | 105 | plt.figure(figsize=(size+2,size),dpi=80) 106 | heatmap = plt.pcolor(jm_mat,cmap='gray') 107 | 108 | for y in range(size): 109 | for x in range(size): 110 | plt.text(x + 0.5, y + 0.5, '%.4f' % jm_mat[x, y], 111 | horizontalalignment='center', 112 | verticalalignment='center', 113 | ) 114 | plt.yticks(np.arange(size)+0.5,np.arange(size)+1) 115 | plt.xticks(np.arange(size)+0.5,np.arange(size)+1) 116 | plt.colorbar(heatmap) 117 | plt.title('Class to class JM-Distance') 118 | 119 | plt.show() 120 | 121 | return pairwise_sorted 122 | -------------------------------------------------------------------------------- /Hyspeclib/hyspeclib/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | with open("README", 'r') as f: 4 | long_description = f.read() 5 | 6 | 7 | setup( 8 | name='hyspeclib', 9 | version='1.0', 10 | description='Deep learning library for crop classification using hyperspectral image', 11 | author='Hetul V Patel', 12 | author_email='hetulvp@gmail.com', 13 | packages=['hyspeclib'], #same as name 14 | install_requires=['pandas', 'spectral', 'tensorflow'], #external packages as dependencies 15 | ) 16 | -------------------------------------------------------------------------------- /Images/pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Images/pic1.png -------------------------------------------------------------------------------- /Images/pic2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Images/pic2.png -------------------------------------------------------------------------------- /Mini Project report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kandarpkakkad/GUI-For-Hyperspectral-Image-Preprocessing-Using-Python/a683ff71bf480e5e3f2d926e5b08b0d1fb8ba437/Mini Project report.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GUI For Hyperspectral Image Preprocessing Using Python 2 | 3 | ## 1. Introduction 4 | 5 | In layman’s language, remote recognizing is the checking of Earth by satel- 6 | lite or high-flying workmanship so as to get data concerning it. It’s essentially 7 | the investigation of getting data concerning articles or zones from a detachment, 8 | sometimes from claim to fame or satellites. 9 | 10 | Remote sensors collect learning by examination of the criticalness that is 11 | reflected from the planet. These sensors are on the satellites or mounted on the 12 | workmanship. 13 | 14 | Remote sensors are either inactive or dynamic. Standoffish sensors answer to 15 | outer redesigns. They record standard centrality that is reflected or discharged 16 | from the Earth’s surface. The essential ordinary supply of radiation perceived 17 | by inert sensors is reflected in the sunshine. 18 | 19 | In a refinement, dynamic sensors utilize inward upgrades to gather getting 20 | the hang of concerning Earth. For instance, an optical contraption shaft remote 21 | distinctive structure comes a laser onto the outside of Earth and measures the 22 | time that it takes for the laser to reflect back to its perceiving part. 23 | 24 |  25 | 26 | ## 2. Application of Remote Sensing 27 | 28 | Coastal applications: Screen bound changes, track dregs transport guide 29 | waterfront alternatives. This information is utilized for the seaside mapping 30 | and disintegration block. 31 | 32 | Ocean applications: Screen sea dissemination and the ebb and flow frame- 33 | works, live sea temperature and wave statures and track sea ice. This learning 34 | is won’t to higher see the seas and the best approach to best oversee sea assets. 35 | 36 | Hazard applications: Tack hurricanes, earthquakes, erosion and flooding. 37 | This knowledge is wont to assess the impacts of natural disaster and make readi- 38 | ness ways to be used before and once a venturous event. 39 | 40 | Natural resource management: Monitor land use, map wetlands, and 41 | outline life circumstances. This information is wont to limit the insidiousness 42 | that urban improvement has on the setting and bolster pick the most ideal ap- 43 | proach to manage the guarantee run of the mill assets. 44 | 45 | ## 3. Formats Of This Hyperspectral Image 46 | 47 | Multiband image data are represented by a combination of spatial position 48 | (pixel number and line number) and band. The data format for remote sensing 49 | images is classified into the following three types: 50 | 51 | **BSQ:** Band SeQuential image data (pixel number and line number) of each band 52 | are separately stored. 53 | 54 | **BIL:** Band Interleaved by Line data are arranged in the order of band number 55 | and repeated with respect to the line number. 56 | 57 | **BIP:** Band Interleaved by Pixel data with respect to each pixel arranged spa- 58 | tially by pixel number and line number. 59 | 60 | For shading picture yield, BSQ organization would be helpful on the grounds 61 | that three groups will be doled out to R, G and B. Anyway BIP arrangement 62 | would be better for characterization by most extreme probability classifier in 63 | light of the fact that multi-band information are required pixel by pixel for the 64 | multi-variable handling. BIL would be a trade off among BSQ and BIP. 65 | 66 | Remote detecting data some of the time incorporates various explanation 67 | information also to picture information. So the satellite picture information 68 | have been given in a standard organization called World Standard Format (as 69 | a rule utilizes BSQ or BIL format), or LTWG position (indicated via Landsat 70 | Technical Working Group). 71 | 72 | ## 4. Reflectance Value of Hyperspectral Images 73 | 74 | Each non-living or living body reflects also ingests transmissions by numer- 75 | ous sources. Presently the satellites transmit flag which is pondered by items 76 | Earth. Each material assimilates an alternate measure of transmissions and re- 77 | flects an alternate measure of transmissions. 78 | 79 | The reflected flag figures out which object is there and stores the reflectance 80 | esteems. There are 425 groups which store distinctive snippets of data of a 81 | pixel and has diverse reflectance esteems for various wavelengths. By plotting 82 | of reflectance esteems versus wavelengths chart we can realize which object it is 83 | and furthermore the qualities of that object. 84 | 85 |  86 | 87 | ## 5. Classification of Reflectance Values 88 | 89 | The classification of the objects can be done on the basis of wavelengths. 90 | Few examples are given below. 91 | 92 | **Vegetation:** Chlorophyll being green acclimatizes light at wavelength around 0.45m 93 | (blue) and 0.67m (red) and reflect immovably in green light, in this man- 94 | ner our eyes see strong vegetation as green. Strong plants have a high 95 | reflectance in close infrared some place in the scope of 0.7m and 1.3m. 96 | This is fundamentally a result of the inside structure of plant leaves. As 97 | the inside structure of leaves varies from plant to plant. This urges us to 98 | understand which plant is there. 99 | 100 | **Water:** In the liquid state, water has commonly low reflectance, with clear wa- 101 | ter having the best reflectance in the blue portion of the unmistakable 102 | piece of the range. Water has high absorption and no reflectance in the 103 | nearby infrared wavelengths extend.Turbid water has high reflectance in 104 | evident district than clear water. This is moreover substantial for wa- 105 | ters containing vegetation. Ice and snow all things considered have high 106 | reflectance over each perceptible wavelength. Reflectance reduces in the 107 | nearby infrared section and there is low reflectance in shortwave infrared. 108 | 109 | **Soil:** Exposed soil, for the most part, has to expand reflectance, with more 110 | noteworthy reflectance in close infrared and shortwave infrared. A few 111 | variables influencing the reflectance are: 112 | 113 | - **Moisture Content** 114 | 115 | - **Soil Texture** 116 | 117 | - **Surface Roughness** 118 | 119 | - **Presence of FeO 2 and Fe 2 O 3** 120 | 121 | - **Moisture Content** 122 | 123 | ## 6. GUI Usage 124 | 125 | The GUI, presented above is made in python using Tkinter library. This 126 | library contains functions like Button, Menu, Canvas, Frame, etcetera. I also 127 | used classes like filedialog. This class contains functions used to open a dialog 128 | box to navigate hrough computer drives and select the file. 129 | 130 | Here I first created a frame in which we will be making other features like 131 | buttons or menu or even loading the photo. After that I created a navigation 132 | menu bar which contains options like File and Edit which contains options like: 133 | 134 | - **File: ”Open”, ”Save”, ”Exit”** 135 | 136 | - **Edit: ”Bands”** 137 | 138 | - **Quit: ”Quit”** 139 | 140 | #### 6.1 File 141 | 142 | The Open option will open a dialog box which will be used to select the 143 | .ENVI file which then will be used to load the hyperspectral image. The Save 144 | option will save the current modified image as .ENVI file or any other as per 145 | users choice. The Exit option will close the window and the program will shut 146 | down. 147 | 148 | The Open option opens a dialog box and allows us to select the image to 149 | open. For this I used the spectral library of python from which I used io class 150 | and envi function. 151 | 152 | #### 6.2 Edit 153 | 154 | The ”Edit” menu contains ”Bands” option which will open a window in 155 | which the user have to enter 3 values i.e the bands which will show the image 156 | in having the entered bands. 157 | 158 | #### 6.3 Graph 159 | 160 | The graph in one the image above is created by Spectral library. This 161 | library has an in-built function that will show the graph of reflectance values 162 | vs wavelength. This graph gives us the information of the object present in the 163 | pixel selected. 164 | 165 | #### 6.4 Preprocessing 166 | 167 | The bands having negative values are not used and so we need to remove it. 168 | For that I used a library called Hyspeclib. This library gives eigenvavlues and 169 | minimum and maximum reflectance values so that we can remove the negative 170 | values. Usually the negative values are -9999 and so it is easy to know them 171 | and remove them. 172 | 173 | After their removal, the image is saved in two parts where the original image 174 | is stored and then the saved image is opened. This image does not contain 175 | reflectance values that are negative. 176 | 177 | ## 7. References 178 | 179 | - https://www.rsipvision.com/image-processing-for-precise-agriculture/ 180 | 181 | - https://dialnet.unitioja.es/descarga/articulo/5178334.pdf 182 | 183 | - http://gsp.humboldt.edu/OLM/Courses/GSP_216_Online/lesson2-1/reflectance.html 184 | 185 | - http://www.spectralpython.net/ 186 | 187 | - https://github.com/hetul-patel/hyspeclib 188 | 189 | ## 8. Acknowledgement 190 | 191 | I would like to express my deepest appreciation to all those who provided me 192 | with the possibility to complete this project. I acknowledge with thanks, the 193 | support rendered by Prof. Tarjani Vyas and Junior Research fellow Kinjal 194 | Dave, under whose support I was able to complete the task in a given period 195 | of time. I also appreciate the constructive suggestions given by my friends to 196 | further enhance the content of the project and report. At the home front, I am extremely 197 | grateful to my family members for the support and encouragement I got from 198 | them in successfully completing the project. 199 | 200 | ## 9. Run The Code 201 | 202 | Intall the requirements from requirements.txt. 203 |
204 | pip3 install -r requirements.txt 205 |206 | To run the program run the Front_End_GUI.py file. 207 |
208 | python3 Front_End_GUI.py 209 |210 | 211 | ## 10. To-Do 212 | 213 | - [ ] Identifying the region based on reflectance value. 214 | - [ ] Using clustering algorithms to predict the region. 215 | - [ ] Format the code to a more readable format. 216 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /open_save.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from tkinter.simpledialog import askstring, askinteger, askfloat 3 | import numpy as np 4 | import os 5 | from tkinter import filedialog 6 | from tkinter import messagebox 7 | from spectral.io.envi import * 8 | import spectral.io.envi as envi 9 | from spectral import imshow 10 | import os 11 | import functools 12 | import Hyspeclib.hyspeclib as hy 13 | 14 | # Check if the function is called 15 | 16 | def calltracker(func): 17 | @functools.wraps(func) 18 | def wrapper(*args): 19 | wrapper.has_been_called = True 20 | return func(*args) 21 | wrapper.has_been_called = False 22 | return wrapper 23 | 24 | 25 | @calltracker 26 | 27 | # Open a file by browsing 28 | 29 | def open_file(): 30 | open_file.has_been_called = True 31 | filedialog.askopenfilename.has_been_called = True 32 | file_name = filedialog.askopenfilename(initialdir=os.path.expanduser("/"), filetypes=(("ENVI", "*.envi"), ("All files", "*"))) 33 | if str(file_name).endswith(".envi"): 34 | img = envi.open(file_name + ".hdr", file_name + ".envi") 35 | else: 36 | img = envi.open(file_name + ".hdr", file_name) 37 | file_save = file_name.split('/') 38 | file_save = file_save[:-1] 39 | save_dir = "" 40 | for string in file_save: 41 | save_dir = save_dir + string + "/" 42 | print(save_dir) 43 | filedialog.askopenfilename.has_been_called = False 44 | imshow.has_been_called = True 45 | imshow(img, bands=(55, 32, 20), aspect=0.45, stretch=0.25) 46 | print(img) 47 | print(file_name) 48 | noisy_bands_info = hy.noise_removal(file_name, min_threshold=0, max_threshold=0.55) 49 | noisy_bands_info.reflectance_plot() 50 | print("--------- List of noisy bands ---------") 51 | x = noisy_bands_info.show_noisy_bands_with_min_max() 52 | print(len(x)) 53 | for values in x: 54 | print(values) 55 | nb = noisy_bands_info.show_noisy_bands() 56 | pre = hy.preprocessing(img_path=file_name.split(".")[0] + ".hdr", save_directory=save_dir, available_memory_gb=8) 57 | pre.perform(ndvi_threshold=125, data_ignore_value=-9999.0, NIR=90, RED=55, min_threshold=0, max_threshold=0.55, noisy_bands=nb) 58 | file2_header = file_name + "_part_1" 59 | pre_image = envi.open(file2_header+".hdr",file2_header) 60 | imshow(pre_image, bands=(55, 32, 20), aspect=0.45, stretch=0.25) 61 | imshow.has_been_called = True 62 | print(pre_image) 63 | if imshow.has_been_called == False and filedialog.askopenfilename.has_been_called == False: 64 | open_file.has_been_called = False 65 | 66 | 67 | 68 | 69 | 70 | def open_band(): 71 | file_name = filedialog.askopenfilename(initialdir=os.path.expanduser("/"), filetypes=(("ENVI", "*.envi"), ("All files", "*"))) 72 | if str(file_name).endswith(".envi"): 73 | img = envi.open(file_name + ".hdr", file_name + ".envi") 74 | else: 75 | img = envi.open(file_name + ".hdr", file_name) 76 | 77 | def ret(x, y, z, s, a): 78 | return x, y, z, s, a 79 | 80 | x, y, z, stretch, aspect = ret(int(input("x: ")), int(input("y: ")), int(input("z: ")), int(input("stretch:")), int(input("aspect: "))) 81 | 82 | open_band.has_been_called = True 83 | imshow(img, bands=(x, y, z), aspect=aspect, stretch=stretch) 84 | print(img) 85 | 86 | # Save an opened file 87 | 88 | def save(): 89 | file_name = filedialog.askopenfilename(initialdir=os.path.expanduser("/"), filetypes=(("ENVI", "*.envi"), ("All files", "*"))) 90 | save_dir = filedialog.askdirectory() 91 | myfile = envi.open(file_name + ".hdr") 92 | imageArray = 10000 * myfile[:, :, :] 93 | save_file = envi.save_image(save_dir + file_name.split("/")[-1] + ".hdr", imageArray, dtype=np.int16, metadata=myfile.metadata, force=True) 94 | return save_file 95 | 96 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | tk 2 | spectral 3 | functools 4 | --------------------------------------------------------------------------------