【问题标题】:Estimate the gradient of an undefined surface估计未定义曲面的梯度
【发布时间】:2013-04-28 05:28:33
【问题描述】:

我想估计 undefined 表面的梯度(坡度和坡向)(即函数未知)。为了测试我的方法,这里是测试数据:

require(raster); require(rasterVis)            
set.seed(123)
x <- runif(100, min = 0, max = 1)
y <- runif(100, min = 0, max = 1)
e <- 0.5 * rnorm(100)
test <- expand.grid(sort(x),sort(y))
names(test)<-c('X','Y')
z1 <- (5 * test$X^3 + sin(3*pi*test$Y))
realy <- matrix(z1, 100, 100, byrow = F)
# And a few plots for demonstration #
persp(sort(x), sort(y), realy, 
      xlab = 'X', ylab = "Y", zlab = 'Z',
      main = 'Real function (3d)', theta = 30, 
      phi = 30, ticktype = "simple", cex=1.4)
      contour(sort(x), sort(y), realy, 
      xlab = 'X', ylab = "Y",
      main = 'Real function (contours)', cex=1.4)

我将所有内容转换为栅格并使用rasterVis::vectorplot 进行绘图。一切看起来都很好。矢量场表示变化幅度最大的方向,阴影类似于我的等高线图...

test.rast <- raster(t(realy), xmn = 0, xmx = 1, 
                    ymn = 0, ymx = 1, crs = CRS("+proj"))
vectorplot(test.rast, par.settings=RdBuTheme, narrow = 100, reverse = T)

但是,我需要一个斜率值矩阵。据我了解向量图,它使用 raster::terrain 函数:

terr.mast <- list("slope" = matrix(nrow = 100, 
                                   ncol = 100, 
                                   terrain(test.rast, 
                                           opt = "slope", 
                                           unit = "degrees",
                                           reverse = TRUE, 
                                           neighbors = 8)@data@values, 
                                    byrow = T),
                  "aspect" = matrix(nrow = 100, 
                                    ncol = 100, 
                                    terrain(test.rast, 
                                            opt = "aspect", 
                                            unit = "degrees",
                                            reverse = TRUE, 
                                            neighbors = 8)@data@values, 
                                     byrow = T))

然而,坡度似乎真的很高...(90度是垂直的,对吧?!)

terr.mast$slope[2:6,2:6] 
#         [,1]     [,2]     [,3]     [,4]     [,5]
#[1,] 87.96546 87.96546 87.96546 87.96550 87.96551
#[2,] 84.68628 84.68628 84.68627 84.68702 84.68709
#[3,] 84.41349 84.41350 84.41349 84.41436 84.41444
#[4,] 84.71757 84.71757 84.71756 84.71830 84.71837
#[5,] 79.48740 79.48741 79.48735 79.49315 79.49367

如果我绘制斜率和坡向,它们似乎与矢量图形不符。

plot(terrain(test.rast, opt = c("slope", "aspect"), unit = "degrees", 
     reverse = TRUE, neighbors = 8))

我的想法:

  1. 向量图必须平滑斜率,但如何平滑?
  2. 我相当肯定raster::terrain 正在使用粗纱窗方法来计算斜率。可能是窗口太小了……可以扩大吗?
  3. 我是否以不恰当的方式处理这件事?我还能如何估计未定义曲面的斜率?

【问题讨论】:

  • 该对象数据槽中的单位不是“度”,而是“”。此外,test.rast 不是 S3 对象,并返回带有 test.rast$slope 的错误。我看到你拼写了“terr.mast”。你还有其他物体在敲打吗???

标签: r surface raster terrain gradient


【解决方案1】:

您也可以为此使用imager 函数:

library(imager)

# view (plot) image matrix
image(realy)

# compute gradient
gradient <- imgradient(as.cimg(realy), "xy")

# view x and y gradients
plot(gradient$x)
plot(gradient$y)

# access matrix values
mat.x <- as.matrix(gradient$x)
mat.y <- as.matrix(gradient$y)

【讨论】:

    【解决方案2】:

    我使用来自raster 的函数使用您的数据构建了一个RasterLayer

    library(raster)
    library(rasterVis)
    
    test.rast <- raster(ncol=100, nrow=100, xmn = 0, xmx = 1,  ymn = 0, ymx = 1)
    xy <- xyFromCell(test.rast, 1:ncell(test.rast))
    test.rast[] <- 5*xy[,1] + sin(3*pi*xy[,2])
    

    让我们用levelplot显示这个对象:

    levelplot(test.rast)
    

    vectorplot的梯度向量场:

    vectorplot(test.rast)
    

    如果您只需要坡度,请使用terrain

    slope <- terrain(test.rast, unit='degrees')
    
    levelplot(slope, par.settings=BTCTheme())
    

    但是,如果我没听错的话,你真的需要渐变,所以 你应该计算斜率和方面:

    sa <- terrain(test.rast, opt=c('slope', 'aspect'))
    

    为了理解vectorplot绘制箭头的方式, 在这里,我展示了它的(修改的)代码的水平部分 并计算箭头的垂直分量:

    dXY <- overlay(sa, fun=function(slope, aspect, ...){
        dx <- slope*sin(aspect) ##sin due to the angular definition of aspect
        dy <- slope*cos(aspect)
        c(dx, dy)
        })
    

    由于原RasterLayer的结构, 水平分量几乎是恒定的,所以让我们画出我们的 注意垂直分量。下一个代码覆盖了 垂直分量上的矢量场的箭头。

    levelplot(dXY, layers=2, par.settings=RdBuTheme()) +
        vectorplot(test.rast, region=FALSE)
    

    最后,如果您需要坡度和坡向的值,请使用 getValues:

    saVals <- getValues(sa)
    

    【讨论】:

    • 感谢奥斯卡的帮助。正是我想要的。
    猜你喜欢
    • 2017-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    相关资源
    最近更新 更多