How to extract only outer contours from an image (OpenCV)

给你一囗甜甜゛ 提交于 2021-02-09 09:21:36

问题


I am trying to extract digits from the below image using simple OpenCV contours approach, but I am getting overlapping bounding boxes over contours

cv2.RETR_EXTERNAL should return only outer contours in the hierarchy but it’s not working as can be seen from the below output

Code:

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')

Requirements:

opencv-python==3.4.5.20
matplotlib==3.1.2

回答1:


You need to blur then apply a threshold before finding contours. You need to do this because if you find contours directly on the grayscale image, there are tiny particles which are picked up as contours. Here's a simple process:

  • Load image, grayscale, Gaussian blur, Otsu's threshold
  • Find contours and sort using imutils.contours.sort_contours() with the left-to-right parameter
  • Obtain bounding box then extract ROI using Numpy slicing

Here's the detected bounding boxes highlighted in green

Extracted/saved ROIs

Code

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()


来源:https://stackoverflow.com/questions/59858377/how-to-extract-only-outer-contours-from-an-image-opencv

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!