OpenCV计算两个最大轮廓质心并绘制最小外接圆方法
OpenCV 轮廓质心计算与最小外接圆绘制实现
你已经筛选出两个面积最大的轮廓后,直接调用OpenCV内置接口即可完成需求,不需要额外实现复杂计算:
- 质心计算:通过
cv2.moments()获取轮廓矩,按矩的物理意义换算坐标 - 最小外接圆:通过
cv2.minEnclosingCircle()直接获取外接圆的圆心和半径
核心逻辑说明
质心计算
对单个轮廓调用cv2.moments(轮廓对象)会返回包含所有矩值的字典,其中:
m00对应轮廓的零阶矩,值等于轮廓面积m10/m00为质心横坐标m01/m00为质心纵坐标
计算前需要判断m00不为0,避免轮廓面积极端为0时触发除以0的运行错误。拿到坐标后用cv2.circle()绘制蓝色实心标记点即可。
最小外接圆绘制
对单个轮廓调用cv2.minEnclosingCircle(轮廓对象)会直接返回两个结果:外接圆圆心坐标(浮点型)、外接圆半径(浮点型),将值转为整数后,用cv2.circle()绘制红色空心圆即可。
修改后完整代码
已移除原代码里冗余的循环内函数定义、无用导入,加入了质心和外接圆绘制逻辑:
import cv2 import numpy as np # 初始化摄像头 cap = cv2.VideoCapture(0) if not cap.isOpened(): print("Error opening video stream or file") # 视频流循环 while cap.isOpened(): ret, frame = cap.read() if not ret: break # 转HSV空间做颜色阈值筛选 hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) red_lower = np.array([16, 132, 0]) red_upper = np.array([20, 236, 255]) mask = cv2.inRange(hsv, red_lower, red_upper) res = cv2.bitwise_and(frame, frame, mask=mask) thresh = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY) # 查找轮廓 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) print(f'Number of contours found = {len(contours)}') # 轮廓数足够时取面积最大的两个处理 if len(contours) >= 2: sorted_contours = sorted(contours, key=cv2.contourArea, reverse=True) top2_contours = [sorted_contours[0], sorted_contours[1]] for cnt in top2_contours: # 1. 计算轮廓矩绘制质心(蓝色点) M = cv2.moments(cnt) if M["m00"] != 0: cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) cv2.circle(frame, (cX, cY), 5, (255, 0, 0), -1) # 2. 计算并绘制最小外接圆(红色圈) (circle_x, circle_y), radius = cv2.minEnclosingCircle(cnt) circle_center = (int(circle_x), int(circle_y)) cv2.circle(frame, circle_center, int(radius), (0, 0, 255), 2) # 画面展示 cv2.imshow('Frame', frame) cv2.imshow('mask', mask) cv2.imshow('gray', thresh) # 按q退出 if cv2.waitKey(25) & 0xFF == ord('q'): break # 资源释放 cap.release() cv2.destroyAllWindows()
效果说明
运行后输出的Frame窗口中:
- 蓝色实心点为两个激光点的轮廓质心
- 红色空心圈为对应轮廓的最小外接圆
- 标记逻辑和参考示例完全匹配
内容的提问来源于stack exchange,提问作者Nathan Walsworth
相关产品推荐
相关产品推荐

