如何检测指定轮廓内的物体?解决OpenCV pointPolygonTest报错问题
球场轮廓内的球检测问题解决
报错原因分析
你遇到的pointPolygonTest报错,是因为参数完全传反且类型错误:
- 该函数的正确调用格式是
cv.pointPolygonTest(多边形轮廓, 单个点坐标, 是否返回距离) - 你代码里把轮廓的局部点
cnt[0]和所有轮廓的列表contours传反了,而且contours是多个轮廓的集合,不是单个点,导致函数收到长度为60的序列(你的轮廓数量),而它只需要(x,y)这样的二维点。
正确实现思路
- 先提取球场的轮廓:通常球场是画面中面积最大的轮廓,所以从轮廓列表里筛选面积最大的那个作为球场轮廓
- 提取球的轮廓:通过最小外接圆判断(你原代码的逻辑可以保留)
- 对每个球的中心坐标,用
pointPolygonTest判断是否在球场轮廓内,仅绘制符合条件的球
修正后的代码
import cv2 as cv def get_court_contour(inputCitra): # 获取所有轮廓 contours, _ = cv.findContours(inputCitra, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) # 筛选面积最大的轮廓作为球场轮廓 if not contours: return None return max(contours, key=cv.contourArea) def contourBola(inputCitra, outputCitra, court_contour): if court_contour is None: return # 获取球的轮廓 contours, _ = cv.findContours(inputCitra, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) for cnt in contours: # 计算球的最小外接圆和中心 (x,y), radius = cv.minEnclosingCircle(cnt) center = (int(x), int(y)) # 判断中心是否在球场轮廓内(返回值>0表示在内部) if cv.pointPolygonTest(court_contour, center, False) > 0: # 仅绘制球场内的球 cv.circle(outputCitra, center, int(radius), (255,0,0), 3) # 使用示例(假设你已经有预处理后的球场二值图和球的二值图) # court_binary = ... # 预处理后的球场二值图像 # ball_binary = ... # 预处理后的球二值图像 # output = cv.cvtColor(court_binary, cv.COLOR_GRAY2BGR) # 初始化输出图像 # court_contour = get_court_contour(court_binary) # contourBola(ball_binary, output, court_contour) # cv.imshow("Result", output) # cv.waitKey(0)
额外说明
- 注意预处理步骤:你需要分别对球场和球做二值化处理,确保
inputCitra传入的是对应的二值图像(黑白,目标区域为白色) - 如果球场轮廓不是面积最大的,可以根据轮廓的近似多边形(比如
cv.approxPolyDP)来筛选,比如球场通常是矩形或近似矩形的轮廓
内容的提问来源于stack exchange,提问作者Mr. x
相关产品推荐
相关产品推荐

