Numpy 2d-массив: получить индексы всех записей, которые связаны и имеют одно и то же значение

У меня есть 2D-массив numpy, заполненный целочисленными значениями от 0 до N, как я могу получить индексы всех записей, которые напрямую связаны и имеют одно и то же значение.

Дополнение: Большинство записей нулевые и их можно игнорировать!

Пример входного массива:

[ 0 0 0 0 0 ]
[ 1 1 0 1 1 ]
[ 0 1 0 1 1 ]
[ 1 0 0 0 0 ]
[ 2 2 2 2 2 ]

Желаемые выходные показатели:

1: [ [1 0] [1 1] [2 1] [3 0] ] # first 1 cluster
   [ [1 3] [1 4] [2 3] [2 4] ] # second 1 cluster

2: [ [4 0] [4 1] [4 2] [4 3] [4 4] ] # only 2 cluster

формирование выходных массивов не важно, мне просто нужны отдельные кластеры значений, где можно адресовать отдельные индексы

Сначала я подумал:

N = numberClusters
x = myArray

for c in range(N):
   for i in np.where(x==c):
         # fill output array with i

но при этом отсутствует разделение кластеров с одинаковым значением

подключено означает «в той же строке»?

Jacquot 11.04.2018 12:10

с connected я имею в виду, что они «касаются» друг друга либо по x, y, либо по диагонали. Взгляните на пример, как я сгруппировал «единицы», надеюсь, это проясняет.

gustavz 11.04.2018 12:17

Ищите реализацию connected components labeling algorithm

MBo 11.04.2018 12:21
3
3
1 482
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать skimage.measure.label (при необходимости установите его с pip install scikit-image):

import numpy as np
from skimage import measure

# Setup some data
np.random.seed(42)
img = np.random.choice([0, 1, 2], (5, 5), [0.7, 0.2, 0.1])
# [[2 0 2 2 0]
#  [0 2 1 2 2]
#  [2 2 0 2 1]
#  [0 1 1 1 1]
#  [0 0 1 1 0]]

# Label each region, considering only directly adjacent pixels connected
img_labeled = measure.label(img, connectivity=1)
# [[1 0 2 2 0]
#  [0 3 4 2 2]
#  [3 3 0 2 5]
#  [0 5 5 5 5]
#  [0 0 5 5 0]]

# Get the indices for each region, excluding zeros
idx = [np.where(img_labeled == label)
       for label in np.unique(img_labeled)
       if label]
# [(array([0]), array([0])),
#  (array([0, 0, 1, 1, 2]), array([2, 3, 3, 4, 3])),
#  (array([1, 2, 2]), array([1, 0, 1])),
#  (array([1]), array([2])),
#  (array([2, 3, 3, 3, 3, 4, 4]), array([4, 1, 2, 3, 4, 2, 3]))]

# Get the bounding boxes of each region (ignoring zeros)
bboxes = [area.bbox for area in measure.regionprops(img_labeled)]
# [(0, 0, 1, 1),
#  (0, 2, 3, 5),
#  (1, 0, 3, 2),
#  (1, 2, 2, 3),
#  (2, 1, 5, 5)]

Ограничивающие рамки могут быть найдены с помощью очень полезной функции skimage.measure.regionprops, которая содержит множество информации о регионах. Для ограничивающего прямоугольника он возвращает кортеж (min_row, min_col, max_row, max_col), где пиксели, принадлежащие ограничивающему прямоугольнику, находятся в полуоткрытом интервале [min_row; max_row) и [min_col; max_col).

Позвольте нам продолжить обсуждение в чате.

gustavz 11.04.2018 13:54

как я могу дополнительно получить класс, назначенный ограничивающей рамке? Потому что, когда я беру класс, который назначен координатам блока, я в основном получаю фон, поскольку минимальные значения x, y обычно не лежат на объекте.

gustavz 11.04.2018 16:34

@GustavZ Какой лейбл? Значение, которое находится в исходном массиве? Для этого можно использовать [img[i][0] for i in idx]. Если вам нужна метка, указанная в маркировке, вы можете использовать [area.label for area in measure.regionprops(img_labeled)].

Graipher 11.04.2018 16:38

да, именно то, что делает [img[i][0] for i in idx], но это просто дает мне все метки, которые есть в текущем изображении (например, классификация), но я хочу найти точную метку для каждого ограничивающего прямоугольника, который я вычисляю с помощью boxes = [area.bbox for area in measure.regionprops(map_labeled)] (например, обнаружение) Как мне сделать что? Потому что сейчас я просто предполагаю, что в середине коробки должен быть объект, и я беру эту метку ...

gustavz 16.04.2018 09:31

@GustavZ См. Мой комментарий выше: [area.label for area in measure.regionprops(img_labeled)].

Graipher 16.04.2018 09:32

ты про [area.label for area in measure.regionprops(img_labeled)]? это делает то же самое с той лишь разницей, что это метка, созданная skimage. Но я хочу следующее: мой исходный image - это карта сегментации, где все пиксели являются метками классов, и после вычисления поля для каждого кластера мне также нужна метка для каждого кластера ... извините, если вы уже ответили на это , но я не вижу где

gustavz 16.04.2018 09:36

@GustavZ Вы правы, что я еще не ответил. Я вернусь к вам, когда перестану пользоваться мобильным телефоном.

Graipher 16.04.2018 10:03

неважно, я понял. с area.coords я могу адресовать правильные пиксели :) спасибо!

gustavz 16.04.2018 10:24

@GustavZ Да, я просто экспериментировал с этим.

Graipher 16.04.2018 10:25

Другие вопросы по теме