在R或Grass GIS中填充栅格孔

时间:2016-12-16 14:11:36

标签: r r-raster sp grass

样本数据

x <- raster(x=matrix(data=1:36, nrow=6), xmn=-1000, xmx=1000, ymn=-100, ymx=900)
x[c(8, 15, 16, 17, 22, 25, 26, 30, 31)] <- NA
plot(x)

enter image description here

问题

如何区分(算法上)光栅中的孔,即由单元c(15:17,22)限定的区域与非空洞的其他间隙(即其余空单元)? / p>

这样就可以只对光栅的孔/岛区域进行操作,用自定义值填充孔等等。

实际的栅格有大约30000个孔,因此速度很重要。我对R和Grass GIS解决方案感兴趣。非常感谢您的帮助,非常感谢!

3 个答案:

答案 0 :(得分:2)

多边形化怎么样?为了速度,我不知道它的价值,但你可以:

x[!is.na(values(x))]<-1
plot(x)
x[is.na(values(x))]<-0

hole <- rasterToPolygons(x, fun=NULL, n=4, na.rm=TRUE, digits=12, dissolve=T)

现在你必须将你的单部分多边形变为多部分:

hole2 <- SpatialPolygons(lapply(hole@polygons[[1]]@Polygons, function(xx) Polygons(list(xx),ID=round(runif(1,1,100000000)))))

plot(hole2, add=T)

现在你找到了“真正的”洞,这些洞是没有触及边界的洞

around <- as(extent(x), "SpatialLines")
touch_border <- gIntersects(around, hole2, byid=T) 
extract(x, hole2[!touch_border,],cellnumbers=T)

它可以逐个为您提供单元格。它发现单元格“8”,你不是说它是一个洞,所以我不确定它是否正确,但它必须非常接近!

如果在R中速度很慢,请在GRASS中执行相同的算法(主要是rasterToPolygons调用)

答案 1 :(得分:2)

这里没有多边形化的解决方案:(它不优雅,但它有效)。 然而你必须将你的洞/岛重新分类为值(即999)和所有其他非岛屿到NA。像这样:

x <- raster(x=matrix(rep(NA,36), nrow=6), xmn=-1000, xmx=1000, ymn=-100, ymx=900)
x[c(8, 15, 16, 17, 22, 25, 26, 30, 31)] <- 999

plot(x)

Inital dummy raster

现在我使用clump()函数来检查是否存在孤岛并且该函数很酷,它还会返回这些岛的ID:

#Get Islands with IDs
cl <- clump(x,directions=8)
plot(cl)

clumps/island with IDs

然后我根据岛屿的频率创建一个数据帧(这只是为了得到每个岛屿的ID)

freqCl <- as.data.frame(freq(cl))

#remove the (row) which corresponds to the NA values (this is important for the last step)
freqCl <- freqCl[-which(is.na(freqCl$value)),]

检查是否有任何岛屿接触边界:

#Check if the island touches any border and therefore isn't a "real island" (first and last column or row)

noIslandID <- c()
#First row
if(any(rownames(freqCl) %in% cl[1,])){
  eliminate   <- rownames(freqCl)[rownames(freqCl) %in% cl[1,]]
  noIslandID  <- append(noIslandID, eliminate)
}
#Last row
if(any(rownames(freqCl) %in% cl[nrow(cl),])){
  eliminate  <- rownames(freqCl)[rownames(freqCl) %in% cl[nrow(cl),]]
  noIslandID <- append(noIslandID, eliminate)
}
#First col
if(any(rownames(freqCl) %in% cl[,1])){
  eliminate   <- rownames(freqCl)[rownames(freqCl) %in% cl[,1]]
  noIslandID  <- append(noIslandID, eliminate)
}
#Last col
if(any(rownames(freqCl) %in% cl[,ncol(cl)])){
  eliminate   <- rownames(freqCl)[rownames(freqCl) %in% cl[,ncol(cl)]]
  noIslandID  <- append(noIslandID, eliminate)
}

消除那些触及边界的岛屿:

noIslandID <- unique(noIslandID)
IslandID   <- setdiff(rownames(freqCl), noIslandID)

在最后一步中,为每个真正的岛屿分配一个&#34;来自初始光栅:

for(i in 1:length(IslandID)) {
  x[cl[]==as.numeric(IslandID[i])] <- 1
}

plot(x)

enter image description here

答案 2 :(得分:0)

在这种情况下,如果一个单元在四个基本方向的每个方向上都被至少一个非缺失值所包围,则该单元位于孔中。您可以使用下面的代码对此进行测试,该代码还将缺失的值替换为99。

x2 <- x                        ## Create a copy of the raster
notNA <- !is.na(as.matrix(x))  ## Matrix identifying cells that are not NA

nr <- nrow(x) ## Number of rows
nc <- ncol(x) ## Number of columns

for(i in 2:(nr-1)) {       ## Loop over rows, ignoring first and last
    for(j in 2:(nc-1)) {   ## Loop over columns, ignoring first and last
        if(notNA[i,j]) ## Skip cell if not NA
            next
        ## For NA cells, determine if non-NA cell exists in each cardinal direction
        any.north <- any(notNA[1:(i-1),j])
        any.south <- any(notNA[(i+1):nr,j])
        any.west <- any(notNA[i,1:(j-1)])
        any.east <- any(notNA[i,(j+1):nc])
        if(any.north & any.south & any.west & any.east)
            x2[i,j] <- 99 ## If cell is in hole, repalce with new value
    }
}

这是新的栅格:

New raster with holes filled by the value 99