You can use area-to-point regression Kriging (ATPRK) to downscale S2 using the atakrig
package. ATPRK consists of two steps:
- regression
- area-to-point Kriging on the regression's residuals
Assuming your coarse and fine bands are the red and nir, respectively, and the CRS is in meters, then:
#linear regression
library(raster)
#extract prediction part of a lm model as a raster
red = raster ("path/red.tif")
vals_red <- as.data.frame(values(red))
red_coords = as.data.frame(xyFromCell(red, 1:ncell(red))
combine <- as.data.frame(cbind(red_coords, vals_red))
nir = raster ("path/nir.tif")
nir <- resample(nir, red, method="bilinear")
vals_nir <- as.data.frame(values(nir))
s = stack(red, nir)
block.data <- as.data.frame(cbind(combine, vals_nir))
names(block.data)[3] <- "red"
names(block.data)[4] <- "nir"
block.data <- na.omit(block.data)
block.data = read.csv("path/block.data.csv")
model <- lm(formula = red ~ nir, data = block.data)
#predict to a raster
r1 <- predict(s, model, progress = 'text')
plot(r1)
writeRaster(r1, filename = "path/lm_pred.tif")
#extract residuals
map.resids <- as.data.frame(model$residuals)
x = as.data.frame(block.data$x)
y = as.data.frame(block.data$y)
map.resids <- SpatialPointsDataFrame(data=map.resids, coords=cbind(x,y))
gridded(map.resids) <- TRUE
r <- raster(map.resids)
raster::crs(r) <- "EPSG:...." #your EPSG in meters
writeRaster(r,
filename = "path/lm_resids.tif",
format = "GTiff",
overwrite = T)
#area-to-point Kriging
library(atakrig)
block.data = read.csv("path/coords.csv")#csv with 2 columns (x,y) taken from the high resolution raster
nir = raster("path/nir.tif")
rsds = raster("path/lm_resids.tif")
#raster to points
nir.d = discretizeRaster(nir , 10, type = "value")
rsds.d = discretizeRaster(rsds, 10, type = "value")
# point-scale cross-variogram
aod.list <-list(rsds = rsds.d, nir = nir .d)
sv.ck <-deconvPointVgmForCoKriging(aod.list,
model = "Sph",
rd = 0.5,
maxIter = 50,
nopar = F) #play with the rd and model
ataStartCluster()
pred.atpok <- atpKriging(rsds.d,
block.data,
sv.ck$nir.rsds,
showProgress = T,
nopar = F)
ataStopCluster()
# convert result to raster for atp
pred.atpok.r <-rasterFromXYZ(pred.atpok[,-1])
#plot(pred.ataok.r)
raster::crs(pred.atpok.r) <- "EPSG:...." #your EPSG (in meters)
writeRaster(pred.atpok.r$pred,
'path/atpk.tif', overwrite = T)
pred = raster('path/lm_pred.tif')
atpk = raster('path/atpk.tif')
pred = resample(pred, atpk, method = 'bilinear')
red_atprk = pred + atprk
red_atprk[red_atprk <= 0] <- 0
writeRaster(red_atprk,
filename = "path/red_atprk.tif")
Important note: In order ATPRK to produce good results, your bands (coarse and fine) needs to be highly correlated. You can check that by investigating the results of the lm
(i.e., high R2
and low AIC
or BIC
).