0

I am trying to get the number of 1s (black pixels) connected by more than 1 other black pixel in a binary matrix. I have a matrix...

set.seed(1234)
mat <- matrix(rbinom(30, 1, 0.5), nrow = 5)

which outputs a matrix...

      [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    0    1    1    0    0    0
[2,]    1    1    1    1    0    0
[3,]    1    0    1    0    0    0
[4,]    1    0    1    1    0    0

I am now trying to figure out how to use this matrix to get the count (sum) of all black pixels that have more than 1 other black pixel connected such as...

[1,2] [1,3] [2,1] [2,2] [2,3] [3,1] [3,3] [4,3] = 8 

Where 8 I would think would be the expected result. Is there a way to do this?

Arron
  • 25
  • 7

1 Answers1

2

You can use diff in combination with apply to get the number of neighbour pixels having a 1.

f  <- function(x) {
  tt  <- diff(x)==0  #See it there is no difference between Neighbors - Length is 1 less then x
  (c(0, tt) + c(tt, 0)) * x #Add a Zero at the begin and end and multiply it with x to get the number of Neighbors in 1 direction
}

n  <- t(apply(mat, 1, f)) + apply(mat, 2, f) #Use function f over rows and cols to get the number of Neighbors is two directions

sum(n>1)
#[1] 8

which(n>1, arr.ind = T)
     row col
#[1,]   3   1
#[2,]   4   1
#[3,]   5   1
#[4,]   4   2
#[5,]   5   2
#[6,]   1   3
#[7,]   2   6
#[8,]   3   6

n
#     [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]    0    1    3    1    0    1
#[2,]    1    0    1    0    0    2
#[3,]    2    0    0    0    0    2
#[4,]    3    3    1    0    0    1
#[5,]    2    2    0    0    0    0

Data:

set.seed(1234)
mat <- matrix(rbinom(30, 1, 0.5), nrow = 5)
mat
#     [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]    0    1    1    1    0    1
#[2,]    1    0    1    0    0    1
#[3,]    1    0    0    0    0    1
#[4,]    1    1    1    0    0    1
#[5,]    1    1    0    0    0    0
GKi
  • 37,245
  • 2
  • 26
  • 48
  • Thanks this works great @GKi! If I wanted to do these on a number of csv files at the same time by reading them in like so... temp <- list.files(pattern="*.csv") files <- lapply(temp, read.delim). How would I stop the error dim(X) must have a positive length? – Arron Oct 14 '19 at 15:07
  • Maybe try `lapply(files, function(mat) sum(t(apply(mat, 1, f)) + apply(mat, 2, f) > 1))` – GKi Oct 14 '19 at 15:14
  • Thanks so much @GKi it works! Please could you briefly explain what is happening in the function above just so I can gain more understanding of it? – Arron Oct 14 '19 at 15:33
  • I have added some inline comments. – GKi Oct 14 '19 at 15:39
  • Thanks for the comments @GKi! – Arron Oct 14 '19 at 15:40
  • Just out of curiosity @GKi how would I do 'lapply(files, function(mat) sum(t(apply(mat, 1, f)) + apply(mat, 2, f) > 1))' to find the sum connected by 5 or more for instance? I tried just changing the 1 above to 5 but this outputs as 0 even though there is at least 1 csv file in my directory that contains 5 or more 1s together. – Arron Oct 16 '19 at 21:06
  • @Arron Here it is looking only for direct neighbours and there the maximum is 4. – GKi Oct 21 '19 at 06:45