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

基于3D数据集拟合椭圆曲面并计算面积的Python实现方案

3D类椭圆点集的椭圆拟合与面积计算方案

方法概述

由于你的点集近似分布在一个平面上(类椭圆火焰边缘),最优方案是:

  1. 求解点集的最佳拟合平面
  2. 将3D点投影到该平面得到2D坐标
  3. 对2D点拟合椭圆并计算面积

这种方法相比三角拟合,能生成光滑的椭圆形状,避免面积高估和杂乱曲面问题。

实现代码

import numpy as np
from skimage.measure import EllipseModel
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 加载给定数据
data = np.array([[
    0.14893939, 0.14893939, 0.14621212, 0.14621212, 0.14651515, 0.14651515, 0.14984848, 0.14984848,
    0.15015152, 0.15015152, 0.15045455, 0.15045455, 0.15075758, 0.15075758, 0.14439394, 0.14439394,
    0.1519697, 0.1519697, 0.14378788, 0.14378788, 0.14348485, 0.14348485, 0.15318182, 0.15318182,
    0.15318182, 0.15318182, 0.15318182, 0.15318182, 0.15318182, 0.15318182, 0.15318182, 0.15318182,
    0.15318182, 0.15318182, 0.15318182, 0.15318182, 0.15287879, 0.15287879, 0.15287879, 0.15287879,
    0.14378788, 0.14378788, 0.14378788, 0.14378788, 0.14409091, 0.14409091, 0.14409091, 0.14409091,
    0.1519697, 0.1519697, 0.15166667, 0.15166667, 0.15106061, 0.15106061, 0.15136364, 0.15136364,
    0.14469697, 0.14469697, 0.15015152, 0.15015152, 0.15045455, 0.15045455, 0.14530303, 0.14530303,
    0.14530303, 0.14560606, 0.14560606, 0.14560606, 0.1480303, 0.1480303], [
    0.14560606, 0.14560606, 0.14590909, 0.14590909, 0.14590909, 0.14590909, 0.14590909, 0.14590909,
    0.14590909, 0.14590909, 0.14590909, 0.14590909, 0.14590909, 0.14590909, 0.14651515, 0.14651515,
    0.14681818, 0.14681818, 0.1480303, 0.1480303, 0.14924242, 0.14924242, 0.14924242, 0.14924242,
    0.15045455, 0.15045455, 0.15075758, 0.15075758, 0.15106061, 0.15106061, 0.15136364, 0.15136364,
    0.15166667, 0.15166667, 0.1519697, 0.1519697, 0.15287879, 0.15287879, 0.15318182, 0.15318182,
    0.15409091, 0.15409091, 0.15439394, 0.15439394, 0.15469697, 0.15469697, 0.155, 0.155, 0.155,
    0.155, 0.15530303, 0.15530303, 0.15560606, 0.15560606, 0.15560606, 0.15560606, 0.15621212,
    0.15621212, 0.15621212, 0.15621212, 0.15621212, 0.15621212, 0.15651515, 0.15651515, 0.15651515,
    0.15651515, 0.15651515, 0.15651515, 0.15651515, 0.15651515], [
    0.01907071, 0.01921212, 0.01935354, 0.01949495, 0.01935354, 0.01949495, 0.01907071, 0.01921212,
    0.01907071, 0.01921212, 0.01907071, 0.01921212, 0.01907071, 0.01921212, 0.02062626, 0.02076768,
    0.01878788, 0.01892929, 0.02034343, 0.02048485, 0.02006061, 0.02020202, 0.01793939, 0.01808081,
    0.01765657, 0.01779798, 0.01765657, 0.01779798, 0.01765657, 0.01779798, 0.01765657, 0.01779798,
    0.01765657, 0.01779798, 0.01765657, 0.01779798, 0.01765657, 0.01779798, 0.01765657, 0.01779798,
    0.01935354, 0.01949495, 0.01935354, 0.01949495, 0.01935354, 0.01949495, 0.01935354, 0.01949495,
    0.01793939, 0.01808081, 0.01793939, 0.01808081, 0.01793939, 0.01808081, 0.01793939, 0.01808081,
    0.02006061, 0.02020202, 0.01822222, 0.01836364, 0.01822222, 0.01836364, 0.01963636, 0.01977778,
    0.01991919, 0.01963636, 0.01977778, 0.01991919, 0.01822222, 0.01836364]]).T

# 步骤1:计算最佳拟合平面
# 中心化数据
mean = np.mean(data, axis=0)
centered_data = data - mean

# SVD分解求平面法向量
u, s, vh = np.linalg.svd(centered_data)
normal = vh[-1]  # 最小奇异值对应的向量是平面法向量

# 平面方程:normal · (x - mean) = 0 → ax + by + cz + d = 0
d = -np.dot(normal, mean)

# 步骤2:将3D点投影到平面,转换为2D坐标
# 构建平面内的正交坐标系
# 取第一个主方向作为u轴
u_axis = vh[0]
# v轴为法向量与u轴的叉乘,确保正交
v_axis = np.cross(normal, u_axis)
# 归一化轴向量
u_axis /= np.linalg.norm(u_axis)
v_axis /= np.linalg.norm(v_axis)

# 投影到2D坐标
projected_2d = np.array([
    [np.dot(p - mean, u_axis), np.dot(p - mean, v_axis)]
    for p in data
])

# 步骤3:拟合2D椭圆
ellipse_model = EllipseModel()
ellipse_model.fit(projected_2d)

# 获取椭圆参数:(中心x, 中心y, 半长轴a, 半短轴b, 旋转角theta)
x0, y0, a, b, theta = ellipse_model.params

# 步骤4:计算椭圆面积
ellipse_area = np.pi * a * b
print(f"拟合椭圆的面积:{ellipse_area:.6f}")

# 可选:可视化结果
fig = plt.figure(figsize=(12, 6))

# 3D视图:原始点与拟合平面
ax1 = fig.add_subplot(121, projection='3d')
ax1.scatter(data[:,0], data[:,1], data[:,2], c='r', label='原始点')

# 绘制拟合平面
xx, yy = np.meshgrid(np.linspace(data[:,0].min(), data[:,0].max(), 10),
                     np.linspace(data[:,1].min(), data[:,1].max(), 10))
zz = (-normal[0]*xx - normal[1]*yy - d) / normal[2]
ax1.plot_surface(xx, yy, zz, alpha=0.3, label='拟合平面')
ax1.set_xlabel('X')
ax1.set_ylabel('Y')
ax1.set_zlabel('Z')
ax1.legend()
ax1.set_title('3D点集与拟合平面')

# 2D视图:投影点与拟合椭圆
ax2 = fig.add_subplot(122)
ax2.scatter(projected_2d[:,0], projected_2d[:,1], c='r', label='投影点')

# 生成椭圆上的点用于绘制
theta_vals = np.linspace(0, 2*np.pi, 100)
ellipse_x = x0 + a*np.cos(theta_vals)*np.cos(theta) - b*np.sin(theta_vals)*np.sin(theta)
ellipse_y = y0 + a*np.cos(theta_vals)*np.sin(theta) + b*np.sin(theta_vals)*np.cos(theta)
ax2.plot(ellipse_x, ellipse_y, 'b-', label='拟合椭圆')
ax2.set_xlabel('U轴')
ax2.set_ylabel('V轴')
ax2.legend()
ax2.set_title('2D投影点与拟合椭圆')
ax2.axis('equal')

plt.tight_layout()
plt.show()

关键说明

  1. 平面拟合:通过SVD分解找到点集的最小方差方向(法向量),确保平面最佳贴合所有点。
  2. 2D投影:在平面内构建正交坐标系,将3D点无损转换为2D坐标,保留原始形状关系。
  3. 椭圆拟合:使用skimage.measure.EllipseModel确保拟合结果为椭圆(而非其他二次曲线),参数直接给出半轴长度。
  4. 面积计算:椭圆面积公式为π*a*b,其中a和b是拟合得到的半长轴和半短轴长度,结果准确反映类椭圆火焰边缘的实际面积。

内容的提问来源于stack exchange,提问作者balcieb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 03:27:04