Python OpenCV — маркировка и анализ подключенных компонентов

начало работы с массивами Python Программирование и разработка

В этой статье мы научимся реализовывать маркировку и анализ подключенных компонентов с помощью OpenCV в Python.

Маркировка подключенных компонентов

Маркировка компонентов в основном представляет собой извлечение области из исходного изображения, за исключением того, что мы пытаемся найти только компоненты, которые «связаны», что определяется применением теории графов.

OpenCV предоставляет нам следующие 4 функции для этой задачи:

  • connectedComponents
  • connectedComponentsWithStats
  • connectedComponentsWithAlgorithm
  • connectedComponentsWithStatsWithAlgorithm

Нижние два более эффективны и быстрее, но работают, только если у вас есть параллельная предварительная обработка с включенным OpenCV, в противном случае разумнее придерживаться первых двух. И первый, и второй методы одинаковы, за исключением того, что во втором методе, как следует из названия, мы получаем статистику для каждого из компонентов, и мы будем использовать второй метод, потому что в большинстве случаев вам понадобится эта статистика..

В этой программе мы собираемся использовать изображение баннера для извлечения текстовых компонентов.

Установка зависимостей

Начнем с установки необходимых пакетов:

$ pip install opencv-contrib-python

Шаг 1: Загрузка изображения и предварительная обработка

Давайте сначала загрузим наше изображение и преобразуем его в изображение в градациях серого, это сделает алгоритм намного более эффективным и точным. После этого мы также применим размытие по Гауссу 7 × 7, это поможет удалить нежелательные края и поможет сделать более четкую сегментацию, которую мы сделаем на следующем шаге.

Python3

# Applying threshold
threshold = cv2.threshold(blurred, 0, 255,
cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]

Шаг 2: Пороговое значение

Пороговое определение — это очень простой метод сегментации изображения, который помогает нам отделить интересующие нас объекты фона и переднего плана. После применения размытия воспользуемся функцией cv2.threshold для сегментации изображения.

Python3

# Applying threshold
threshold = cv2.threshold(blurred, 0, 255,
cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]

Шаг 3: Применение метода анализа компонентов

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

Python3

# Apply the Component analysis function
analysis = cv2.connectedComponentsWithStats(threshold,
                                            4,
                                            cv2.CV_32S)
(totalLabels, label_ids, values, centroid) = analysis
# Initialize a new image to
# store all the output components
output = np.zeros(gray_img.shape, dtype="uint8")

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

Шаг 4: Отфильтруйте полезные компоненты

Давайте пройдемся по каждому из компонентов и воспользуемся статистикой, полученной на последнем шаге, чтобы отфильтровать полезные компоненты. Например, здесь я использовал значение «Площадь», чтобы отфильтровать только символы на изображении. И после фильтрации компонентов мы будем использовать переменную label_ids, чтобы создать маску для компонента, который мы просматриваем, и использовать операцию bitwise_or на маске для создания нашего окончательного вывода. Звучит сложно, но вы поймете это лучше после самостоятельной реализации кода.

Python3

# Loop through each component
for i in range(1, totalLabels):
    area = values[i, cv2.CC_STAT_AREA] 
    if (area > 140) and (area < 400):
      
        # Labels stores all the IDs of the components on the each pixel
        # It has the same dimension as the threshold
        # So we'll check the component
        # then convert it to 255 value to mark it white
        componentMask = (label_ids == i).astype("uint8") * 255
        
        # Creating the Final output mask
        output = cv2.bitwise_or(output, componentMask)

Как выбрать значение площади (или любое другое условие, например ширину или высоту) для фильтрации?

Добавьте оператор печати, чтобы распечатать значение статистики, которую вы хотите использовать в качестве условия, а затем для полезных компонентов запишите диапазон значений и используйте их для создания условия фильтра.

Шаг 5: Визуализируйте конечный результат

Теперь наш последний шаг — просто отобразить наше исходное изображение и окончательную маску, которую мы получили.

Python3

cv2.imshow("Image", img)
cv2.imshow("Filtered Components", output)
cv2.waitKey(0)

Ниже приведена реализация:

Python3

import cv2
import numpy as np
# Loading the image
img = cv2.imread('Images/img5.png')
# preprocess the image
gray_img = cv2.cvtColor(img , cv2.COLOR_BGR2GRAY)
# Applying 7x7 Gaussian Blur
blurred = cv2.GaussianBlur(gray_img, (7, 7), 0)
# Applying threshold
threshold = cv2.threshold(blurred, 0, 255,
    cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
# Apply the Component analysis function
analysis = cv2.connectedComponentsWithStats(threshold,
                                            4,
                                            cv2.CV_32S)
(totalLabels, label_ids, values, centroid) = analysis
# Initialize a new image to store
# all the output components
output = np.zeros(gray_img.shape, dtype="uint8")
# Loop through each component
for i in range(1, totalLabels):
  
      # Area of the component
    area = values[i, cv2.CC_STAT_AREA]
    
    if (area > 140) and (area < 400):
        componentMask = (label_ids == i).astype("uint8") * 255
        output = cv2.bitwise_or(output, componentMask)
cv2.imshow("Image", img)
cv2.imshow("Filtered Components", output)
cv2.waitKey(0)

Выход:

это выходная маска и исходное изображение

это выходная маска и исходное изображение

Примечание. Запустите программу на нескольких больших и маленьких изображениях, чтобы увидеть, что на выходе много «шума». Поэтому мы применили «фильтр» в последнем прогоне, и окончательный результат, который мы получили, содержал только нужные нам текстовые символы.

Маркировка и анализ подключенных компонентов OpenCV

Вот еще одна реализация, в которой я продемонстрировал весь процесс для каждого компонента, чтобы вам было легче его визуализировать:

Python3

import cv2
import numpy as np
# Loading the image
img = cv2.imread('Images/img5.png')
# preprocess the image
gray_img = cv2.cvtColor(img ,
                        cv2.COLOR_BGR2GRAY)
# Applying 7x7 Gaussian Blur
blurred = cv2.GaussianBlur(gray_img, (7, 7), 0)
# Applying threshold
threshold = cv2.threshold(blurred, 0, 255,
    cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
# Apply the Component analysis function
analysis = cv2.connectedComponentsWithStats(threshold,
                                            4,
                                            cv2.CV_32S)
(totalLabels, label_ids, values, centroid) = analysis
# Initialize a new image to
# store all the output components
output = np.zeros(gray_img.shape, dtype="uint8")
# Loop through each component
for i in range(1, totalLabels):
  
      # Area of the component
    area = values[i, cv2.CC_STAT_AREA]
    
    if (area > 140) and (area < 400):
        # Create a new image for bounding boxes
        new_img=img.copy()
        
        # Now extract the coordinate points
        x1 = values[i, cv2.CC_STAT_LEFT]
        y1 = values[i, cv2.CC_STAT_TOP]
        w = values[i, cv2.CC_STAT_WIDTH]
        h = values[i, cv2.CC_STAT_HEIGHT]
        
        # Coordinate of the bounding box
        pt1 = (x1, y1)
        pt2 = (x1+ w, y1+ h)
        (X, Y) = centroid[i]
        
        # Bounding boxes for each component
        cv2.rectangle(new_img,pt1,pt2,
                      (0, 255, 0), 3)
        cv2.circle(new_img, (int(X),
                             int(Y)),
                   4, (0, 0, 255), -1)
        # Create a new array to show individual component
        component = np.zeros(gray_img.shape, dtype="uint8")
        componentMask = (label_ids == i).astype("uint8") * 255
        # Apply the mask using the bitwise operator
        component = cv2.bitwise_or(component,componentMask)
        output = cv2.bitwise_or(output, componentMask)
        
        # Show the final images
        cv2.imshow("Image", new_img)
        cv2.imshow("Individual Component", component)
        cv2.imshow("Filtered Components", output)
        cv2.waitKey(0)

Выход:

одна реализация, в которой я продемонстрировал весь процесс

Читайте также:  Использование Tight_Layout Matplotlib в Python
Оцените статью
bestprogrammer.ru
Добавить комментарий