OpenCV椭圆检测代码误检问题:实际6个却检测出24个
精准检测图像中的椭圆/圆形
原代码未对轮廓进行有效筛选,会将噪声、环形结构的内外轮廓全部拟合为椭圆,导致误检数量远超实际。以下是修正后的代码及核心优化点:
import cv2 import numpy as np def resize_image(img, scale_percent): width = int(img.shape[1] * scale_percent / 100) height = int(img.shape[0] * scale_percent / 100) dim = (width, height) resized = cv2.resize(img, dim, interpolation=cv2.INTER_AREA) return resized def detect_ellipses(img, contours, hierarchy): ellipses = [] # 自定义最小轮廓面积阈值,根据图像尺寸调整 min_area = 500 for i, contour in enumerate(contours): # 过滤面积过小的噪声轮廓 area = cv2.contourArea(contour) if area < min_area: continue # 只保留外层轮廓(环形结构的内层轮廓会有父轮廓,直接跳过) if hierarchy[i][3] != -1: continue # 确保轮廓点数满足椭圆拟合的最低要求(至少5个点) if len(contour) < 5: continue ellipse = cv2.fitEllipse(contour) # 过滤过于细长的非椭圆形状 (_, axes, _) = ellipse major_axis = max(axes) minor_axis = min(axes) if minor_axis / major_axis < 0.5: continue ellipses.append(ellipse) return ellipses # 加载图像 img = cv2.imread('canny.jpg') if img is None: print("Failed to load the image") exit() # 缩放图像 img = resize_image(img, 15) # 转灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 形态学闭运算去除噪声 kernel = np.ones((5,5),np.uint8) gray = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, kernel) # Canny边缘检测 edges = cv2.Canny(gray, 75, 200) # 提取轮廓及层级信息 contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 适配OpenCV不同版本的返回格式 if isinstance(hierarchy, tuple): hierarchy = hierarchy[0] # 检测椭圆 ellipses = detect_ellipses(img, contours, hierarchy) print(f"检测到椭圆数量:{len(ellipses)}") # 绘制椭圆 for ellipse in ellipses: cv2.ellipse(img, ellipse, (0, 255, 0), 2) # 展示结果 cv2.imshow('Ellipse Detection', img) cv2.waitKey(0) cv2.destroyAllWindows()
核心优化说明
- 小轮廓过滤:通过轮廓面积阈值剔除噪声点形成的无效小轮廓,避免误拟合。
- 层级筛选:利用轮廓层级区分内外层,只保留环形结构的外层轮廓,解决环形重复检测问题。
- 点数校验:确保轮廓点数满足
cv2.fitEllipse的最低要求,避免异常拟合。 - 形状校验:通过长短轴比例过滤细长形状,保证检测结果符合椭圆/圆形的形态特征。
内容的提问来源于stack exchange,提问作者Kirtan Shirodkar
相关产品推荐
相关产品推荐

