如何用OpenCV提取图像最内层轮廓并计算其中心?
提取最内层轮廓并计算中心
原代码问题分析
你的代码通过cv2.RETR_TREE获取了所有轮廓,但未对轮廓层级做筛选。要提取最内层轮廓,核心是利用OpenCV返回的hierarchy层级信息判断轮廓的嵌套关系。
关键原理
cv2.RETR_TREE返回的hierarchy数组中,每个轮廓对应的条目格式为[next, prev, first_child, parent]:
first_child:当前轮廓的第一个子轮廓索引,无后代则为-1parent:当前轮廓的父轮廓索引,无父轮廓则为-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() # 释放窗口资源
改动说明
- 保留
cv2.RETR_TREE:只有该模式能获取完整的轮廓嵌套层级,RETR_EXTERNAL仅能提取最外层,无法区分内层结构 - 层级筛选逻辑:通过
has_child和has_parent的组合判断,精准定位最内层轮廓 - 优化异常处理:单独判断
M["m00"] == 0的情况,避免潜在的除零错误 - 新增资源释放:添加
cv2.destroyAllWindows(),程序结束后及时释放窗口内存
内容的提问来源于stack exchange,提问作者Abhinav V Jithin
相关产品推荐
相关产品推荐

