我有一个小光栅。它是来自Digital Globe底图的单个图块(缩放= 16);它是标准的256 x 256像素。在QGIS中,我创建了一个多边形shapefile并添加了大约50个特征。栅格和shapefile位于同一个CRS中。在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]中。
似乎brick()函数将x和y扩展区设置为正数,但我已经查看了包/函数文档,并且不明白为什么会出现这种情况。如何让这两个文件在R中对齐?
我已经尝试将栅格导出为GeoTIFF,但这也不起作用。我也试过在shapefile中读一些其他R包,比如rgdal。我可以让它“工作”,如果在QGIS中我导出shapefile,同时以光栅为中心,并选择“地图视图范围”,但这不是最佳解决方案,并且(a)我需要使用数组地图图块并且不想手动缩放到每个图块,并且(b)这并不能解释我所犯的错误。我甚至不确定我的问题是从QGIS导出还是导入到R,尽管我很确定我的错误是在brick()中。
注意:有一个类似的声音问题here,但是尽管问题的标题,错误仍然是坐标参考系统。
答案 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)
我们还可以索引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)