我正在使用Python 3.8.2
和openCV 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)))
这是输入图像:
这是输入的Canny图片:
请提出所需的更改。
答案 0 :(得分:0)
这是在Python / OpenCV中执行此操作的一种方法。您的问题是由于边缘的黑色轮廓,您正在从白色背景获取外部轮廓。一种方法是使用层次结构来获取第二级轮廓。我在这里使用的花药仅仅是为了消除黑色边框。
输入:
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()
黑色边框输入变成白色:
阈值图像:
输入轮廓:
在黑色背景上的轮廓:
答案 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])