如何使用R生成离散2D高斯平滑内核

时间:2014-03-26 00:39:35

标签: r smoothing

我想知道R是否具有此功能,或者如何编码高斯平滑内核的2D离散版本。目标是使用它来平滑2D矩阵值。

2 个答案:

答案 0 :(得分:1)

我写了一个函数来解决我的问题。这是我称之为 kernelsmooth 的功能。它需要三个参数,一个要平滑的数据矩阵,一个内核和一个布尔标志 norm ,如果为真,则通过其值的平均值对内核进行标准化(防止矩阵数据膨胀)。

kernelsmooth <- function(x, kern, norm=TRUE) {
  # how many rows/cols of zeroes are used to pad.
  width <- dim(kern)[1]
  pad <- floor(width / 2)

  # record the width and height the input data matrix
  x_w <- ncol(x)
  x_h <- nrow(x)

  # Are we normalizing the kernel?
  if (norm == TRUE) {
    k <- kern / sum(abs(kern))
  } else {
    k <- kern
  }

  # pad all around the matrix an equal width of zeros
  x_pad <- t(padzeros(data=x, nzeros=pad, side="both"))
  x_pad <- t(padzeros(data=x_pad, nzeros=pad, side="both"))

  # Pre-allocate the final (smoothed) data matrix
  s <- matrix(0, nrow = x_h, ncol = x_w)

  # Pre-allocate a temporary matrix for the iterative calculations
  temp <- matrix(0, width, width)

  # Loop through the data to apply the kernel.
  for (col in 1:x_w ) {
    for (row in 1:x_h ) {
      temp <- x_pad[row:(row + width - 1), col:(col + width - 1)]
      s[row,col] <-  sum(k * temp)
    }
  }

  # return the smoothed data
  return(s)
}

一些例子:

  1. 不要平滑矩阵(应用类似于单位矩阵的身份内核)。

    kernelsmooth(x =矩阵(2,5,5),kern =矩阵(c(0,0,0,0,1,0,0,0,0),3,3))

  2. 输出:

         [,1] [,2] [,3] [,4] [,5] [,6]
    [1,]    2    2    2    2    2    2
    [2,]    2    2    2    2    2    2
    [3,]    2    2    2    2    2    2
    [4,]    2    2    2    2    2    2
    [5,]    2    2    2    2    2    2
    [6,]    2    2    2    2    2    2
    
    1. 平均平滑(如果自身及其邻居平均每个元素平滑):

      kernelsmooth(x =矩阵(4,5,5),kern =矩阵(1,3,3))

    2. 输出:

               [,1]     [,2]     [,3]     [,4]     [,5]
      [1,] 1.777778 2.666667 2.666667 2.666667 1.777778
      [2,] 2.666667 4.000000 4.000000 4.000000 2.666667
      [3,] 2.666667 4.000000 4.000000 4.000000 2.666667
      [4,] 2.666667 4.000000 4.000000 4.000000 2.666667
      [5,] 1.777778 2.666667 2.666667 2.666667 1.777778
      
      1. 高斯平滑(各向同性平滑):

        高斯&lt; - (c(1,4,7,4,1)%*%t(c(1,4,7,4,1))) kernelsmooth(x = matrix(5,8,8),kern = gauss)

      2. 输出:

                 [,1]     [,2]     [,3]     [,4]     [,5]     [,6]     [,7]     [,8]
        [1,] 2.491349 3.321799 3.529412 3.529412 3.529412 3.529412 3.321799 2.491349
        [2,] 3.321799 4.429066 4.705882 4.705882 4.705882 4.705882 4.429066 3.321799
        [3,] 3.529412 4.705882 5.000000 5.000000 5.000000 5.000000 4.705882 3.529412
        [4,] 3.529412 4.705882 5.000000 5.000000 5.000000 5.000000 4.705882 3.529412
        [5,] 3.529412 4.705882 5.000000 5.000000 5.000000 5.000000 4.705882 3.529412
        [6,] 3.529412 4.705882 5.000000 5.000000 5.000000 5.000000 4.705882 3.529412
        [7,] 3.321799 4.429066 4.705882 4.705882 4.705882 4.705882 4.429066 3.321799
        [8,] 2.491349 3.321799 3.529412 3.529412 3.529412 3.529412 3.321799 2.491349
        

答案 1 :(得分:0)

矩阵边缘的急剧下降,例如从3.529412到0,是坏消息。您需要将矩阵放大到边缘值尽可能接近零的大小。您可以通过计算每个矩阵的2D傅里叶变换来检查此语句的有效性,并将其与在较大版本上完成的相同变换进行比较。当应用于您的数据时,您还会看到更好的结果。