perf: optimize rectangle detection algorithm

- Check only first child contour instead of iterating all siblings
- Add area threshold check on inner contour
- Require inner contour to be rectangular with no deeper nesting
This commit is contained in:
dev01
2026-06-04 18:11:49 +08:00
parent bb92f905ce
commit 04f9529c99
@@ -160,25 +160,29 @@ class VisionNode(Node):
best_inner_idx = -1 best_inner_idx = -1
for i, cnt in enumerate(contours): for i, cnt in enumerate(contours):
area = cv2.contourArea(cnt) area = cv2.contourArea(cnt)
# 筛选:面积必须大于阈值
if area < THRESHOLD_AREA: if area < THRESHOLD_AREA:
continue continue
if not _is_rect(cnt): # 筛选:外轮廓必须是矩形
continue
# Require an inner rectangular child contour
child_idx = hierarchy[0][i][2]
has_inner_rect = False
while child_idx != -1:
if _is_rect(contours[child_idx]) and hierarchy[0][child_idx][2] == -1:
has_inner_rect = True
break
child_idx = hierarchy[0][child_idx][0] # next sibling
if not has_inner_rect:
continue
approx = cv2.approxPolyDP(cnt, 0.02 * cv2.arcLength(cnt, True), True) approx = cv2.approxPolyDP(cnt, 0.02 * cv2.arcLength(cnt, True), True)
if area > best_area: if not (len(approx) == 4 and cv2.isContourConvex(approx)):
best_area = area continue
best = approx.reshape(4, 2) # 筛选:必须有子轮廓
best_inner_idx = child_idx # 取第一个子轮廓的索引
child_idx = hierarchy[0][i][2]
# 这个子轮廓需要满足以下要求:
# 1.无平行轮廓(兄弟轮廓);
# 2.内轮廓不能有子轮廓;
# 3.内轮廓必须满足面积要求;
# 4.内轮廓必须是矩形;
if hierarchy[0][child_idx][0] == -1\
and hierarchy[0][child_idx][2] == -1\
and cv2.contourArea(contours[child_idx]) > THRESHOLD_AREA\
and _is_rect(contours[child_idx]):
if area > best_area:
best_area = area
best = approx.reshape(4, 2)
best_inner_idx = child_idx
# Draw all contours on closed for debugging # Draw all contours on closed for debugging
vis = cv2.cvtColor(closed, cv2.COLOR_GRAY2BGR) vis = cv2.cvtColor(closed, cv2.COLOR_GRAY2BGR)