Определите области нулей, которые окружены единицами в матрице - PullRequest
0 голосов
/ 05 ноября 2019

У меня есть список двоичных матриц. В каждой матрице я хочу обнаружить области белых пикселей (0), окруженные кольцом (цепочкой) из подключенных черных пикселей (1).

Например, в приведенной ниже матрице естьдве области белых пикселей (нулей), обе целиком окруженные «цепочкой» соединенных 1-х: группа 2х2 и 3х2 из 0с.

m
#         [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#    [1,]    1    1    1    1    0    0    1
# -> [2,]    1    0    0    1    1    1    1
# -> [3,]    1    0    0    1    0    0    1 <- 
#    [4,]    1    1    1    1    0    0    1 <- 
#    [5,]    1    0    0    1    0    0    1 <-
#    [6,]    0    1    1    1    1    1    1

m <- matrix(c(1, 1, 1, 1, 0, 0, 1,
              1, 0, 0, 1, 1, 1, 1,
              1, 0, 0, 1, 0, 0, 1,
              1, 1, 1, 1, 0, 0, 1,
              1, 0, 0, 1, 0, 0, 1,
              0, 1, 1, 1, 1, 1, 1),
            byrow = TRUE, nrow = 6)

Пример с тремя двоичными матрицами в list:

set.seed(12345)
x <- matrix(sample(c(0,1), 225, prob=c(0.8,0.2), replace=TRUE), nrow = 15)

set.seed(9999)
y <- matrix(sample(c(0,1), 225, prob=c(0.8,0.2), replace=TRUE), nrow = 15)

set.seed(12345)
z <- matrix(sample(c(0,1), 225, prob=c(0.8,0.2), replace=TRUE), nrow = 15)

mat_list <- list(x, y, z)

Я думал об использовании функции boundaries в пакете raster, поэтому я начну с преобразования матриц в растр:

library(igraph)
library(raster)

lapply(list, function (list) {
  Rastermat <- raster(list)
})

Любое руководство о том, как я мог бы реализовать это, будет оценено.


1 Ответ

0 голосов
/ 06 ноября 2019

ПЕРЕСМОТРЕННЫЙ ОТВЕТ для новой информации.

Для этого ответа определение подключенных пикселей немного больше, чем определение, используемое для обработки изображения. Здесь пиксели считаются связанными, если они имеют общую сторону как {x,y} и {x+1,y} или {x,y} и {x,y+1} или касаются в углу как {x,y} и {x+1,y+1}. Возможно, что другие пакеты (такие как igraph) могут быть более эффективными для этой задачи, но EBImage может выполнять работу с инструментами для визуализации или дальнейшей обработки результатов.

Функция bwlabelв пакете EBImage используется здесь для поиска связанных групп пикселей. Как описывают авторы:

bwlabel находит каждый связанный набор пикселей, кроме фона, и перемаркирует эти наборы уникальным возрастающим целым числом

Это частьпакета Bioconductor EBImage , который представляет собой набор инструментов для обработки и анализа изображений для R . Это немного большой. Следующий код проверяет доступность и при необходимости пытается загрузить и установить пакет:

# EBImage needed through Bioconductor, which uses BiocManager
  if (!require(EBImage)) {
    if (!requireNamespace("BiocManager", quietly = TRUE))
      install.packages("BiocManager")
    BiocManager::install("EBImage")
    require(EBImage)
  }

Инструменты EBImage позволяют извлекать связанные пиксели из двоичных изображений (рассматриваемых объектов) и количественно определять или визуализироватьих. С извинениями за любое превышение, вот ответ REPLACED с более обширным примером, включающим нерегулярные объекты для демонстрации решения.

Как правило, 0 используется для отсутствия данных при обработке изображений, поэтомуданные в примере используют 0 для не данных и 1 для данных.

# Sample data with 1 as data, 0 as non-data
dat <- c(0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,
         0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,
         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,
         0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,
         0,0,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,0,1,1,
         0,0,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,0,0,0,
         0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
         0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
         0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
         0,0,1,1,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,0,
         0,0,1,1,1,1,1,1,0,0,0,1,1,1,0,0,1,1,1,0,
         0,0,1,1,1,1,1,1,0,0,0,1,1,1,0,0,1,0,1,0,
         0,0,1,1,1,1,1,1,0,0,0,1,1,1,0,0,1,1,1,0,
         0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
         0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,
         0,1,1,0,0,0,0,0,0,1,1,0,0,0,1,1,1,0,0,0,
         0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
         0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
         0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
# convert to 20x20 pixel image object
  x <- Image(dat, dim = c(20, 20)) # use 1 for data, 0 for non-data
# plotting with base graphics allows the use of other R tools
  plot(x, interp = FALSE) # interpolate = FALSE option preserves pixels

Представление изображения двоичного массива 20 x 20 в dat.

image representation of data

# bwlabel() extracts connected pixels from a binary image
# and labels the connected objects in a new Image object
  xm <- bwlabel(x)
  xm # show the first 5 rows, first 6 columns of "objects" identified by bwlabel
> Image 
>   colorMode    : Grayscale 
>   storage.mode : integer 
>   dim          : 20 20 
>   frames.total : 1 
>   frames.render: 1 
> 
> imageData(object)[1:5,1:6]
>      [,1] [,2] [,3] [,4] [,5] [,6]
> [1,]    0    0    0    0    0    0
> [2,]    0    0    0    0    0    0
> [3,]    0    0    0    0    4    4
> [4,]    1    1    0    0    4    4
> [5,]    1    1    0    0    4    4

Количество объектов(найденные пиксели) - это просто максимальное значение в объекте, возвращаемое bwlabel. Размер каждого объекта (подключенных пикселей) легко получить с помощью функции table. Эта информация может быть извлечена и использована для подготовки маркированного изображения. Этот пример включает в себя объект с отверстием.

# total number of objects found
  max(xm) 
> 9

# size of each object (leaving out background or value = 0 pixels)
  table(xm[xm > 0])
>  1  2  3  4  5  6  7  8  9 
>  8 13 21 36 15  8  4  6 21 

# plot results with labels
  iy <- (seq_along(x) - 1) %/% dim(x)[1] + 1
  ix <- (seq_along(x) - 1) %% dim(x)[1] + 1

  plot(xm, interp = FALSE)
  text(ix, iy, ifelse(xm==0, "", xm)) # label each pixel with object group

labeled objects

Пять объектов окружены «цепочкой» связанных фоновых пикселей: # 3, № 4, № 6, № 7 и № 9. Объект № 6 включен, хотя у него есть отверстие. Логика может быть скорректирована, чтобы исключить объекты с отверстиями. Объекты № 1 и № 2 должны быть исключены, потому что они граничат с краем. Объекты № 5 и № 8 должны быть исключены, потому что они касаются в углу. Если это точно соответствует задаче, EBImage все еще может помочь с логикой, перечисленной ниже. Вкратце, граница вокруг каждого объекта будет создана и определена, если она охватывает только пустые (или не имеющие границы) пиксели в исходном изображении.

  1. Извлечение каждого найденного объекта с помощью bwlabel как отдельногоimage (xobj)
  2. Добавление границы черного (нулевого) пикселя к каждому объекту в xobj
  3. Расширение каждого объекта в xobj на один пиксель с помощью EBImage::dilate (xdil)
  4. Создание маски разности с помощью xor (xmask)
  5. Добавление ненулевой границы к исходному изображению (x2)
  6. Объединениеxmask и x2 для определения границ, имеющих непустые пиксели
  7. Удаление объектов, указанных выше
# Extract each object found by bwlabel() as a separate image
  xobj <- lapply(seq_len(max(xm)), function(i) xm == i)

# Add a border of black (zero) pixels to each object in `xobj`
  xobj <- lapply(xobj, function(v) cbind(0, rbind(0, v, 0), 0))
  xobj <- lapply(xobj, as.Image)
  xobj <- combine(xobj) # combine as multi-dimensional array

# Dilate each object in `xobj` by one pixel
  br <- makeBrush(3, shape = "box") # 3 x 3 structuring element
  xdil <- dilate(xobj, br)

# Create difference mask with xor()
  xmask <- xor(xdil, xobj) # difference is the border

# Add a non-zero border to the original image
  x2 <- Image(cbind(1, rbind(1, x, 1), 1))

# Identify borders that have non-blank pixels
  target <- Image(x2, dim = dim(xmask)) # replicate x2
  sel <- which(apply(xmask & target, 3, any) == TRUE)

# Remove objects identified above (keeping original numbers)
  found <- rmObjects(xm, sel, reenumerate = FALSE)

# Show the found objects
  table(found[found > 0])
>  3  4  6  7  9 
> 21 36  8  4 21 

Каждый из объектов можно исследовать путем построения графика. Многомерные изображения, такие как xobj, xdil и xmask, могут быть нанесены с помощью plot(xobj, all = TRUE, interp = FALSE) для просмотра промежуточных результатов. Здесь отфильтрованные (найденные) объекты переназначаются с исходными номерами объектов

  plot(found, interp = FALSE)
  text(ix, iy, ifelse(found==0, "", found)) # label each pixel group no.

found objects

Чтобы узнать больше о EBImage см. На упаковке виньетка .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...