问题描述
我有以下输入图像:
我的目标是在红色区域绘制轮廓.为此,我有以下代码:导入cv2
My aim is to draw contours across the red area. To do this I have following code: 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)
我得到以下输出:
我的目标是删除所有落在较大矩形内的矩形并连接较大的矩形,例如:
My target is to remove all the rectangles which fall inside bigger rectangle and connect the bigger rectangles for example like this:
我该怎么做?
推荐答案
如果在 findContours
cv2.RETR_EXTERNAL 而不是 cv2.RETR_TREE
>,该函数只会返回外轮廓.所以它不会返回另一个轮廓内部的轮廓.
If you use cv2.RETR_EXTERNAL
instead of cv2.RETR_TREE
in findContours
, the function will only return outer contours. So it won't return contours that are inside of another contour.
要合并轮廓,一个非常简单的方法是在黑色蒙版上绘制填充为白色的轮廓,然后在该蒙版上执行新的 findContours.它将返回组合轮廓的轮廓.
To merge contours, a very easy approach is to draw the contours filled white on a black mask, and then perform a new findContours on that mask. It will return the outline of the combined contours.
排除小轮廓:您可以使用 contourArea
获取轮廓的大小,并将其与您设置的值进行比较.在下面的代码中,我添加了一个轨迹栏,以便您可以动态设置最小值.
To exclude small contours: you can get the size of the contour using contourArea
and compare it to a value you set. In the code below I added a trackbar so you can set the minimum value dynamically.
结果:
注意大小合适的小矩形.它不重叠,但高于 minContourSize.如果你想排除那个轮廓,你可以增加 minContourSize,但你也可以开始排除你想要的轮廓.一个解决方案是在轮廓尺寸上设置第二次检查,这次是在掩码上.由于蒙版具有组合轮廓,您可以将阈值设置得更高.
Note the small rectangle to the right size. It doesn't overlap, but is above the minContourSize. If you want to exclude that contour, you can increase minContourSize, but you might also start excluding contours you do want. A solution is to set a second check on the contourSize, this time on the mask. As the mask has combined contours, you can set the threshold much higher.
如果您更愿意将该轮廓合并到更大的轮廓:您可以通过绘制一个填充的轮廓和一个轮廓为几个像素宽的非填充矩形来使轮廓连接到蒙版上.虽然更合适的方法是查看 Morphological Transformations,您可以将其应用于蒙版.
If you would rather merge that contour to the larger one: you can can make the contours join on the mask by drawing a filled contour and also a non filled rectangle with an outline several pixels wide. Though a more appropriate approach would be to look into Morphological Transformations, which you can apply to the mask.
代码:
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()
这篇关于当矩形与另一个矩形重叠时,OpenCV 连接轮廓的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!