Project

General

Profile

« Previous | Next » 

Revision 445a6521

Added by Jim Regetz over 13 years ago

  • ID 445a65219f854db9720bc2861d377d456587d259

added GDAL/R code for fusing and correcting DEMs near Canadian border

View differences:

terrain/dem/dem-fusion.txt
1
# Snippets of GDAL commands and R code for processing DEMs
2
# Jim Regetz
3
# Created on 08-Jun-2011
4
#
5
# Note: Working with the original ASTERs yields this warning from GDAL:
6
#    Warning 1: TIFFReadDirectoryCheckOrder:Invalid TIFF directory;
7
#    tags are not sorted in ascending order
8
#
9
# I first ran gdal_translate on each of the ASTERs, then repeated the
10
# vrt/warp on those (without warnings), but the output was the same as
11
# when I operated on the original files (with warnings), so for the
12
# moment I'm just going to ignore the warnings?
13

  
14
#=======================================================================
15
# bash -- resample source DEMs into desired grids near the 60N boundary
16
#=======================================================================
17

  
18
# generate strips of data along a 40-degree longitudinal extent matching
19
# (at least one of) Rick's mosaicked CDEM grids; strips extend 150
20
# pixels south of border and (in case of aster) north of border
21

  
22
# these are currently correct on vulcan
23
export ASTDIR="/home/reeves/active_work/EandO/asterGdem"
24
export SRTMDIR="/home/reeves/active_work/EandO/CgiarSrtm/SRTM_90m_ASCII_4_1"
25

  
26
# SRTM (also convert to 16bit integer)
27
gdalbuildvrt srtm.vrt $SRTMDIR/srtm_*_01.asc
28
gdalwarp -ot Int16 -te -136 59.875 -96 60 -ts 48000 150 -r bilinear \
29
  srtm.vrt srtm_150below.tif
30

  
31
# ASTER
32
gdalbuildvrt aster.vrt $ASTDIR/ASTGTM_N59*W*_dem.tif \
33
  $ASTDIR/ASTGTM_N60*W*_dem.tif
34
gdalwarp -te -136 59.875 -96 60 -ts 48000 150 -r bilinear \
35
  aster.vrt aster_150below.tif
36
gdalwarp -te -136 60 -96 60.125 -ts 48000 150 -r bilinear \
37
  aster.vrt aster_150above.tif
38

  
39
# note that the top 150 rows of this one are, somewhat surprisingly,
40
# slightly different from the above!
41
# gdalwarp -te -136 59.875 -96 60.125 -ts 48000 300 -r bilinear \
42
#   aster.vrt aster_300straddle.tif
43
#
44
# and this yields an even different set of values
45
# gdalbuildvrt aster_N60.vrt $ASTDIR/ASTGTM_N60*W*_dem.tif
46
# gdalwarp -te -136 60 -96 60.125 -ts 48000 150 -r bilinear \
47
#   aster_N60.vrt aster_150above.tif
48

  
49
#=======================================================================
50
# R -- apply several kinds of boundary fixes and write out new GeoTIFFs
51
#=======================================================================
52

  
53
library(raster)
54

  
55
# load relevant SRTM and ASTER data
56
srtm.south <- raster("srtm_150below.tif")
57
aster.south <- raster("aster_150below.tif")
58
aster.north <- raster("aster_150above.tif")
59

  
60
# create difference raster for area of overlap
61
delta.south <- srtm.south - aster.south
62

  
63
#
64
# OPTION 1
65
#
66

  
67
# smooth to the north, by calculating the deltas _at_ the boundary,
68
# ramping them down to zero with increasing distance from the border,
69
# and adding them to the north ASTER values
70

  
71
# create simple grid indicating distance (in units of pixels) north from
72
# boundary, starting at 1 (this is used for both option 1 and option 2)
73
aster.north.matrix <- as.matrix(aster.north)
74
ydistN <- nrow(aster.north.matrix) + 1 - row(aster.north.matrix)
75

  
76
# 1b. linear ramp north from SRTM edge
77
# -- Rick is doing this --
78

  
79
# 2b. exponential ramp north from SRTM edge
80
# -- Rick is also doing this, but here it is... --
81
r <- -0.045
82
w <- exp(ydistN*r)
83
aster.north.smooth <- aster.north
84
aster.north.smooth[] <- values(aster.north) + as.integer(round(t(w) *
85
    as.matrix(delta.south)[1,]))
86
writeRaster(aster.north.smooth, file="aster_150above_rampexp.tif")
87

  
88
#
89
# OPTION 2
90
#
91

  
92
# smooth to the north, by first using LOESS with values south of 60N to
93
# model deltas as a function of observed ASTER, then applying the model
94
# to predict pixel-wise deltas north of 60N, then ramping these
95
# predicted deltas to zero with increasing distance from the border, and
96
# adding them to the associated ASTER values
97

  
98
# first fit LOESS on a random subsample of data
99
# note: doing all the data takes too long, and even doing 50k points
100
#       seems to be too much for calculating SEs during predict step
101
set.seed(99)
102
samp <- sample(ncell(aster.south), 10000)
103
sampdata <- data.frame(delta=values(delta.south)[samp],
104
    aster=values(aster.south)[samp])
105
lo.byaster <- loess(delta ~ aster, data=sampdata)
106

  
107
# now create ASTER prediction grid north of 60N
108
# TODO: deal with NAs in data (or make sure they are passed through
109
#       properly in the absence of explicit treatment)?
110
aster.north.pdelta <- aster.north
111
aster.north.pdelta[] <- predict(lo.byaster, values(aster.north))
112
# for actual north ASTER values that exceed the max value used to fit
113
# LOESS, just use the prediction associated with the maximum
114
aster.north.pdelta[aster.north<min(sampdata$aster)] <- predict(lo.byaster,
115
    data.frame(aster=min(sampdata$aster)))
116
# for actual north ASTER value less than the min value used to fit
117
# LOESS, just use the prediction associated with the minimum
118
aster.north.pdelta[aster.north>max(sampdata$aster)] <- predict(lo.byaster,
119
    data.frame(aster=max(sampdata$aster)))
120

  
121
# 2a: exponential distance-weighting of LOESS predicted deltas
122
r <- -0.045
123
w <- exp(ydistN*r)
124
aster.north.smooth <- aster.north
125
aster.north.smooth[] <- values(aster.north) + as.integer(round(t(w *
126
    as.matrix(aster.north.pdelta))))
127
writeRaster(aster.north.smooth, file="aster_150above_predexp.tif")
128

  
129
# 2b: gaussian distance-weighting of LOESS predicted deltas
130
r <- -0.001  # weight drops to 0.5 at ~26 cells, ie 2.4km at 3" res
131
w <- exp(-0.001*ydistN^2)
132
aster.north.smooth <- aster.north
133
aster.north.smooth[] <- values(aster.north) + as.integer(round(t(w *
134
    as.matrix(aster.north.pdelta))))
135
writeRaster(aster.north.smooth, file="aster_150above_predgau.tif")
136

  
137
#
138
# OPTION 3
139
#
140

  
141
# smooth to the south, now by simply taking pixel-wise averages of the
142
# observed SRTM and ASTER using a distance-based weighting function such
143
# that the relative contribution of ASTER decays to zero over a few km
144

  
145
# create simple grid indicating distance (in units of pixels) south from
146
# boundary, starting at 1
147
aster.south.matrix <- as.matrix(aster.south)
148
ydistS <- row(aster.south.matrix)
149

  
150
# 3a: gaussian weighting function
151
r <- -0.001  # weight drops to 0.5 at ~26 cells, or 2.4km at 3" res
152
w <- exp(-0.001*ydistS^2)
153
aster.south.smooth <- aster.south
154
aster.south.smooth[] <- values(srtm.south) - as.integer(round(t(w *
155
    as.matrix(delta.south))))
156
aster.south.smooth[aster.south.smooth<0] <- 0
157
writeRaster(aster.south.smooth, file="dem_150below_blendgau.tif")
158

  
159

  
160
#=======================================================================
161
# bash -- fuse DEMS, generate hillshade
162
#=======================================================================
163

  
164
#
165
# create simple fused layers
166
#
167

  
168
# uncorrected fused layer
169
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
170
  srtm_150below.tif aster_150above.tif fused_300straddle.tif
171

  
172
# exponential ramp of boundary delta to the north
173
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
174
  srtm_150below.tif aster_150above_rampexp.tif fused_300straddle_rampexp.tif
175

  
176
# exponential blend of predicted deltas to the north
177
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
178
  srtm_150below.tif aster_150above_predexp.tif fused_300straddle_predexp.tif
179

  
180
# gaussian blend of predicted deltas to the north
181
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
182
  srtm_150below.tif aster_150above_predgau.tif fused_300straddle_predgau.tif
183

  
184
# gaussian blend of SRTM/ASTER to the south
185
gdalwarp -ot Int16 -te -136 59.875 -96 60.125 -ts 48000 300 \
186
  dem_150below_blendgau.tif aster_150above.tif fused_300straddle_blendgau.tif
187

  
188
#
189
# hillshade the different fused DEMs created above
190
#
191

  
192
gdaldem hillshade -s 111120 fused_300straddle.tif fused_300straddle_hs.tif
193
gdaldem hillshade -s 111120 fused_300straddle_rampexp.tif fused_300straddle_rampexp_hs.tif
194
gdaldem hillshade -s 111120 fused_300straddle_predexp.tif fused_300straddle_predexp_hs.tif
195
gdaldem hillshade -s 111120 fused_300straddle_predgau.tif fused_300straddle_predgau_hs.tif
196
gdaldem hillshade -s 111120 fused_300straddle_blendgau.tif fused_300straddle_blendgau_hs.tif
197

  
198

  
199
#=======================================================================
200
# R -- generate some quick hillshade visuals of a 1-degree wide swath
201
#=======================================================================
202

  
203
library(raster)
204

  
205
uncorrected <- raster("fused_300straddle_hs.tif")
206
rampexp <- raster("fused_300straddle_rampexp_hs.tif")
207
blendgau <- raster("fused_300straddle_blendgau_hs.tif")
208

  
209
window <- extent(-135, -134, 59.875, 60.125)
210

  
211
png("boundary-hillshade.png", height=8, width=8, units="in", res=600)
212
par(mfrow=c(3,1))
213
plot(crop(uncorrected, window), main="uncorrected (hillshade)")
214
plot(crop(rampexp, window), main="north exponential ramp (hillshade)")
215
plot(crop(blendgau, window), main="south gaussian blend (hillshade)")
216
dev.off()
217

  

Also available in: Unified diff