rgeospatialspatialedge-detectionterra

using terra::focal() with even sided weight matrix


i want to use the terra::focal() with an even sided matrix (e.g. to apply "Roberts cross" edge detection; https://en.wikipedia.org/wiki/Roberts_cross).

However, focal() only accepts windows with odd sides. On the other hand, the focal3D() documentation states "w =window. [...] If you desire to use even sides, you can use an array, and pad the values with rows and/or columns that contain only NAs."

Applying this "trick" for 2D focal does not work:

r <- rast(matrix(rnorm(1000),ncol=100,nrow=100))
robx <- matrix(c(NA,1,0,NA,0,1),nrow=3)
plot(focal(r,w=robx,fun="sum")

while (of course), a 3 by 3 matrix without NAs works:

sobx <- matrix(c(-1,-2,-1,0,0,0,1,2,1) / 4, nrow=3)
plot(focal(r,w=sobx,fun="sum")

Are there any known workarounds? How can i get focal() to accept even sided windows (or at least trick it)?

Cheers.


Solution

  • The matrix robx in your question doesn't meet the requirements described in the instructions; it is a 3 x 2 matrix.

    matrix(c(NA, 1, 0, NA, 0, 1), nrow = 3)
    #>      [,1] [,2]
    #> [1,]   NA   NA
    #> [2,]    1    0
    #> [3,]    0    1
    

    Obviously, one of its sides has an even number of entries, so you get the w must be odd sized error.

    If you give a 3x3 matrix where the top row and last column are NA, then you get the desired result:

    library(terra)
    #> terra 1.7.3
    
    r <- rast(matrix(rnorm(1000), ncol = 100, nrow = 100))
    
    robx <- matrix(c(NA, 1, 0, NA, 0,1, NA, NA, NA), nrow = 3)
    
    robx
    #>      [,1] [,2] [,3]
    #> [1,]   NA   NA   NA
    #> [2,]    1    0   NA
    #> [3,]    0    1   NA
    

    No we can run focal without issues:

    plot(focal(r, w = robx, fun = "sum"))
    

    Created on 2023-10-05 with reprex v2.0.2