findContours()函数未返回适当数量的轮廓

时间:2020-05-18 01:23:45

标签: python-3.x opencv image-processing computer-vision opencv-contour

我正在使用Python 3.8.2openCV 4.3.0。 我应该得到3时得到1个轮廓的答案。我尝试使用RETR_TREE而不是RETR_EXTERNAL。在这种情况下,它会给我8的轮廓。

import cv2 as cv
def getCounters(img):
    contours,hierarchy=cv.findContours(img,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
    print("Number of Contours found = " + str(len(contours)))

这是输入图像:

https://i.stack.imgur.com/Pr9hp.png

这是输入的Canny图片:

https://i.stack.imgur.com/FhIyr.png

请提出所需的更改。

3 个答案:

答案 0 :(得分:0)

这是在Python / OpenCV中执行此操作的一种方法。您的问题是由于边缘的黑色轮廓,您正在从白色背景获取外部轮廓。一种方法是使用层次结构来获取第二级轮廓。我在这里使用的花药仅仅是为了消除黑色边框。

  • 阅读输入内容
  • 删除黑色边框,将其变为白色
  • 转换为灰色
  • 反转灰色
  • 阈值使对象在黑色背景上为白色
  • 获取轮廓并在输入以及黑色背景上绘制
  • 保存结果

输入:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('shapes.png')
hh, ww = img.shape[:2]

# remove black border and add white border back
img2 = img[2:hh-2, 2:ww-2]
img2 = cv2.copyMakeBorder(img2, 2, 2, 2, 2, cv2.BORDER_CONSTANT, value=(255,255,255))

# convert to grayscale
gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)

# invert
gray = 255 - gray

# threshold
thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)[1]

# get contours and draw on input and on black background
result1 = img.copy()
result2 = np.zeros_like(img)
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
for cntr in contours:
    cv2.drawContours(result1, [cntr], 0, (0,0,255), 1)
    cv2.drawContours(result2, [cntr], 0, (255,255,255), 1)

# save results
cv2.imwrite('shapes_modified.png',img2)
cv2.imwrite('shapes_thresh.png',thresh)
cv2.imwrite('shapes_result1.png',result1)
cv2.imwrite('shapes_result2.png',result2)

# show results  
cv2.imshow("img2", img2)
cv2.imshow("thresh", thresh)
cv2.imshow("result1", result1)
cv2.imshow("result2", result2)
cv2.waitKey(0)
cv2.destroyAllWindows()


黑色边框输入变成白色:

enter image description here

阈值图像:

enter image description here

输入轮廓:

enter image description here

在黑色背景上的轮廓:

enter image description here

答案 1 :(得分:0)

@ fmw42的答案是正确的。以下是替代方法,请仔细阅读cv2.RETR_CCOMP对findContours的操作。

import numpy as np
import cv2

gray = cv2.imread('shapes.png', cv2.IMREAD_GRAYSCALE)
imgw, imgh = gray.shape

th = cv2.adaptiveThreshold(gray,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV,3,1)

_, ctrs, hierarchy = cv2.findContours(np.copy(th), cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
out_test = np.zeros(th.shape[:2], dtype="uint8")

for i in range(len(ctrs)):
    if(hierarchy[0][i][3] != -1): # Discard contours that are holes
        continue
    x, y, w, h = cv2.boundingRect(ctrs[i])

    if w * h < 0.9 * (imgw * imgh): # Eliminates white square surrounding the whole image
        cv2.drawContours(out_test, [ctrs[i]], -1, 255, -1)

答案 2 :(得分:0)

最快的方法是:在您的代码中,使用RETR_TREE查找轮廓。如您所说,这将总共提供8个轮廓。现在,我们必须消除所有外部轮廓,即所需的轮廓是形状的内部边缘处的轮廓。如您所见,内边缘的这些轮廓将没有子轮廓。因此,请使用此观察结果。

Refer this for info about parent-child relation in contours

执行此操作的一个班轮代码是-

contours = np.asarray([contours[i] for i in range(len(contours)) if hierarchy[0][i][2] == -1])
相关问题