You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用OpenCV提取图像最内层轮廓并计算其中心?

提取最内层轮廓并计算中心

原代码问题分析

你的代码通过cv2.RETR_TREE获取了所有轮廓,但未对轮廓层级做筛选。要提取最内层轮廓,核心是利用OpenCV返回的hierarchy层级信息判断轮廓的嵌套关系。

关键原理

cv2.RETR_TREE返回的hierarchy数组中,每个轮廓对应的条目格式为[next, prev, first_child, parent]:

  • first_child:当前轮廓的第一个子轮廓索引,无后代则为-1
  • parent:当前轮廓的父轮廓索引,无父轮廓则为-1

最内层轮廓的判定条件:没有子轮廓(first_child == -1)且存在父轮廓(parent != -1)——这类轮廓处于嵌套结构的最深处,没有自己的子轮廓,同时排除了最外层的大轮廓。

修改后的代码

import cv2

image = cv2.imread("pcb.jpg")
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, thresh_image = cv2.threshold(gray_image, 150, 255, cv2.THRESH_BINARY)
# 保留RETR_TREE以获取完整层级关系
contours, hierarchy = cv2.findContours(thresh_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 遍历轮廓,筛选最内层并计算中心
for i, contour in enumerate(contours):
    # 提取当前轮廓的层级信息
    h_info = hierarchy[0][i]
    has_child = h_info[2] != -1
    has_parent = h_info[3] != -1
    
    # 仅处理最内层轮廓:无后代且有父轮廓
    if not has_child and has_parent:
        M = cv2.moments(contour)
        if M["m00"] == 0:
            continue  # 避免除零错误
        cX = int(M["m10"] / M["m00"])
        cY = int(M["m01"] / M["m00"])
        cv2.circle(image, (cX, cY), 3, (0, 0, 0), -1)

cv2.imshow("Out", image)
cv2.waitKey()
cv2.destroyAllWindows()  # 释放窗口资源

改动说明

  1. 保留cv2.RETR_TREE:只有该模式能获取完整的轮廓嵌套层级,RETR_EXTERNAL仅能提取最外层,无法区分内层结构
  2. 层级筛选逻辑:通过has_child和has_parent的组合判断,精准定位最内层轮廓
  3. 优化异常处理:单独判断M["m00"] == 0的情况,避免潜在的除零错误
  4. 新增资源释放:添加cv2.destroyAllWindows(),程序结束后及时释放窗口内存

内容的提问来源于stack exchange,提问作者Abhinav V Jithin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 08:15:27