Отдельные линии и круги на изображении с помощью OpenCV в python - PullRequest
4 голосов
/ 30 января 2020

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

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

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

Input Image

  • РЕДАКТИРОВАТЬ

Пример 2

Input

Input Image

Output :  Not desired output

Output image

В выходном изображении Я получил круги, которые не были разделены, и линии были объединены с кругами, и контур дал другую форму.

Пожалуйста, найдите способ разделить круги и линии. Пожалуйста, попробуйте ответить на него Python вместо C ++. Ответы на C ++ тоже разрешены.

Заранее спасибо!

1 Ответ

7 голосов
/ 30 января 2020

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

Заполненное пороговое изображение

enter image description here

Морфинг открыт

enter image description here

Результат

enter image description here

Код

import cv2

# Load iamge, grayscale, Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Fill contours
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(thresh, [c], -1, (255,255,255), -1)

# Morph open
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3)

# Draw circles
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    cv2.drawContours(image, [c], -1, (36,255,12), 3)

cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.imshow('image', image)
cv2.waitKey()

Для другого изображения используется иерархия контуров

enter image description here enter image description here enter image description here enter image description here

import cv2
import numpy as np

# Load image, grayscale, Otsu's threshold
image = cv2.imread('1.png')
mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Filter using contour hierarchy
cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
hierarchy = hierarchy[0]
for component in zip(cnts, hierarchy):
    currentContour = component[0]
    currentHierarchy = component[1]
    x,y,w,h = cv2.boundingRect(currentContour)
    # Only select inner contours
    if currentHierarchy[3] > 0:
        cv2.drawContours(mask, [currentContour], -1, (255,255,255), -1)

# Filter contours on mask using contour approximation
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
cnts = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.05 * peri, True)
    if len(approx) > 5:
        cv2.drawContours(mask, [c], -1, (0,0,0), -1)
    else:
        cv2.drawContours(image, [c], -1, (36,255,12), 2)

cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.imshow('mask', mask)
cv2.waitKey()

Примечание: Чтобы получить полное объяснение иерархии контуров, взгляните на этот пост

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