Как сгруппировать близлежащие контуры в OpenCV Python? - Обнаружение Зебры - PullRequest
2 голосов
/ 17 февраля 2020

Я хочу обнаружить линии пересечения зебры. Я попытался выяснить координаты линии пересечения зебры на изображении, используя контур , но это дает вывод для отдельных белых прямоугольников (только белые линии в пересечении зебры). Но мне нужны координаты всего скрещивания зебры.

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

Исходное изображение

Полученное изображение на выходе

Ожидаемый результат

import cv2
import numpy as np
image = cv2.imread('d.jpg',-1)
paper = cv2.resize(image,(500,500))
ret, thresh_gray = cv2.threshold(cv2.cvtColor(paper, cv2.COLOR_BGR2GRAY),
                        200, 255, cv2.THRESH_BINARY)
image, contours, hier = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
for c in contours:
    rect = cv2.minAreaRect(c)
    box = cv2.boxPoints(rect)
    # convert all coordinates floating point values to int
    box = np.int0(box)
    cv2.drawContours(paper, [box], 0, (0, 255, 0),1)
cv2.imshow('paper', paper)
cv2.imwrite('paper.jpg',paper)
cv2.waitKey(0)

1 Ответ

2 голосов
/ 18 февраля 2020

Вы можете закрыть морфологическую операцию для закрытия пробелов.

Я могу предложить следующие этапы:

  • Найти контуры в thresh_gray.
  • Сотрите контуры с очень маленькой областью (шум).
  • Стирание контуров с низким соотношением сторон (предположим, что линия зебры должна быть длинной и узкой.
  • Используйте morphologyEx для выполнения морфологической операции закрытия - закрытие объединяет близкие компоненты.
  • Поиск контуров на изображении после стирания и закрытия.
    На последнем этапе игнорируйте маленькие контуры.

Вот пример рабочего кода:

import cv2
import numpy as np

image = cv2.imread('d.jpg', -1)
paper = cv2.resize(image, (500,500))
ret, thresh_gray = cv2.threshold(cv2.cvtColor(paper, cv2.COLOR_BGR2GRAY), 200, 255, cv2.THRESH_BINARY)
image, contours, hier = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# Erase small contours, and contours which small aspect ratio (close to a square)
for c in contours:
    area = cv2.contourArea(c)

    # Fill very small contours with zero (erase small contours).
    if area < 10:
        cv2.fillPoly(thresh_gray, pts=[c], color=0)
        continue

    # https://stackoverflow.com/questions/52247821/find-width-and-height-of-rotatedrect
    rect = cv2.minAreaRect(c)
    (x, y), (w, h), angle = rect
    aspect_ratio = max(w, h) / min(w, h)

    # Assume zebra line must be long and narrow (long part must be at lease 1.5 times the narrow part).
    if (aspect_ratio < 1.5):
        cv2.fillPoly(thresh_gray, pts=[c], color=0)
        continue


# Use "close" morphological operation to close the gaps between contours
# https://stackoverflow.com/questions/18339988/implementing-imcloseim-se-in-opencv
thresh_gray = cv2.morphologyEx(thresh_gray, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (51,51)));

# Find contours in thresh_gray after closing the gaps
image, contours, hier = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

for c in contours:
    area = cv2.contourArea(c)

    # Small contours are ignored.
    if area < 500:
        cv2.fillPoly(thresh_gray, pts=[c], color=0)
        continue

    rect = cv2.minAreaRect(c)
    box = cv2.boxPoints(rect)
    # convert all coordinates floating point values to int
    box = np.int0(box)
    cv2.drawContours(paper, [box], 0, (0, 255, 0),1)

cv2.imshow('paper', paper)
cv2.imwrite('paper.jpg', paper)
cv2.waitKey(0)
cv2.destroyAllWindows()

thresh_gray перед удалением малых и прямоугольных контуров:
enter image description here

thresh_gray после удаления маленьких и прямоугольных контуров:
enter image description here

thresh_gray после закрытия:
enter image description here

Окончательный результат:
enter image description here


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

...