I'm trying to write my own image filtering functions and one easier style is averaging the cell neighbour values. I've got a matrix with pixel values, but instead of using a huge for loop I'm trying to use apply, but can't seem to get the current co-ordinates of a cell being "worked on".
I'm struggling to get any multi-variable function to work with apply(), but ideally I think I'd pass the whole matrix to the function?
picture = matrix(data=0,nrow=px,ncol=px)
# I then have a function that draws a few squares and adds some random noise
# Now I'd like to go through the matrix, find the cells neighbour values, avg.
test <- function(x,cur_matrix){
up = cur_matrix[i,j+1]
left = cur_matrix[i-1,j]
right = cur_matrix[i+1,j]
down = cur_matrix[i,j-1]
avg = ( up + down + left + right ) / 4
x = avg
return(x)
}
picture_2 = apply(picture, 1:2, test, cur_matrix = picture)
How could I pass both the matrix "picture" and the current i,j co-ords into this function?
For pixel averaging, you usually may need to consider its valid neighbors + itself, instead of the neighbors only (as revealed in your post).
Update: Vectorized
As pointed out by @Onyambu, yes, the approach given in
ftic0(see my earliest solution) is super inefficient, both time-wisely and space-wisely. So, in what follows, we avoid spanning the distance space as did previously and vectorize the operations like belowand let's see the performance improvement
which shows
and
bench::markshows
Previous Solution: Low-code version but inefficient
You can try
sapplylike thisand we will see that
In the approach above, you should be aware of treatment for edge and corner pixels:
2neighbors for averaging3neighbors for averaging