基于图像边缘坐标点,求最小二乘平均圆后如何获取最大、最小外接圆直径?
解决方法
一、以最小二乘拟合圆心为中心,覆盖所有点的圆(直径计算)
如果要求圆心固定在你已拟合得到的(xc, yc),步骤如下:
- 计算所有边缘点到该圆心的距离:
import numpy as np # 计算每个点到拟合圆心的欧氏距离 distances = np.sqrt((coordinates[:, 0] - xc)**2 + (coordinates[:, 1] - yc)**2)
- 能覆盖所有点的最小圆(圆心固定)的半径等于这些距离的最大值,对应的直径为:
# 覆盖所有点的最小圆半径(圆心固定) max_radius_fixed = np.max(distances) # 直径 max_diameter_fixed = 2 * max_radius_fixed
注:若提及“圆心固定的最大圆”,该表述无实际意义——圆可无限放大;若你需要的是所有点到拟合圆心的最小距离对应的圆,直径为2*np.min(distances),但这个圆无法覆盖所有点。
二、全局最小外接圆(覆盖所有点的最小圆,圆心任意)
如果要找不限制圆心位置、能包含所有点的半径最小的圆(即最小外接圆),可通过以下代码实现:
- 先安装依赖(未安装时执行):
pip install scipy
- 实现代码:
from scipy.spatial import ConvexHull from scipy.spatial.distance import cdist def min_enclosing_circle(points): # 最小外接圆的顶点必在凸包上,先提取凸包点缩小计算范围 hull = ConvexHull(points) hull_points = points[hull.vertices] min_radius = float('inf') best_center = None # 情况1:所有点重合 if len(hull_points) == 1: return hull_points[0], 0.0 # 情况2:圆由两个点确定(直径为两点间距) for i in range(len(hull_points)): for j in range(i+1, len(hull_points)): p1, p2 = hull_points[i], hull_points[j] center = (p1 + p2) / 2 radius = np.linalg.norm(p1 - p2) / 2 # 验证所有凸包点是否在圆内(加微小误差 tolerance) if np.all(cdist(hull_points, [center]) <= radius + 1e-8): if radius < min_radius: min_radius = radius best_center = center # 情况3:圆由三个点确定(外接圆) for i in range(len(hull_points)): for j in range(i+1, len(hull_points)): for k in range(j+1, len(hull_points)): p1, p2, p3 = hull_points[i], hull_points[j], hull_points[k] # 构建线性方程组求解外接圆圆心 A = np.array([ [2*(p2[0]-p1[0]), 2*(p2[1]-p1[1])], [2*(p3[0]-p1[0]), 2*(p3[1]-p1[1])] ]) b = np.array([ p2[0]**2 + p2[1]**2 - p1[0]**2 - p1[1]**2, p3[0]**2 + p3[1]**2 - p1[0]**2 - p1[1]**2 ]) try: center = np.linalg.solve(A, b) except np.linalg.LinAlgError: continue # 三点共线,跳过该组合 radius = np.linalg.norm(p1 - center) # 验证所有凸包点是否在圆内 if np.all(cdist(hull_points, [center]) <= radius + 1e-8): if radius < min_radius: min_radius = radius best_center = center return best_center, min_radius # 计算最小外接圆的圆心和半径 min_center, min_radius = min_enclosing_circle(coordinates) # 最小外接圆直径 min_diameter = 2 * min_radius
关于“最大圆”的补充说明
如果需求是“能覆盖所有点的最大圆”,该表述无实际意义(圆可无限放大)。若你实际需要的是其他相关圆(比如包含所有点的最大内切圆),可补充具体需求后进一步调整实现。
内容的提问来源于stack exchange,提问作者mehmet_kacmaz_03
相关产品推荐
相关产品推荐

