-
Notifications
You must be signed in to change notification settings - Fork 7
/
rfClassification.py
187 lines (142 loc) · 7.6 KB
/
rfClassification.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import ee
from addCovariates import *
class randomForest():
def __init__(self):
ee.Initialize()
self.exportPath = 'users/TEST/'
self.epsg = "EPSG:32717"
# set number of trees for the random forest classifier
self.trees = 40
# set the version number of the product
self.versionNumber = 9;
# specify the training data set
self.TrainingID = 'CompiledData02102019'
# // specify the Landsat and Sentinel 1 data set
self.LandsatID = 'TOA_composites_V2'
self.DualS1_ID = 'S1Dual_Annual_V2'
# specify the sample dataset
self.trainingData = ee.FeatureCollection("projects/Sacha/AncillaryData/RefData/CompiledData02102019")
# // specify the Sentinel 1 and Landsat S2 data set
self.Dual_Annual = ee.ImageCollection("projects/Sacha/PreprocessedData/S1Dual_Annual_V2")
self.S2LSTOA = ee.ImageCollection("projects/Sacha/PreprocessedData/TOA_composites_V2")
# Specify the regions feature collection
self.ecoregions = ee.FeatureCollection("projects/Sacha/AncillaryData/StudyRegions/Ecuador_EcoRegions_Complete")
# todo need to convert covariates into py
self.covariates = addCovariates()
self.bandNames = ee.List(["red", "nir", "swir1", "swir2",
"ND_nir_red", "ND_nir_swir1", "ND_nir_swir2",
"ND_red_swir1", "ND_red_swir2",
"ND_swir1_swir2",
"p25_nir", "p25_red", "p25_swir1", "p25_swir2",
"p25_ND_nir_red", "p25_ND_nir_swir1", "p25_ND_nir_swir2",
"p25_ND_red_swir1", "p25_ND_red_swir2",
"p25_ND_swir1_swir2",
"p75_nir", "p75_red", "p75_swir1", "p75_swir2",
"p75_ND_nir_red", "p75_ND_nir_swir1", "p75_ND_nir_swir2",
"p75_ND_red_swir1", "p75_ND_red_swir2",
"p75_ND_swir1_swir2",
"VH", "VH_amplitude_1", "VH_phase_1", "VV", "VV_amplitude_1","VV_phase_1","ratio",
"aspect", "eastness", "elevation", "northness", "slope",
"change_abs", "change_norm", "max_extent","occurrence", "transition", "seasonality",
'svvi','blue_stdDev','red_stdDev','green_stdDev','nir_stdDev','swir1_stdDev','swir2_stdDev',
'ND_green_swir1_stdDev','ND_nir_red_stdDev','ND_nir_swir2_stdDev','clusters']);
def main(self,year,ProcessingRegion,**kwargs):
studyArea = self.ecoregions.filter(ee.Filter.eq("PROVINCIA", ProcessingRegion)).geometry().buffer(1000);
sampleData = self.trainingData.filterBounds(studyArea)
imageLandsatS2 = image if kwargs.get('image') else self.S2LSTOA.filterDate(str(year)).first()
trianingImg = self.S2LSTOA.filterDate('2016').first()
analysisYr = self.addBandsToComposite(imageLandsatS2)
trainingYr = self.addBandsToComposite(trianingImg)
data = trainingYr.sampleRegions(sampleData,["niv2_int"],20);
classifier = ee.Classifier.randomForest(self.trees,0).train(ee.FeatureCollection(data),"niv2_int",self.bandNames);
classification = analysisYr.classify(classifier,'Mode');
# todo think if we want to include this if its not automated
classification = classification.set({
'system:time_start': ee.Date.fromYMD(year,6,1).millis(),
'version': self.versionNumber,
'TrainingData': self.TrainingID,
'LandsatID': self.LandsatID,
'S1_Dual_ID': self.DualS1_ID,
'regionName': ProcessingRegion,
});
classificationMMU = self.sieve(classification,11)
self.mmuEx = kwargs.get('mmu')
self.exportMap(classification,studyArea,"") if kwargs.get('exportImg') and self.mmuEx == False or self.mmuEx == 3 else None
self.exportMap(classificationMMU,studyArea,"_MMU") if kwargs.get('exportImg') and self.mmuEx == True or self.mmuEx == 3 else None
print(classification.bandNames().getInfo())
return classification, classificationMMU
def exportMap(self,img,studyArea, suffix):
img = img
ed = str(year) + suffix
regionName = ProcessingRegion.replace(" ",'_')
task_ordered= ee.batch.Export.image.toAsset(image=img.clip(studyArea),
description = regionName + '_LandCover_' + ed,
assetId = self.exportPath + regionName + '_LandCover_' + ed,
region = studyArea.bounds().getInfo()['coordinates'],
maxPixels = 1e13,
crs = self.epsg,
scale = 30)
task_ordered.start()
print('Export Started: ',self.exportPath + regionName + '_LandCover_' + ed)
# in functions
def addBandsToComposite(self,composite):
year = ee.Date(composite.get('system:time_start')).get('year')
stdBands = composite.select(['svvi','blue_stdDev','red_stdDev','green_stdDev',
'nir_stdDev','swir1_stdDev','swir2_stdDev',
'ND_green_swir1_stdDev','ND_nir_red_stdDev','ND_nir_swir2_stdDev'])
img25 = composite.select(['p25_blue','p25_green','p25_red','p25_nir','p25_swir1','p25_swir2'])
img75 = composite.select(['p75_blue','p75_green','p75_red','p75_nir','p75_swir1','p75_swir2'])
composite = composite.select(['blue','green','red','nir','swir1','swir2'])
# adding abnds to the composite
addJRCAndTopo = self.covariates.addJRCAndTopo(composite)
# gets nd for selected bands
img = addJRCAndTopo.addBands(self.covariates.addCovariates("",composite));
# // gets nd of 25 and 75percentile bands
img = img.addBands(self.covariates.addCovariates("p75_",img75)).addBands(self.covariates.addCovariates("p25_",img25));
bands = img.bandNames().removeAll(['blue_1','green_1','red_1','nir_1','swir1_1','swir2_1']);
img = img.select(bands).addBands(stdBands)
Seg = ee.Algorithms.Image.Segmentation.SNIC(image = img.select(['ND_nir_red']),
size = 20,
compactness = 0,
connectivity = 8);
img = img.addBands(Seg.select(['clusters']))
# the dual pol SAR data is added here
DualSar = ee.Image(self.Dual_Annual.filter(ee.Filter.calendarRange(year,year,'year')).first()).divide(10000);
img = img.addBands(DualSar)
return img
def mosaicUniqueDates(self,collection):
allDates = ee.List(collection.aggregate_array('system:time_start')).distinct()
def getUDate(i):
uD = collection.filterDate(i).mosaic()
return uD
out = allDates.map(getUDate)
return ee.ImageCollection(out)
def sieve(self,image,mmu):
"""function to filter isolated pixels be designated MMU.
MMU value is the pixel count. """
connected = image.connectedPixelCount(mmu+20);
elim = connected.gt(mmu);
mode = image.focal_mode(mmu/2,'circle');
mode = mode.mask(image.mask());
filled = image.where(elim.Not(),mode);
return filled.rename('Mode_MMU')
if __name__ == "__main__":
# // EcoRegions include: AMAZONIA NOROCCIDENTAL, ANDES DEL NORTE, GALAPAGOS, SIERRA,
# // CHOCO, PACIFICO ECUATORIAL
ProcessingRegion = 'AMAZONIA NOROCCIDENTAL'
year = 2018;
''' main() takes 2 paramters -year,ProcessingRegion- and returns a tulep of classified images (0: no mmu, 1: mmu)
optionally you can choose to export by setting exportImg to true and selecting which product you want with
mmu. By default main will use the Sentinel2/Landsat Collection, but you can pass in another compostie by setting
image = ee.Image('path/to/asset')
mmu can be 0: exports classification without mmu
1: exports classification with mmu
3: exports both
example: using default image collection and not exporting
randomForest().main(2016,'AMAZONIA NOROCCIDENTAL')
randomForest().main(2016,'AMAZONIA NOROCCIDENTAL',exportImg=True,mmu=1)
exporting mmu
providing your own image and exporting
myImg = ee.Image('projects/Sacha/.../LSS2_ECUADOR_ANNUAL_MEDIAN_CLDMX80_2016_000365_ST')
randomForest().main(2016,'AMAZONIA NOROCCIDENTAL',exportImg=False,mmu=True, image=myImg) '''
randomForest().main(year,ProcessingRegion,exportImg=True,mmu=3)