-
Notifications
You must be signed in to change notification settings - Fork 19
/
landscape_modifier.py
148 lines (122 loc) · 4.95 KB
/
landscape_modifier.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
# -*- coding: utf-8 -*-
"""
/***************************************************************************
LecoS
A QGIS plugin
Contains analytical functions for landscape analysis
-------------------
begin : 2012-09-06
copyright : (C) 2013 by Martin Jung
email : martinjung at zoho.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
# Import PyQT bindings
from builtins import str
from builtins import range
from builtins import object
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
# Import QGIS analysis tools
from qgis.core import *
from qgis.gui import *
#from qgis.analysis import *
# Import base libraries
import os,sys,csv,string,math,operator,subprocess,tempfile,inspect
# Import numpy and scipy
import numpy
try:
import scipy
# import ndimage module seperately for easy access
from scipy import ndimage
except ImportError:
QMessageBox().critical(QDialog(),"LecoS: Warning","Please install scipy (http://scipy.org/) in your QGIS python path.")
sys.exit(0)
# Try to import functions from osgeo
try:
from osgeo import gdal
except ImportError:
import gdal
try:
from osgeo import ogr
except ImportError:
import ogr
try:
from osgeo import osr
except ImportError:
import osr
try:
from osgeo import gdal_array
except ImportError:
import gdalnumeric
try:
from osgeo import gdalconst
except ImportError:
import gdalconst
tmpdir = tempfile.gettempdir()
## CODE START ##
# Landscape Modifier class
class LandscapeMod(object):
def __init__(self,rasterPath,cl):
# load as a gdal image to get full array
self.srcImage = gdal.Open(str(rasterPath))
self.nodata = self.srcImage.GetRasterBand(1).GetNoDataValue()
try:
self.srcArray = self.srcImage.GetRasterBand(1).ReadAsArray() # Convert first band to array
except ValueError:
QMessageBox.warning(QDialog(),"LecoS: Warning","Raster file is to big for processing. Please crop the file and try again.")
return
self.cl = cl
self.cl_array = numpy.copy(self.srcArray)
self.cl_array[self.srcArray!=self.cl] = 0
# Extract edges from landscape patches class
def extractEdges(self,size):
# Extract basic edge skeleton
edge = ndimage.distance_transform_edt(self.cl_array == 0) == 1
# Increase Size if needed
if size > 1:
s = ndimage.generate_binary_structure(2,1) #taxi-cab structure default
edge = ndimage.binary_dilation(edge,s,iterations=size-1)
return(edge)
# Isolate smallest or greatest Patch from raster
def getPatch(self,which):
s = ndimage.generate_binary_structure(2,2) # Chessboard struct
labeled_array, numpatches = ndimage.label(self.cl_array,s)
sizes = ndimage.sum(self.cl_array,labeled_array,list(range(1,numpatches+1)))
# inside the largest, respecitively the smallest labeled patches with values
if which == "min":
mip = numpy.where(sizes==sizes.min())[0] + 1
min_index = numpy.zeros(numpatches + 1, numpy.uint8)
min_index[mip] = self.cl
feature = min_index[labeled_array]
else:
map = numpy.where(sizes==sizes.max())[0] + 1
max_index = numpy.zeros(numpatches + 1, numpy.uint8)
max_index[map] = self.cl
feature = max_index[labeled_array]
return(feature)
# Increase or decrease landscape patches
def InDecPatch(self,which,amount):
s = ndimage.generate_binary_structure(2,1) # taxi-cab struct
if which == 0:
ras = ndimage.binary_dilation(self.cl_array,s,iterations=amount,border_value=0)
else:
ras = ndimage.binary_erosion(self.cl_array,s,iterations=amount,border_value=0)
return(ras)
# Close inner patch holes
def closeHoles(self):
s = ndimage.generate_binary_structure(2,2) # Chessboard struct
ras = ndimage.binary_fill_holes(self.cl_array,s)
return(ras)
# Remove smaller pixels in class raster
def cleanRaster(self,n):
s = ndimage.generate_binary_structure(2,1) # Taxicab struct
ras = ndimage.binary_opening(self.cl_array,s,iterations=n).astype(int)
return(ras)