如何用OpenCV检测相互交叠的独立矩形并获取其坐标?
问题描述
需要检测屏幕上随机出现的多个矩形坐标,已知矩形宽度,但用轮廓法检测宽度存在误差。当前代码只能检测到整个矩形块,无法识别出独立的3个矩形,希望获取每个矩形的准确坐标。
现有实时检测代码:
yellow = (5,242,206) while True: isFrameValid, frame = capture.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) roi = gray [0:300, 0:1920] threshold, thresh_image = cv2.threshold(roi, 30, 255, cv2.THRESH_BINARY) # 查找轮廓 contours, _ =cv2.findContours(thresh_image,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) cv2.drawContours(frame, contours, -1,yellow,1)
问题复现代码:
import cv2 img= cv2.imread('./IwOXW.png') yellow = (5,242,206) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) roi = gray [0:300, 0:1920] threshold, thresh_image = cv2.threshold(roi, 30, 255, cv2.THRESH_BINARY) # 查找轮廓 contours, _ = cv2.findContours(thresh_image,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) cv2.drawContours(img, contours, -1,yellow,1) cv2.imshow('Frame',img) cv2.waitKey(0)
示例图片说明:画面中有3个垂直排列的深色矩形,位于浅色背景上,矩形之间存在细小的间隙。
解决方案
1. 替换固定阈值为自适应阈值
固定阈值容易受全局明暗影响,导致矩形间的背景被误判为前景,使轮廓粘连。改用自适应阈值能根据局部区域调整阈值,更精准分离前景和背景:
# 替换原固定阈值代码 thresh_image = cv2.adaptiveThreshold( roi, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2 )
使用THRESH_BINARY_INV是因为目标矩形为深色,反转后矩形变为白色前景,更便于轮廓检测。
2. 形态学开运算分离粘连轮廓
若阈值调整后仍有轮廓粘连,用开运算(先腐蚀再膨胀)断开连通区域,参数可根据矩形间隙大小调整:
import numpy as np # 定义结构元素,尺寸根据实际间隙调整 kernel = np.ones((3, 3), np.uint8) # 开运算分离粘连 thresh_image = cv2.morphologyEx(thresh_image, cv2.MORPH_OPEN, kernel)
3. 基于已知尺寸筛选目标轮廓
利用已知的矩形宽度(及高度)范围,过滤掉不符合的干扰轮廓,确保只保留目标矩形:
# 遍历所有轮廓,筛选符合尺寸的矩形 for cnt in contours: x, y, w, h = cv2.boundingRect(cnt) # 替换为你实际的宽度、高度范围 w_min, w_max = 45, 55 h_min, h_max = 190, 210 if w_min < w < w_max and h_min < h < h_max: # 绘制矩形并打印坐标 cv2.rectangle(img, (x, y), (x + w, y + h), yellow, 2) print(f"矩形坐标:左上角({x}, {y}),右下角({x+w}, {y+h})")
完整优化后的复现代码
import cv2 import numpy as np img = cv2.imread('./IwOXW.png') yellow = (5,242,206) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) roi = gray[0:300, 0:1920] # 自适应阈值处理 thresh_image = cv2.adaptiveThreshold( roi, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2 ) # 形态学开运算分离粘连轮廓 kernel = np.ones((3, 3), np.uint8) thresh_image = cv2.morphologyEx(thresh_image, cv2.MORPH_OPEN, kernel) # 查找轮廓 contours, _ = cv2.findContours(thresh_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 筛选并标记目标矩形 for cnt in contours: x, y, w, h = cv2.boundingRect(cnt) # 根据实际尺寸调整范围 if 45 < w < 55 and 190 < h < 210: cv2.rectangle(img, (x, y), (x + w, y + h), yellow, 2) print(f"矩形坐标:左上角({x}, {y}),右下角({x+w}, {y+h})") cv2.imshow('Frame', img) cv2.waitKey(0) cv2.destroyAllWindows()
内容的提问来源于stack exchange,提问作者Seriousl Lancerl
相关产品推荐
相关产品推荐

