OpenCV椭圆检测过滤非目标形状的判定条件设置
OpenCV目标椭圆检测过滤方案
当前以全图几何中心为基准的区域过滤逻辑失效,可通过分层筛选直接定位对应3个亮区的目标椭圆,无需提前硬编码目标中心坐标。
预过滤规则(先剔除绝大多数无效检测结果)
在做椭圆拟合和匹配前,先对轮廓做第一层筛选,砍掉噪点、边框等无效轮廓:
- 轮廓点数校验:拟合椭圆要求轮廓点数大于5,不满足的轮廓直接跳过
- 面积过滤:用
cv2.contourArea(cnt)计算轮廓面积,设置上下阈值,剔除面积过小的噪点、面积过大的图像边缘轮廓 - 椭圆形态过滤:目标椭圆接近正圆,计算椭圆长短轴比值(短轴长度/长轴长度),剔除比值低于0.7的扁长形无效椭圆;同时过滤长/短轴尺寸超出合理范围的椭圆
亮区匹配规则(精准定位3个目标椭圆)
目标椭圆对应图中亮度最高的3个区域,直接通过椭圆覆盖区域的平均亮度做最终筛选:
- 对所有通过预过滤的椭圆,创建同尺寸全黑掩码,用
cv2.ellipse()将当前椭圆以白色填充到掩码上 - 调用
cv2.mean(灰度图, mask=掩码)计算当前椭圆覆盖区域的平均灰度值 - 将所有椭圆按平均灰度值从高到低排序,取前3个即为目标椭圆
动态中心计算(替代硬编码的全图中心)
如果后续需要用中心区域做二次校验,不需要使用全图几何中心(w/2, h/2),直接计算3个目标椭圆中心坐标的平均值,即可得到3个亮区组成的目标组的实际中心,适配性远高于硬编码坐标。
修正后代码
注:修复了原代码中未定义变量t2的bug,阈值参数可根据实际图像尺寸微调
import cv2 import numpy as np input_image = cv2.imread('test_image_2.bmp') gray = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY) thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 101, 0) h, w = gray.shape contours, hierarchy = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_TC89_KCOS) valid_ellipses = [] for cnt in contours: if len(cnt) <= 5: continue # 面积过滤 area = cv2.contourArea(cnt) if area < 100 or area > w*h*0.2: continue ellipse = cv2.fitEllipse(cnt) (x, y), (major_axis, minor_axis), angle = ellipse # 规避除零错误 if minor_axis == 0 or major_axis == 0: continue # 长短轴比过滤 axis_ratio = min(major_axis, minor_axis) / max(major_axis, minor_axis) if axis_ratio < 0.7: continue # 尺寸过滤 if major_axis < 20 or major_axis > 200: continue # 计算椭圆区域平均亮度 mask = np.zeros(gray.shape, dtype=np.uint8) cv2.ellipse(mask, ellipse, 255, -1) mean_bright = cv2.mean(gray, mask=mask)[0] valid_ellipses.append( (-mean_bright, ellipse) ) # 按亮度降序取前3个目标 valid_ellipses.sort() target_ellipses = [item[1] for item in valid_ellipses[:3]] # 绘制检测结果 for e in target_ellipses: cv2.ellipse(input_image, e, (0, 0, 255), 2) # 可选:绘制3个目标的组中心 if len(target_ellipses) == 3: center_x = int(sum(e[0][0] for e in target_ellipses) / 3) center_y = int(sum(e[0][1] for e in target_ellipses) / 3) cv2.circle(input_image, (center_x, center_y), 10, (255, 255, 0), -1) cv2.imshow('target_ellipses', input_image) cv2.waitKey()
相关参考素材
- 输入图像:

- 图像中心标记:

- 全量椭圆检测结果:

内容的提问来源于stack exchange,提问作者Vladislav
相关产品推荐
相关产品推荐

