在R中对齐栅格和shapefile的范围:使用相同的CRS

时间:2017-09-30 14:32:32

标签: r qgis r-raster

我有一个小光栅。它是来自Digital Globe底图的单个图块(缩放= 16);它是标准的256 x 256像素。在QGIS中,我创建了一个多边形shapefile并添加了大约50个特征。栅格和shapefile位于同一个CRS中。在QGIS中,它们对齐很好,如下图所示。

Overlapping shape and raster in QGIS

然而,当我在R中打开栅格和shapefile时,两者不再对齐。同样,两者都在同一个CRS中。下面是可重现的代码,shapefile和栅格可以从GitHub文件夹here下载。我正在使用光栅包中的brick()来保持RGB波段分离。

#load
library(raster)
img <- brick("26261.png")
proj4string(img) <- CRS("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs")
trainData <- shapefile("26261_train.shp")

#shape plots fine alone
plot(trainData, axes = TRUE)
#raster plots fine alone
plot(img,1)
#two do not match
plot(trainData, add = TRUE)

#summary
img
trainData 

问题似乎是由于两个文件具有不同的范围,如摘要中所示:

> img
class       : RasterBrick 
dimensions  : 256, 256, 65536, 4  (nrow, ncol, ncell, nlayers)
resolution  : 1, 1  (x, y)
extent      : 0, 256, 0, 256  (xmin, xmax, ymin, ymax)
coord. ref. : +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs 
data source : /.../26261.png 
names       : X26261.1, X26261.2, X26261.3, X26261.4 
min values  :        0,        0,        0,        0 
max values  :      255,      255,      255,      255 

> trainData
class       : SpatialPolygonsDataFrame 
features    : 49 
extent      : 4.38, 244.9, -232.72, -6.48  (xmin, xmax, ymin, ymax)
coord. ref. : +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs 
variables   : 3
names       : id, cat1, cat2 
min values  : NA,    1,    0 
max values  : NA,    7,    2 

但是,当我在QGIS中检查两个文件的范围时,它们会重叠。下图是QGIS中的栅格。 shapefile和栅格的y范围都在[-256,0]中。

Raster extent in QGIS

似乎brick()函数将x和y扩展区设置为正数,但我已经查看了包/函数文档,并且不明白为什么会出现这种情况。如何让这两个文件在R中对齐?

我已经尝试将栅格导出为GeoTIFF,但这也不起作用。我也试过在shapefile中读一些其他R包,比如rgdal。我可以让它“工作”,如果在QGIS中我导出shapefile,同时以光栅为中心,并选择“地图视图范围”,但这不是最佳解决方案,并且(a)我需要使用数组地图图块并且不想手动缩放到每个图块,并且(b)这并不能解释我所犯的错误。我甚至不确定我的问题是从QGIS导出还是导入到R,尽管我很确定我的错误是在brick()中。

注意:有一个类似的声音问题here,但是尽管问题的标题,错误仍然是坐标参考系统。

1 个答案:

答案 0 :(得分:0)

感谢@LoBu的评论,虽然没有正确地进行地理配准并没有解释为什么从QGIS导出到R通过brick()翻转栅格的y范围,正确地对R中的地图图块进行地理配准确实解决了更大的问题。

瓷砖是来自数字地球底图的'滑动地图'瓷砖,带有QGIS的Qtiles插件。因此,它们按照here所述进行索引,对于TMS磁贴,实现仅略有不同。 Slippy地图图块使用NW角作为参考,而TMS图块使用SW角作为参考。我们可以使用目录结构和文件名对每个tile进行地理配准。

对于我的问题中给出的示例图块,下面是R中的一个实现,修改了上一个链接中的Python示例:

#funtion to take tile names and return extent
num2deg <- function(xtile,ytile,zoom){

  n = 2^zoom

  lon_deg_nw = xtile / n * 360.0 - 180.0
  lat_rad_nw = atan(sinh(pi * (1 - 2 * ytile / n)))
  lat_deg_nw = lat_rad_nw * 180 / pi

  lon_deg_se = (xtile + 1) / n * 360.0 - 180.0
  lat_rad_se = atan(sinh(pi * (1 - 2 * (ytile - 1) / n)))
  lat_deg_se = lat_rad_se * 180 / pi

  #returns extent: vector (length=4; order= xmin, xmax, ymin, ymax)
  return(c(lon_deg_nw, lon_deg_se, lat_deg_se, lat_deg_nw))
}

#example get tile 
library(raster)
tile <- brick(".../16/39281/26261.png")

#get extent for raster
my.extent <- num2deg(xtile = 39281, ytile = 26261, zoom = 16)

#georeference and plot  
extent(tile) <- my.extent
projection(tile) <- CRS("+proj=longlat +datum=WGS84")
plot(tile, 1) 

仅绘制栅格的第一个波段,进行适当的地理配准: Georeferenced example plot

我们还可以索引Qtiles导出的目录和子目录,以便我们可以根据需要检索和地理配置一个或多个切片:

library(stringr)
library(reshape2)

# index directories of slippy map tiles
# tiles obtain with Qtiles plugin for zoom levels 10-16
x <- list.files(".../tiles/", recursive = TRUE) 
index <- strsplit(x,"/") %>%
  data.frame() %>% 
  t() %>% 
  data.frame() 
# get only zoom level 16
index <- subset(index, X1 == "16")
# x and y array of tile reference numbers
index <- dcast(index, X2 ~ X3, value.var = "X3")
x.index <- as.character(index[,1])
y.index <- as.character(index[1,2:(length(index[1,]))]) 
y.index <- gsub(".png","",y.index)
x.index <- as.numeric(x.index)
y.index <- as.numeric(y.index)

#example usage
my.extent <- num2deg(xtile = x.index[1], ytile = y.index[1], zoom = 16)