Как извлечь только внешние контуры из изображения (OpenCV) - PullRequest
3 голосов
/ 22 января 2020

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

enter image description here

cv2.RETR_EXTERNAL должен возвращать только внешние контуры в иерархии, но он не работает, как видно из приведенного ниже вывода

enter image description here

Код :

from matplotlib import pyplot as plt
import cv2

img = cv2.imread('image.png', 0)

_, contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

imgRGB = cv2.cvtColor(img.copy(), cv2.COLOR_GRAY2RGB)

for c in contours:
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(imgRGB, (x, y), (x+w, y+h), (0,255,0), 2)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(imgRGB, cmap='gray')

Требования :

opencv-python==3.4.5.20
matplotlib==3.1.2

1 Ответ

3 голосов
/ 23 января 2020

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

  • Загрузка изображения, оттенки серого, размытие по Гауссу, порог Оцу
  • Поиск контуров и сортировка с использованием imutils.contours.sort_contours() с параметром left-to-right
  • Получите ограничивающий прямоугольник, затем извлеките ROI, используя Numpy срез

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

enter image description here

Извлеченные / сохраненные РИ

enter image description here

Код

import cv2
from imutils import contours

image = cv2.imread('1.png')
original = image.copy()
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
(cnts, _) = contours.sort_contours(cnts, method="left-to-right")
num = 0
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 1)
    ROI = original[y:y+h, x:x+w]
    cv2.imwrite('ROI_{}.png'.format(num), ROI)
    num += 1

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