如果你使用cv2.RETR_EXTERNAL
代替cv2.RETR_TREE
in findContours
,该函数将仅返回外部轮廓。因此它不会返回位于另一个轮廓内部的轮廓。
要合并轮廓,一种非常简单的方法是在黑色蒙版上绘制白色填充的轮廓,然后在该蒙版上执行新的 findContours。它将返回组合轮廓的轮廓。
要排除小轮廓:您可以使用以下命令获取轮廓的大小contourArea
并将其与您设置的值进行比较。在下面的代码中,我添加了一个跟踪栏,以便您可以动态设置最小值。
Result:
注意小矩形的大小合适。它不重叠,但高于 minContourSize。如果您想排除该轮廓,可以增加 minContourSize,但您也可以开始排除您确实想要的轮廓。解决方案是对轮廓大小设置第二次检查,这次是在掩模上。由于蒙版具有组合轮廓,因此您可以将阈值设置得更高。
如果您想将该轮廓合并到较大的轮廓:您可以通过绘制填充轮廓以及具有几个像素宽轮廓的非填充矩形来使轮廓连接到蒙版上。尽管更合适的方法是调查形态转变,您可以将其应用到面膜上。
Code:
import cv2
import numpy as np
# Read image
src = cv2.imread("3E3MT.jpg", cv2.IMREAD_GRAYSCALE)
# Set threshold and maxValue
thresh = 150
maxValue = 200
# set an initial minimal contour size
minContourSize = 250
# create a window (needed for use with trackbar)
cv2.namedWindow("Contour")
def setMinSize(val):
# set the minimal contour size and find/draw contours
global minContourSize
minContourSize = val
doContours()
def doContours():
# create a copy of the image (needed for use with trackbar)
res = src.copy()
# find contours - external only
countours,hierarchy=cv2.findContours(dst,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
# create an empty mask
mask = np.zeros(src.shape[:2],dtype=np.uint8)
# draw filled boundingrects if the contour is large enough
for c in countours:
if cv2.contourArea(c) > minContourSize:
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(mask,(x,y),(x+w,y+h),(255),-1)
# find the contours on the mask (with solid drawn shapes) and draw outline on input image
countours,hierarchy=cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
for c in countours:
cv2.drawContours(res,[c],0,(255,255,255),2)
# show image
cv2.imshow("Contour",res)
# create a trackbar to set the minContourSize - initial is set at 250,
# maximum value is currently set at 1500, you can increase it if you like
cv2.createTrackbar("minContourSize", "Contour",250,1500,setMinSize)
# Basic threshold example
th, dst = cv2.threshold(src, thresh, maxValue, cv2.THRESH_BINARY)
# Find Contours
doContours()
# waitkey to prevent program for exiting by itself
cv2.waitKey(0)
cv2.destroyAllWindows()