Как использовать связанные компоненты openCV со статистикой в ​​Python?

Я ищу пример того, как использовать функцию OpenCV ConnectedComponentsWithStats () в python, обратите внимание, что это доступно только с OpenCV 3 или новее. Официальная документация показывает только API для C ++, хотя функция существует при компиляции для python. Я нигде не нашел в сети.


person Zack Knopp    schedule 07.03.2016    source источник


Ответы (3)


Функция работает следующим образом:

# Import the cv2 library
import cv2
# Read the image you want connected components of
src = cv2.imread('/directorypath/image.bmp')
# Threshold it so it becomes binary
ret, thresh = cv2.threshold(src,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# You need to choose 4 or 8 for connectivity type
connectivity = 4  
# Perform the operation
output = cv2.connectedComponentsWithStats(thresh, connectivity, cv2.CV_32S)
# Get the results
# The first cell is the number of labels
num_labels = output[0]
# The second cell is the label matrix
labels = output[1]
# The third cell is the stat matrix
stats = output[2]
# The fourth cell is the centroid matrix
centroids = output[3]

Метки - это матрица размера входного изображения, в которой каждый элемент имеет значение, равное его метке.

Статистика - это матрица статистики, которую вычисляет функция. Он имеет длину, равную количеству меток, и ширину, равную количеству характеристик. Его можно использовать с документацией OpenCV для этого:

Вывод статистики для каждой метки, включая фоновую метку, доступную статистику см. Ниже. Доступ к статистике осуществляется через stats [label, COLUMN], доступные столбцы определены ниже.

  • cv2.CC_STAT_LEFT Крайняя левая координата (x), включающая начало ограничивающей рамки в горизонтальном направлении.
  • cv2.CC_STAT_TOP Самая верхняя координата (y), включающая начало ограничивающей рамки в вертикальном направлении.
  • cv2.CC_STAT_WIDTH Горизонтальный размер ограничивающей рамки.
  • cv2.CC_STAT_HEIGHT Размер ограничивающей рамки по вертикали.
  • cv2.CC_STAT_AREA Общая площадь (в пикселях) подключенного компонента.

Центроиды - это матрица с координатами x и y каждого центроида. Строка в этой матрице соответствует номеру метки.

person Zack Knopp    schedule 07.03.2016
comment
Я должен сказать, что по какой-то причине мне пришлось использовать cv2.THRESH_BINARY вместо cv2.THRESH_BINARY + cv2.THRESH_OTSU, тогда мне пришлось преобразовать src в целое число и thresh в float, чтобы он работал. Не знаю почему, но иначе это не сработало. - person Бојан Матовски; 27.06.2016
comment
Я не понимаю, зачем вы создаете матрицу меток, когда она все равно является частью вывода? - person ypnos; 01.07.2016
comment
@ypnos Это не нужно для подключенных компонентов со статистикой, но нужно делать для подключенных компонентов без статистики. Я думаю, что эта часть просто осталась от меня, когда я делал это по-другому. Исправил сейчас. Ваше здоровье! - person Zack Knopp; 04.07.2016
comment
Большое спасибо за это! Это гораздо лучшее описание того, как это работает, чем в документации по C ++. - person Haldean Brown; 11.10.2016
comment
кто-нибудь может объяснить, как использовать ярлыки? Как проверить, какая метка - это центроид? - person recurf; 08.12.2016
comment
Каждому компоненту на изображении присваивается номер (метка). Фон имеет метку 0, а дополнительные объекты пронумерованы от 1 до num_labels-1. Центроиды индексируются теми же номерами, что и метки. centroids[0] не особо полезен - это просто фон. centroids[1:num_labels] это то, что вы хотите. - person krs013; 26.02.2017
comment
@ZackKnopp Вы также знаете, как я могу упорядочить этикетки по площади, ширине или высоте? - person matchifang; 24.07.2017
comment
@ZackKnopp Это неверно, вы можете использовать функцию и без статистики, например: _, labels = cv2.connectedComponents(segmentation) :) - person smcs; 01.09.2017
comment
@matchifang Вы можете создать массив с областями компонентов: areas=output[2][:,4] Затем массив с номерами компонентов: nr=np.arange(output[0]) Затем отсортировать их по размеру области: ranked=sorted(zip(areas,nr)) С помощью отсюда: stackoverflow.com/questions/6618515/ - person smcs; 01.09.2017
comment
cv2.connectedComponentsWithStats не принимает возможность подключения в качестве входного аргумента в OpenCV 3 или 4, и я не думаю, что эта функция присутствовала в 2. Это просто смешение между conectedComponentsWithStats и connectedComponentsWithStatsWithAlgorithm? output = cv2.connectedComponentsWithStats(thresh) дает мне тот же результат. - person Atnas; 24.02.2021

Я приходил сюда несколько раз, чтобы вспомнить, как это работает, и каждый раз мне приходится сокращать приведенный выше код до:

_, thresh = cv2.threshold(src,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
connectivity = 4  # You need to choose 4 or 8 for connectivity type
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh , connectivity , cv2.CV_32S)

Надеюсь, всем пригодится :)

person Dan Erez    schedule 13.11.2018

Добавляя к Zack Knopp ответу, если вы используете изображение в оттенках серого, вы можете просто использовать:

import cv2
import numpy as np

src = cv2.imread("path\\to\\image.png", 0)
binary_map = (src > 0).astype(np.uint8)
connectivity = 4 # or whatever you prefer

output = cv2.connectedComponentsWithStats(binary_map, connectivity, cv2.CV_32S)

Когда я попытался использовать Zack Knopp ответ на изображении в оттенках серого, это не сработало, и это было моим решением.

person Barel Levy    schedule 05.03.2018