Opencv 学习笔记:提取轮廓中心点坐标(矩计算法)

在轮廓分析中,获取轮廓的中心点(质心)是目标定位、尺寸测量的核心步骤。本文通过 OpenCV 的图像矩(cv.moments())实现轮廓中心点的精准计算与可视化,新手可直接复用完整流程。

核心代码实现

python 复制代码
import cv2 as cv
import numpy as np

# 1. 读取图像并校验
src = cv.imread('./image/21.bmp')
if src is None:
    print('图像读取失败,请检查路径!')
    exit()

# 2. 预处理:高斯滤波去噪 + 二值化
dst = cv.GaussianBlur(src, (3, 3), 15)  # 高斯滤波去除噪点,避免伪轮廓干扰
grays = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)  # 转灰度图
# 二值化(分离前景轮廓与背景,阈值200可根据图像调整)
ret, binary = cv.threshold(grays, 200, 255, cv.THRESH_BINARY)

# 3. 查找轮廓(CCOMP模式:检索内外层轮廓,适配有孔洞的目标)
contours, hierarchy = cv.findContours(binary, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE)

# 4. 遍历轮廓,计算并绘制每个轮廓的中心点
for i, contour in enumerate(contours):
    # 绘制轮廓(蓝色,线宽5,便于直观查看轮廓范围)
    cv.drawContours(src, contours, i, (255, 0, 0), 5)
    
    # 计算轮廓的图像矩(核心:通过矩获取中心点)
    M = cv.moments(contour)  # 修正原代码:使用当前轮廓contour,而非固定contours[1]
    
    # 避免除零错误(过滤无效小轮廓,m00为零表示轮廓无有效像素)
    if M["m00"] != 0:
        # 计算中心点坐标(x = m10/m00,y = m01/m00)
        center_x = int(M["m10"] / M["m00"])
        center_y = int(M["m01"] / M["m00"])
        
        # 绘制中心点(绿色圆形,半径10,线宽2,醒目易见)
        cv.circle(src, (center_x, center_y), 10, (0, 255, 0), 2)
        
        # 打印中心点坐标,便于数据分析
        print(f"轮廓{i} 中心点坐标:x={center_x}, y={center_y}")
    else:
        print(f"轮廓{i} 为无效轮廓,跳过中心点计算")

# 5. 显示结果图像
cv.namedWindow('src', cv.WINDOW_NORMAL)
cv.resizeWindow('src', 600, 600)
cv.imshow('src', src)

cv.waitKeyEx(0)
cv.destroyAllWindows()

关键知识点解析

1. 核心流程拆解

步骤 核心 API 作用说明
图像矩计算 cv.moments(contour) 计算轮廓的几何矩,包含轮廓的位置、面积等信息
中心点求解 center_x = m10/m00center_y = m01/m00 m00是轮廓面积矩,m10/m01是一阶矩,通过比值求解中心点
中心点可视化 cv.circle() 用圆形标注中心点,直观验证计算结果
无效轮廓过滤 M["m00"] != 0 避免小噪点轮廓导致的除零报错,提升代码健壮性

2. 核心概念说明

  • 图像矩(Moments) :描述图像轮廓几何特征的数值集合,OpenCV 中cv.moments()返回的矩包含多个关键字段,核心用于中心点计算的仅有 3 个:
    • M["m00"]:零阶矩,对应轮廓的面积(非零表示轮廓有效);
    • M["m10"]:一阶矩,用于计算中心点 x 坐标;
    • M["m01"]:一阶矩,用于计算中心点 y 坐标。
  • 轮廓索引 :原代码固定使用contours[1],仅能计算第 2 个轮廓的中心点,改为contour遍历每个轮廓,适配多轮廓场景。

3. 避坑与优化技巧

  • 除零错误 :必须添加M["m00"] != 0的判断,否则小噪点轮廓会导致ZeroDivisionError
  • 阈值调整:二值化阈值 200 需根据图像亮度调整,暗轮廓可降低阈值(如 150),亮背景可提高阈值(如 220);
  • 多轮廓适配 :遍历enumerate(contours)而非固定索引,支持图像中多个目标轮廓的中心点批量计算;
  • 精度优化 :若需更高精度的中心点,可保留浮点数(去除int()转换),适用于精密测量场景。

总结

  1. 轮廓中心点计算的核心是图像矩(cv.moments() ,通过m10/m00m01/m00求解 x、y 坐标;
  2. 必须添加M["m00"] != 0的判断,避免除零错误,提升代码健壮性;
  3. 遍历所有轮廓而非固定索引,才能实现多目标轮廓的中心点批量提取与可视化。
相关推荐
楼田莉子2 小时前
Linux学习:进程信号
linux·运维·服务器·c++·学习
●VON2 小时前
React Native for OpenHarmony:井字棋游戏的开发与跨平台适配实践
学习·react native·react.js·游戏·性能优化·交互
盐焗西兰花2 小时前
鸿蒙学习实战之路-Reader Kit获取目录列表最佳实践
学习·华为·harmonyos
AI视觉网奇2 小时前
ue 安装报错MD-DL ue 安装笔记
笔记·学习·ue5
KeeBoom2 小时前
嵌入式 Linux 应用开发完全手册——阅读笔记14
linux·笔记
pop_xiaoli2 小时前
effective-Objective-C 第一章阅读笔记
开发语言·笔记·ios·objective-c·cocoa·xcode
崇山峻岭之间2 小时前
Matlab学习记录42
学习
暴躁小师兄数据学院2 小时前
【WEB3.0零基础转行笔记】基础知识篇-第二讲:以太坊基础
笔记·web3·区块链
星幻元宇VR2 小时前
消防数字展厅智能升级|AR消防巡检员体验系统
学习·安全·ar·虚拟现实