├── .gitattributes ├── .gitignore ├── License.md ├── OriginalImage.JPG ├── Readme.md ├── SatelliteClassification.java ├── SplitTrainingAndTesting.R ├── afterFilter.JPG ├── beforeFilter.JPG ├── ensemble_final.R ├── featureSelection.R ├── mlp.JPG ├── mlpf1.JPG ├── modeFilter.R ├── postProcessing_AllClasses.R ├── postProcessing_onlyWater.R └── preprocessing_totalImage.R /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Krishna Karthik Gadiraju 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /OriginalImage.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkgadiraju/SatelliteImageClassification/2f5138bc85ab94cbe78d9aab16b8c3a810fce168/OriginalImage.JPG -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # SatelliteImageClassification 2 | Pixel based classification of satellite imagery 3 | - sample training and testing points generated using Point Sampling plugin in QGIS 4 | - feature generation using Orfeo Toolbox 5 | - feature selection using Learning Vector Quantization 6 | - CLassification using Decision Tree, Neural Networks, Random Forests, KNN and Naive Bayes Classifier 7 | - Ensemble classifier for Flood Inundation Mapping - classifies a pixel as water if 2 or more than 2 of the above classifiers classify a pixel as water 8 | - Mode filter used to remove individually wrongly classified pixels 9 | - Classification accuracy to measure goodness of each model 10 | 11 | Outcomes of the best classifier (Multi Layer Perceptron) are as shown below: 12 | 13 | To compile and run SatelliteClassification.java, you need weka.jar that you can download from the Weka website. 14 | 15 | ``` 16 | Compile code: javac -cp weka.jar SatelliteClassification.java 17 | Run code: java -cp weka.jar:. SatelliteClassification "trainingFile" "testingFile" "classifiername" 18 | ``` 19 | 20 | - order: 21 | 22 | |clouds: white | 23 | |roads: yellow | 24 | |shadow: black | 25 | |urban: pink | 26 | |vegetation: green | 27 | |water: blue | 28 | 29 | 30 | 31 | 34 | 37 | 38 | 39 | 42 | 45 | 46 | 49 | 52 | 53 | 54 | 57 | 60 | 61 |
32 | Original LANDSAT 8 Image during Flooding 33 | 35 | Multi Layer Perceptron Classification 36 |
40 | Original LANDSAT 8 Image during Flooding 41 | 43 | Multi Layer Perceptron Classification 44 |
47 | Ensemble Classifier: Water vs Everything, without filtering 48 | 50 | Ensemble Classifier: Water vs Everything, after mode filtering 51 |
55 | Ensemble Classifier 56 | 58 | Ensemble Classifier - After Mode Filter 59 |
62 | 63 | 64 | 65 | References: 66 | - LANDSAT-8 imagery(http://earthexplorer.usgs.gov/) 67 | - Image Preprocessing - QGIS (http://www.qgis.org/en/site/), ArcGIS (https://www.arcgis.com/features/index.html) 68 | - Feature selection performed using Orfeo Toolbox (https://www.orfeo-toolbox.org/) 69 | - Feature Selection: Vatsavai, Ranga Raju. "High-resolution urban image classification using extended features." In 2011 IEEE 11th International Conference on Data Mining Workshops, pp. 869-876. IEEE, 2011. 70 | -------------------------------------------------------------------------------- /SatelliteClassification.java: -------------------------------------------------------------------------------- 1 | /* 2 | Krishna Karthik Gadiraju / kkgadiraju 3 | Classify satellite attributes using weka 4 | Source: Weka Home page and tutorials 5 | 6 | To compile this code: javac -cp path-to-your-weka.jar-file SatelliteClassification.java 7 | To run this code: java -cp weka.jar:. SatelliteClassification "may28-trainingTop10-AllBands-final.arff" "may28-testingTop10-AllBands-final.arff" "classifier-name" 8 | 9 | Tested java version: openjdk version "1.8.0_102" 10 | OpenJDK Runtime Environment (build 1.8.0_102-b14) 11 | 12 | Operating System: Red Hat Enterprise 7.2 13 | 14 | */ 15 | 16 | import java.io.File; 17 | import java.io.FileNotFoundException; 18 | import weka.core.converters.CSVSaver; 19 | import weka.classifiers.Classifier; 20 | import weka.classifiers.Evaluation; 21 | import weka.classifiers.bayes.NaiveBayes; 22 | import weka.classifiers.trees.RandomForest; 23 | import weka.classifiers.trees.J48; 24 | import weka.classifiers.functions.MultilayerPerceptron; 25 | import weka.classifiers.lazy.IBk; 26 | import weka.core.Attribute; 27 | import weka.core.Instance; 28 | import weka.core.Instances; 29 | import weka.core.converters.ConverterUtils.DataSource; 30 | 31 | 32 | 33 | public class SatelliteClassification { 34 | public static void main(String[] args){ 35 | DataSource training=null,testing=null; 36 | Instances trData=null, teData=null; 37 | if(args.length<3){ 38 | System.out.println("Enter 2 paths and type of classifier (nBayes, j48, randomForest, knn or mlp) as command line arguments: training,testing"); 39 | System.exit(0); 40 | } 41 | System.out.println("Training data source: "+args[0]); 42 | System.out.println("Testing data source: "+args[1]); 43 | System.out.println("Classifier type: "+args[2]); 44 | try { 45 | //link to files 46 | long startTime = System.nanoTime(); 47 | training = new DataSource(args[0]); 48 | testing = new DataSource(args[1]); 49 | //read the file 50 | trData = training.getDataSet(); 51 | teData = testing.getDataSet(); 52 | System.out.println("Finished reading datasets....."); 53 | if(training!=null && testing!=null){ 54 | System.out.println("Dataset structure....."); 55 | System.out.println(training.getStructure()); 56 | System.out.println(testing.getStructure()); 57 | 58 | //Set class attribute 59 | if (trData.classIndex() == -1) 60 | trData.setClassIndex(trData.numAttributes()-1); 61 | if (teData.classIndex() == -1) 62 | teData.setClassIndex(teData.numAttributes()-1); 63 | Classifier cModel; 64 | //Train classifiers 65 | switch(args[2]) { 66 | case "nbayes": 67 | cModel = (Classifier) new NaiveBayes(); 68 | break; 69 | case "j48": 70 | cModel = (Classifier)new J48(); 71 | break; 72 | case "randomForest": 73 | cModel = (Classifier)new RandomForest(); 74 | break; 75 | case "mlp": 76 | cModel = (Classifier)new MultilayerPerceptron(); 77 | break; 78 | case "knn": 79 | cModel = (Classifier)new IBk(10); 80 | break; 81 | default: 82 | System.out.println("Incompatible classifier name given, using Naive Bayes by default"); 83 | cModel = (Classifier) new NaiveBayes(); //Set to naive bayes by default 84 | 85 | } 86 | cModel.buildClassifier(trData); 87 | // create copy 88 | Instances teResults = new Instances(teData); 89 | // label instances 90 | for (int i = 0; i < teResults.numInstances(); i++) { 91 | double clsLabel = cModel.classifyInstance(teData.instance(i)); 92 | teResults.instance(i).setClassValue((int)clsLabel); 93 | } 94 | 95 | //write output to CSV 96 | CSVSaver outFile = new CSVSaver(); 97 | outFile.setFile(new File(args[2]+".csv")); 98 | outFile.setInstances(teResults); 99 | outFile.writeBatch(); 100 | long endTime = System.nanoTime(); 101 | System.out.println("Finished execution in"+(endTime-startTime)/1000000+" seconds"); 102 | 103 | } 104 | else{ 105 | System.out.println("File read incorrectly....."); 106 | } 107 | } catch (Exception e) { 108 | // TODO Auto-generated catch block 109 | e.printStackTrace(); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /SplitTrainingAndTesting.R: -------------------------------------------------------------------------------- 1 | ################################################ 2 | ##Read extracted CSV, verify properties 3 | # split into training and test 4 | # Krishna Karthik Gadiraju/kgadira 5 | ################################################ 6 | 7 | 8 | 9 | 10 | rm(list=ls(all=T)) 11 | library(rgdal) 12 | library(rgeos) 13 | library(foreign) 14 | 15 | data.all <- read.csv('may28TrainingAllBandsFinal.csv') #contains all sampled points generated using 16 | #point sampling tool in QGIS 17 | 18 | x2 <- sample(1:nrow(data.all),nrow(data.all),replace=F) 19 | data.all <- data.all[x2,] 20 | 21 | #messed up the original id attribute in QGIS, redo it 22 | id <- seq.int(nrow(data.all)) 23 | data.all$id <- id 24 | 25 | 26 | #Split data into training and testing - Assume 60,40 ratio 27 | colnames(data.all)[4] <- 'Class' 28 | data.all$Class <- as.factor(data.all$Class) 29 | 30 | data.all.split <- split(data.all,data.all$Class,drop=T) 31 | data.training<- data.frame() 32 | data.testing <- data.frame() 33 | #colnames(data.training) <- colnames(data.all) 34 | 35 | for( i in 1:6){ 36 | current <- data.frame(data.all.split[i]) 37 | colnames(current) <- colnames(data.all) 38 | noSamples <- nrow(current) 39 | noTraining <- ceiling(0.6*noSamples) 40 | x2 <- sample(1:nrow(current),noTraining,replace=F) 41 | data.training <- rbind(data.training,current[x2,]) 42 | data.testing <- rbind(data.testing, current[-x2,]) 43 | } 44 | 45 | #remove X,Y, id attribute - we don't use them 46 | data.training <- data.training[,-c(1:3)] 47 | data.testing <- data.testing[,-c(1:3)] 48 | 49 | #Write down CSV and/or arff files 50 | write.csv(x=data.training,'may28-training-AllBands-final.csv',row.names = F) 51 | write.arff(data.training,file='may28-training-AllBands-final.arff',relation='training') 52 | 53 | write.csv(x=data.testing,'may28-testing-AllBands-final.csv',row.names = F) 54 | write.arff(data.testing,file='may28-testing-AllBands-final.arff',relation='testing') 55 | 56 | 57 | -------------------------------------------------------------------------------- /afterFilter.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkgadiraju/SatelliteImageClassification/2f5138bc85ab94cbe78d9aab16b8c3a810fce168/afterFilter.JPG -------------------------------------------------------------------------------- /beforeFilter.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkgadiraju/SatelliteImageClassification/2f5138bc85ab94cbe78d9aab16b8c3a810fce168/beforeFilter.JPG -------------------------------------------------------------------------------- /ensemble_final.R: -------------------------------------------------------------------------------- 1 | #Read outputs from other classifiers, convert into water vs everything else, 2 | # identify a pixel as water if atleast two classifiers have identified it as water 3 | # important to ensure that we don't miss any water pixels 4 | 5 | library(rgdal) 6 | library(rgeos) 7 | library(foreign) 8 | 9 | 10 | #read classified file 11 | classifiednb <- read.csv('nbpredict_10bands.csv') 12 | classifieddt <- read.csv('dtpredict_10bands.csv') 13 | classifiedrf <- read.csv('rfpredict_10bands.csv') 14 | classifiedmlp <- read.csv('mlppredict_10bands.csv') 15 | classifiedknn <- read.csv('knnpredict_10bands.csv') 16 | 17 | classifiednb[which(classifiednb$Class!=6),]$Class <-1 #not water 18 | classifiednb[which(classifiednb$Class==6),]$Class <-2 # water 19 | 20 | classifieddt[which(classifieddt$Class!=6),]$Class <-1 21 | classifieddt[which(classifieddt$Class==6),]$Class <-2 22 | 23 | classifiedrf[which(classifiedrf$Class!=6),]$Class <-1 24 | classifiedrf[which(classifiedrf$Class==6),]$Class <-2 25 | 26 | classifiedmlp[which(classifiedmlp$Class!=6),]$Class <-1 27 | classifiedmlp[which(classifiedmlp$Class==6),]$Class <-2 28 | 29 | classifiedknn[which(classifiedknn$Class!=6),]$Class <-1 30 | classifiedknn[which(classifiedknn$Class==6),]$Class <-2 31 | 32 | 33 | classifiednb$Class <- as.factor(classifiednb$Class) 34 | classifieddt$Class <- as.factor(classifieddt$Class) 35 | classifiedrf$Class <- as.factor(classifiedrf$Class) 36 | classifiedmlp$Class <- as.factor(classifiedmlp$Class) 37 | classifiedknn$Class <- as.factor(classifiedknn$Class) 38 | 39 | classifiedEnsemble <- data.frame() 40 | 41 | 42 | classifiedEnsemble<- classifiednb #copy the data over 43 | 44 | 45 | x <- cbind(classifiednb$Class,classifieddt$Class,classifiedrf$Class,classifiedmlp$Class,classifiedknn$Class) 46 | # identify a pixel as water if atleast two classifiers have identified it as water 47 | # important to ensure that we don't miss any water pixels 48 | getLabel <- function(i,x){ 49 | sum(x[i,]==2)>=2 50 | 51 | } 52 | 53 | print('Begninning assigning labels') 54 | 55 | counts <- sapply(1:nrow(x),getLabel,x) 56 | 57 | classifiedEnsemble$Class <- 1 58 | classifiedEnsemble$Class[counts]<-2 59 | 60 | print('Finished assigning labels') 61 | 62 | myImg1 <- readGDAL('Clip-May28-Composite.TIF') 63 | 64 | col1 = matrix(0, nrow = 2, ncol = 3) 65 | col1[1, ] = c(255, 255, 255) # black everything else 66 | col1[2, ] = c(0, 0, 255) # blue water 67 | 68 | 69 | 70 | colorize1 <- function(d) 71 | { 72 | for(i in 1:3) 73 | { 74 | d[, i] <- rep(col1[d[1, 11], i], nrow(d)) 75 | } 76 | d 77 | } 78 | 79 | print('Beginning to add colors') 80 | colnames(classifiedEnsemble) <- c('band4','band3','Aerosol','energy','band2','invDiffM','SWIR1','SWIR2','diffEntr','inertia','Class') 81 | 82 | print(colnames(classifiedEnsemble)) 83 | 84 | classifiedEnsemble$ID <- seq.int(nrow(classifiedEnsemble)) #reorder slides to original order 85 | 86 | t1 <- split(classifiedEnsemble, classifiedEnsemble$Class, drop = T) 87 | t1 <- lapply(t1, FUN = colorize1) 88 | x1 <- do.call("rbind", t1) 89 | x1 <- x1[order(x1$ID), ] 90 | 91 | x1 <- x1[,-c(12)] 92 | #write.csv(x=x1,file='ensemblepredict_10bands.csv',row.names=F) 93 | x1 <- x1[, -c(4,5,6,7,8,9,10,11)] 94 | colnames(x1) <-c('band4','band3','band2') 95 | 96 | myImg1@data[,c('band4','band3','band2')]<-x1 97 | 98 | writeGDAL(myImg1, fname = "./Ensembletiff_OVO_10bands.tif") 99 | print('Write completed') 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /featureSelection.R: -------------------------------------------------------------------------------- 1 | ################################################ 2 | #Feature selection using Learning Vector Quantization 3 | # Source: http://machinelearningmastery.com/feature-selection-with-the-caret-r-package/ 4 | # Krishna Karthik Gadiraju/kgadira 5 | ################################################ 6 | 7 | 8 | rm(list=ls()) 9 | 10 | 11 | library('mlbench') 12 | library('caret') 13 | library('pROC') 14 | 15 | data.training <- read.csv('may28-training-AllBands-final.csv') 16 | data.testing <- read.csv('may28-testing-AllBands-final.csv') 17 | data.training$Class <- as.factor(data.training$Class) #Convert to factor 18 | data.testing$Class <- as.factor(data.testing$Class) #convert to factor 19 | control <- trainControl(method="repeatedcv", number=10, repeats=3) #we can explore more by changing these params 20 | 21 | model <- train(Class~., data=data.training, method="lvq", preProcess="scale", trControl=control) 22 | # estimate variable importance 23 | importance <- varImp(model, scale=FALSE) 24 | # summarize importance 25 | print(importance) 26 | # plot importance 27 | plot(importance) 28 | 29 | #Based on this, take top 10 most important variables and Class variable 30 | top10 <- c('R','G','Aerosol','energy','B','invDiffM','SWIR1','SWIR2','diffEntr','inertia','Class') 31 | 32 | data.training.final <- data.training[,top10] 33 | data.testing.final <- data.testing[,top10] 34 | 35 | #Write down CSV and/or arff files to use for prediction 36 | #write.csv(x=data.training.final,'may28-trainingTop10-AllBands-final.csv',row.names = F) 37 | write.arff(data.training.final,file='may28-trainingTop10-AllBands-final.arff',relation='training') 38 | 39 | #write.csv(x=data.testing.final,'may28-testingTop10-AllBands-final.csv',row.names = F) 40 | write.arff(data.testing.final,file='may28-testingTop10-AllBands-final.arff',relation='testing') 41 | -------------------------------------------------------------------------------- /mlp.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkgadiraju/SatelliteImageClassification/2f5138bc85ab94cbe78d9aab16b8c3a810fce168/mlp.JPG -------------------------------------------------------------------------------- /mlpf1.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkgadiraju/SatelliteImageClassification/2f5138bc85ab94cbe78d9aab16b8c3a810fce168/mlpf1.JPG -------------------------------------------------------------------------------- /modeFilter.R: -------------------------------------------------------------------------------- 1 | #Mode filter, takes 5*5 neighborhood, removes noisy classified pixels. 2 | # considers a 5*5 neighborhood, pixel value of middle pixel is equal to water if there are atleast 12 water pixels 3 | # classified as not water otherwise 4 | 5 | library(rgdal) 6 | library(rgeos) 7 | library(foreign) 8 | 9 | 10 | infile.name.noExt <- 'ensemblepredict_10bands' 11 | infile.name <- paste(infile.name.noExt,'.csv',sep='') 12 | 13 | outfile.csv <- paste(infile.name.noExt,'_relaxedIterative_10bands_All.csv',sep='') 14 | outfile.tif <- paste(infile.name.noExt,'_relaxedIterative_10bands_All.tif',sep='') 15 | 16 | 17 | #read classified file 18 | labelled.data <- read.csv(infile.name) 19 | colnames(labelled.data) <- c('band4','band3','Aerosol','energy','band2','invDiffM','SWIR1','SWIR2','diffEntr','inertia','Class') 20 | 21 | labelled.data$Class <- as.factor(labelled.data$Class) 22 | 23 | 24 | ExtractNeighbors <- function(i,class.list){ 25 | #Assuming we are doing a 3 by 3 neighborhood i.e., 9 values 26 | nbrs <- matrix(-1,5,5) 27 | #print(i) 28 | #Mange edge conditions left and right borders 29 | if(i%%4218 ==0){#right most border 30 | nbrs[1,1] <- class.list[i-8436] 31 | nbrs[2,1] <- class.list[i-4219] 32 | nbrs[3,1] <- class.list[i-2] 33 | nbrs[4,1] <- class.list[i+4215] 34 | nbrs[5,1] <- class.list[i+8432] 35 | nbrs[1,2] <- class.list[i-8435] 36 | nbrs[2,2] <- class.list[i-4218] 37 | nbrs[3,2] <- class.list[i-1] 38 | nbrs[4,2] <- class.list[i+4216] 39 | nbrs[5,2] <- class.list[i+8433] 40 | nbrs[1,3] <- class.list[i-8434] 41 | nbrs[2,3] <- class.list[i-4217] 42 | #nbrs[3,3] <- class.list[i] 43 | nbrs[4,3] <- class.list[i+4217] 44 | nbrs[5,3] <- class.list[i+8434] 45 | 46 | }else if(i%%4218 ==4217){#one beside right border 47 | nbrs[1,1] <- class.list[i-8436] 48 | nbrs[2,1] <- class.list[i-4219] 49 | nbrs[3,1] <- class.list[i-2] 50 | nbrs[4,1] <- class.list[i+4215] 51 | nbrs[5,1] <- class.list[i+8432] 52 | nbrs[1,2] <- class.list[i-8435] 53 | nbrs[2,2] <- class.list[i-4218] 54 | nbrs[3,2] <- class.list[i-1] 55 | nbrs[4,2] <- class.list[i+4216] 56 | nbrs[5,2] <- class.list[i+8433] 57 | nbrs[1,3] <- class.list[i-8434] 58 | nbrs[2,3] <- class.list[i-4217] 59 | #nbrs[3,3] <- class.list[i] 60 | nbrs[4,3] <- class.list[i+4217] 61 | nbrs[5,3] <- class.list[i+8434] 62 | nbrs[1,4] <- class.list[i-8433] 63 | nbrs[2,4] <- class.list[i-4216] 64 | nbrs[3,4] <- class.list[i+1] 65 | nbrs[4,4] <- class.list[i+4218] 66 | nbrs[5,4] <- class.list[i+8435] 67 | 68 | }else if(i%%4218==1){ # left most border 69 | nbrs[1,3] <- class.list[i-8434] 70 | nbrs[2,3] <- class.list[i-4217] 71 | #nbrs[3,3] <- class.list[i] 72 | nbrs[4,3] <- class.list[i+4217] 73 | nbrs[5,3] <- class.list[i+8434] 74 | nbrs[1,4] <- class.list[i-8433] 75 | nbrs[2,4] <- class.list[i-4216] 76 | nbrs[3,4] <- class.list[i+1] 77 | nbrs[4,4] <- class.list[i+4218] 78 | nbrs[5,4] <- class.list[i+8435] 79 | nbrs[1,5] <- class.list[i-8432] 80 | nbrs[2,5] <- class.list[i-4215] 81 | nbrs[3,5] <- class.list[i+2] 82 | nbrs[4,5] <- class.list[i+4219] 83 | nbrs[5,5] <- class.list[i+8436] 84 | 85 | }else if(i%%4218==2) {# second to left most border 86 | nbrs[1,2] <- class.list[i-8435] 87 | nbrs[2,2] <- class.list[i-4218] 88 | nbrs[3,2] <- class.list[i-1] 89 | nbrs[4,2] <- class.list[i+4216] 90 | nbrs[5,2] <- class.list[i+8433] 91 | nbrs[1,3] <- class.list[i-8434] 92 | nbrs[2,3] <- class.list[i-4217] 93 | #nbrs[3,3] <- class.list[i] 94 | nbrs[4,3] <- class.list[i+4217] 95 | nbrs[5,3] <- class.list[i+8434] 96 | nbrs[1,4] <- class.list[i-8433] 97 | nbrs[2,4] <- class.list[i-4216] 98 | nbrs[3,4] <- class.list[i+1] 99 | nbrs[4,4] <- class.list[i+4218] 100 | nbrs[5,4] <- class.list[i+8435] 101 | nbrs[1,5] <- class.list[i-8432] 102 | nbrs[2,5] <- class.list[i-4215] 103 | nbrs[3,5] <- class.list[i+2] 104 | nbrs[4,5] <- class.list[i+4219] 105 | nbrs[5,5] <- class.list[i+8436] 106 | 107 | } else{ 108 | nbrs[1,1] <- class.list[i-8436] 109 | nbrs[2,1] <- class.list[i-4219] 110 | nbrs[3,1] <- class.list[i-2] 111 | nbrs[4,1] <- class.list[i+4215] 112 | nbrs[5,1] <- class.list[i+8432] 113 | nbrs[1,2] <- class.list[i-8435] 114 | nbrs[2,2] <- class.list[i-4218] 115 | nbrs[3,2] <- class.list[i-1] 116 | nbrs[4,2] <- class.list[i+4216] 117 | nbrs[5,2] <- class.list[i+8433] 118 | nbrs[1,3] <- class.list[i-8434] 119 | nbrs[2,3] <- class.list[i-4217] 120 | #nbrs[3,3] <- class.list[i] 121 | nbrs[4,3] <- class.list[i+4217] 122 | nbrs[5,3] <- class.list[i+8434] 123 | nbrs[1,4] <- class.list[i-8433] 124 | nbrs[2,4] <- class.list[i-4216] 125 | nbrs[3,4] <- class.list[i+1] 126 | nbrs[4,4] <- class.list[i+4218] 127 | nbrs[5,4] <- class.list[i+8435] 128 | nbrs[1,5] <- class.list[i-8432] 129 | nbrs[2,5] <- class.list[i-4215] 130 | nbrs[3,5] <- class.list[i+2] 131 | nbrs[4,5] <- class.list[i+4219] 132 | nbrs[5,5] <- class.list[i+8436] 133 | 134 | } 135 | return(nbrs) 136 | 137 | } 138 | 139 | LabelRelaxation <- function(i,class.list){ 140 | #first extract neighbors 141 | nbrs <- ExtractNeighbors(i,class.list) 142 | count <- sum(nbrs==2) 143 | if(count>=13){ #more than half, change to water 144 | return(2) 145 | } else if(count == 12){ # exactly half, remains same 146 | return(class.list[i]) 147 | }else 148 | return(1) 149 | } 150 | 151 | ModeFilter <- function(){ 152 | 153 | print('Beginning assigning labels') 154 | label <- rep(1,nrow(labelled.data)) 155 | min <- 8437 156 | max <- nrow(labelled.data)-2*4218 157 | label[min:max] <- sapply(min:max,LabelRelaxation,labelled.data$Class) 158 | labelOld = labelled.data$Class 159 | labelled.data$Class <<- as.factor(label) 160 | countDifference <- sum(labelOld!=label) 161 | cat('Difference in labels = ',countDifference,'\n') 162 | 163 | } 164 | 165 | currentTime <- proc.time() 166 | ModeFilter() 167 | print('Finished assigning labels') 168 | cat('Execution time = ',proc.time()-currentTime,'\n') 169 | myImg1 <- readGDAL('Clip-May28-Composite.TIF') 170 | 171 | col1 = matrix(0, nrow = 2, ncol = 3) 172 | col1[1, ] = c(255, 255, 255) # black everything else 173 | col1[2, ] = c(0, 0, 255) # blue water 174 | 175 | 176 | 177 | colorize1 <- function(d) 178 | { 179 | for(i in 1:3) 180 | { 181 | d[, i] <- rep(col1[d[1, 11], i], nrow(d)) 182 | } 183 | d 184 | } 185 | 186 | print('Beginning to add colors') 187 | 188 | labelled.data$ID <- seq.int(nrow(labelled.data)) 189 | t1 <- split(labelled.data, labelled.data$Class, drop = T) 190 | t1 <- lapply(t1, FUN = colorize1) 191 | print('Colorized completed') 192 | 193 | x1 <- do.call("rbind", t1) 194 | x1 <- x1[order(x1$ID), ] 195 | x1 <- x1[,-12] 196 | write.csv(x=x1,file=outfile.csv,row.names=F) 197 | x1 <- x1[, -c(4,5,6,7,8,9,10,11)] 198 | colnames(x1) <- c('band4','band3','band2') 199 | myImg1@data[,c('band4','band3','band2')]<-x1 200 | writeGDAL(myImg1, fname = outfile.tif) 201 | 202 | print('Write completed') 203 | 204 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /postProcessing_AllClasses.R: -------------------------------------------------------------------------------- 1 | ################################################ 2 | # Get classified samples from Weka, visualize it as geotiff 3 | # 6 colors - (Clouds, Roads, Shadow, Urban, Vegetation, Water) - (white, yellow, black, pink, green, blue) 4 | # Krishna Karthik Gadiraju/kgadira 5 | # Bharathkumar Ramachandra/tnybny 6 | ################################################ 7 | 8 | library(rgdal) 9 | library(rgeos) 10 | library(foreign) 11 | 12 | 13 | #read original image 14 | myImg<-readGDAL('path_to_original_image') 15 | 16 | #read classified file 17 | classified <- read.csv('predicted-csv-file') 18 | 19 | #column names of features - top 10 features selected using feature selection + Class Label 20 | colnames(classified) <- c('band4','band3','Aerosol','energy','band2','invDiffM', 21 | 'SWIR1','SWIR2','diffEntr','inertia','Class') 22 | print(colnames(classified)) 23 | print(summary(classified)) 24 | 25 | # Convert class variable to factor 26 | classified$Class <-as.factor(classified$Class) 27 | print('all classes summary') 28 | print(summary(classified)) 29 | 30 | #Assign colors: Source: Visualization work done by BharathKumar Ramachandra/tnybny 31 | col = matrix(0, nrow = 6, ncol = 3) 32 | col[1, ] = c(255, 255, 255) # red clouds 33 | col[2, ] = c(255, 255, 0) # yellow roads 34 | col[3, ] = c(0, 0, 0) # black shadow 35 | col[4, ] = c(255, 105, 180) # hot pink for urban 36 | col[5, ] = c(0, 255,0 ) # green vegetation 37 | col[6, ] = c(0, 0, 255) # blue water 38 | 39 | 40 | colorize <- function(d) 41 | { 42 | for(i in 1:3) 43 | { 44 | d[, i] <- rep(col[d[1, 11], i], nrow(d)) 45 | } 46 | d 47 | } 48 | 49 | 50 | 51 | print('Beginning to add colors') 52 | classified$ID <- seq.int(nrow(classified)) 53 | 54 | 55 | t <- split(classified, classified$Class, drop = T) #split by class 56 | t <- lapply(t, FUN = colorize) #Appl color to each class 57 | 58 | 59 | print('Colorized completed') 60 | x <- do.call("rbind", t) 61 | 62 | 63 | x <- x[order(x$ID), ] #Reorder data in original order 64 | 65 | 66 | x <- x[, -c(4:12)] #Remove unnecessary columns 67 | colnames(x) <-c('band4','band3','band2') #Rename first three bands to ba 68 | myImg@data[,c('band4','band3','band2')]<-x #Copy R,G,B bands 69 | writeGDAL(myImg, fname = "./KNNtiff_10bands.tif") #write GDAL file 70 | 71 | print('Write completed') 72 | -------------------------------------------------------------------------------- /postProcessing_onlyWater.R: -------------------------------------------------------------------------------- 1 | ################################################ 2 | # Get classified samples from Weka, visualize it as geotiff 3 | # Krishna Karthik Gadiraju/kgadira 4 | # Bharathkumar Ramachandra/tnybny 5 | ################################################ 6 | 7 | library(rgdal) 8 | library(rgeos) 9 | library(foreign) 10 | 11 | #read original image 12 | myImg1 <- readGDAL('Clip-May28-Composite.TIF') 13 | 14 | #read classified file 15 | classified <- read.csv('predicted-csv-file') 16 | 17 | #column names of features - top 10 features selected using feature selection + Class Label 18 | colnames(classified) <- c('band4','band3','Aerosol','energy','band2','invDiffM', 19 | 'SWIR1','SWIR2','diffEntr','inertia','Class') 20 | print(colnames(classified)) 21 | print(summary(classified)) 22 | 23 | classified[which(classified$Class!=6),]$Class <-1 24 | classified[which(classified$Class==6),]$Class <-2 25 | 26 | # Convert class variable to factor 27 | classified$Class <-as.factor(classified$Class) 28 | print('classes summary') 29 | print(summary(classified)) 30 | 31 | #Assign colors: Source: Visualization work done by BharathKumar Ramachandra/tnybny 32 | col1 = matrix(0, nrow = 2, ncol = 3) 33 | col1[1, ] = c(255, 255, 255) # white everything else 34 | col1[2, ] = c(0, 0, 255) # blue water 35 | 36 | #Function that assigns colors 37 | colorize <- function(d) 38 | { 39 | for(i in 1:3) 40 | { 41 | d[, i] <- rep(col1[d[1, 11], i], nrow(d)) 42 | } 43 | d 44 | } 45 | 46 | print('Beginning to add colors') 47 | classified$ID <- seq.int(nrow(classified)) 48 | 49 | t <- split(classified, classified$Class, drop = T) 50 | t <- lapply(t, FUN = colorize1) 51 | 52 | print('Colorized completed') 53 | x <- do.call("rbind", t) 54 | 55 | x <- x[order(x$ID), ] #Reorder data in original order 56 | 57 | 58 | x <- x[, -c(4:12)] #Remove unnecessary columns 59 | colnames(x) <-c('band4','band3','band2') #Rename first three bands to ba 60 | myImg@data[,c('band4','band3','band2')]<-x #Copy R,G,B bands 61 | writeGDAL(myImg, fname = "./KNNtiff_10bands.tif") #write GDAL file 62 | 63 | print('Write completed') 64 | 65 | 66 | -------------------------------------------------------------------------------- /preprocessing_totalImage.R: -------------------------------------------------------------------------------- 1 | #convert geotiff to csv/arff format to be used in Weka classifiers 2 | #Krishna Karthik Gadiraju/kkgadiraju 3 | rm(list=ls()) 4 | 5 | library(rgdal) 6 | library(rgeos) 7 | library(foreign) 8 | 9 | 10 | myImg<-readGDAL('Clip-May28-Composite.TIF') 11 | simpleImg <- readGDAL('May28-SimpleFinal.tif') 12 | advancedImg <- readGDAL('May28-AdvancedFinal.tif') 13 | myImgData <- myImg@data 14 | simpleImgData <- simpleImg@data 15 | advancedImgData <- advancedImg@data 16 | colnames(myImgData) <- c("Aerosol","B","G","R","NIR","SWIR1","SWIR2","Cirrus") 17 | colnames(simpleImgData) <- c("energy","entropy","corr","invDiffM","inertia","clusShade","clusProm","hCorr") 18 | colnames(advancedImgData) <- c("mean","variance","dissim","sumAvg","sumVar","sumEntr","diffEntr","diffVar","IC1","IC2") 19 | allData <- cbind(myImgData,simpleImgData,advancedImgData) 20 | x2 <- sample(1:6,nrow(allData),replace=T) 21 | allData$Class <-x2 22 | top10 <- c('R','G','Aerosol','energy','B','invDiffM','SWIR1','SWIR2','diffEntr','inertia','Class') 23 | 24 | outputData <- allData[,top10] 25 | 26 | outputData$Class <- as.factor(outputData$Class) 27 | 28 | #write.csv(x=outputData,file = 'may28-allImage-top10.csv',row.names = F) 29 | write.arff(outputData,file='may28-allImage-top10.arff',relation='testing') 30 | 31 | --------------------------------------------------------------------------------