首页 > 解决方案 > 当矩形与另一个矩形重叠时,OpenCV 加入轮廓

问题描述

我有以下输入图像:

在此处输入图像描述

我的目标是在红色区域绘制轮廓。为此,我有以下代码:import cv2

# Read image
src = cv2.imread("images.jpg", cv2.IMREAD_GRAYSCALE)

# Set threshold and maxValue
thresh = 150 
maxValue = 200

# Basic threshold example
th, dst = cv2.threshold(src, thresh, maxValue, cv2.THRESH_BINARY);

# Find Contours
countours,hierarchy=cv2.findContours(dst,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

for c in countours:
    rect = cv2.boundingRect(c)
    if rect[2] < 10 or rect[3] < 10: continue
    x,y,w,h = rect
    cv2.rectangle(src,(x,y),(x+w,y+h),(255,255,255),2)

# Draw Contour
#cv2.drawContours(dst,countours,-1,(255,255,255),3)

cv2.imshow("Contour",src)
cv2.imwrite("contour.jpg",src)
cv2.waitKey(0)

我得到以下输出:

在此处输入图像描述

我的目标是删除所有落在较大矩形内的矩形并连接较大的矩形,例如:

在此处输入图像描述

我怎么做 ?

标签: pythonpython-3.xopencv

解决方案


如果您使用cv2.RETR_EXTERNAL而不是cv2.RETR_TREEin findContours,该函数将只返回外部轮廓。所以它不会返回另一个轮廓内的轮廓。

要合并轮廓,一种非常简单的方法是在黑色蒙版上绘制填充为白色的轮廓,然后在该蒙版上执行新的 findContours。它将返回组合轮廓的轮廓。

要排除小轮廓:您可以使用获取轮廓的大小contourArea并将其与您设置的值进行比较。在下面的代码中,我添加了一个跟踪栏,以便您可以动态设置最小值。

结果:
在此处输入图像描述

注意适当大小的小矩形。它不重叠,但高于 minContourSize。如果你想排除那个轮廓,你可以增加 minContourSize,但你也可以开始排除你想要的轮廓。一个解决方案是对轮廓大小设置第二次检查,这次是在蒙版上。由于蒙版具有组合轮廓,因此您可以将阈值设置得更高。

如果您希望将该轮廓合并到较大的轮廓:您可以通过绘制一个填充轮廓和一个轮廓几个像素宽的未填充矩形来使轮廓连接到蒙版上。虽然更合适的方法是研究Morphological Transformations,您可以将其应用于蒙版。

代码:

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

推荐阅读