python - 当矩形与另一个矩形重叠时,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)
我得到以下输出:
我的目标是删除所有落在较大矩形内的矩形并连接较大的矩形,例如:
我怎么做 ?
解决方案
如果您使用cv2.RETR_EXTERNAL
而不是cv2.RETR_TREE
in 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()
推荐阅读
- python-3.x - 为什么诅咒中的窗口不更新?
- mysql - 如何获取不同的记录,但仅基于 MySQL 中的前 2 位数字
- python - 导入文件时出错:OSError: [WinError 126] The specified module could not be found
- javascript - 当事件侦听器中的计数器达到 0 时播放声音
- list - 使用 SwiftUI 和 macOS 创建带有标题的列表
- nlp - PyTorch - 稀疏张量没有步幅
- authorization - Identity Server 4 令牌过期 API 与 ClientApp
- python - 为什么要删除您更改数字的行中的第 8 个位置?
- android - React Native 导航和状态管理
- android - OnePlus (Android 10) - 在 PIP 模式下主屏幕冻结