基于三维坐标计算旋转生成的封闭三维物体体积
可以用
scipy.spatial.ConvexHull计算这个近似半球的体积! 作为Python新手,你已经完成了从2D轮廓到3D近似半球的核心步骤,用ConvexHull来计算体积完全可行——因为半球是凸几何体,凸包会完美贴合你的点云,直接给出准确的近似体积。
关键步骤说明
- 整理点云格式:
ConvexHull需要输入一个形状为(N, 3)的数组,所以你需要把qx、qy、qz三个一维数组合并成一个三维点数组。 - 计算凸包并获取体积:调用
ConvexHull后,直接访问其volume属性就能得到体积值。
修改后的完整代码(加入体积计算部分)
import cv2 import numpy as np import math import matplotlib.pyplot as plt from scipy.spatial import ConvexHull # 假设你的origin已经提前定义(比如轮廓的中心) # origin = (x_center, y_center) # 你的原有代码:提取轮廓坐标 c, contours, _ = cv2.findContours(WB, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_NONE) contours = sorted(contours, key=cv2.contourArea, reverse=True) contour = contours[1] # 取目标轮廓 xpointsList = [xpoints[0][0] for xpoints in contour] ypointsList = [ypoints[0][1] for ypoints in contour] zpointsList = np.zeros(len(xpointsList)) # 生成旋转角度 angles = np.arange(0, 180, 5, dtype=int) # 初始化坐标数组 qx = np.zeros(len(xpointsList)*len(angles)) qy = np.zeros(len(ypointsList)*len(angles)) qz = np.zeros(len(zpointsList)*len(angles)) ax = plt.axes(projection='3d') d = 0 for b in range(len(angles)): angle = angles[b] for i in range(len(ypointsList)): qx[i+d] = xpointsList[i] - origin[0] qz[i+d] = origin[0] + math.cos(math.radians(angle)) * zpointsList[i] - math.sin(math.radians(angle)) * (ypointsList[i] - origin[1]) qy[i+d] = origin[1] + math.sin(math.radians(angle)) * zpointsList[i] + math.cos(math.radians(angle)) * (ypointsList[i] - origin[1]) d += len(xpointsList) b += 1 ax.plot3D(qy, qz, qx, color='blue', linewidth=0.1) plt.show() # ------------------- 体积计算部分 ------------------- # 合并成(N, 3)的点云数组 points = np.column_stack((qx, qy, qz)) # 计算凸包 hull = ConvexHull(points) # 输出体积 print(f"近似半球的体积为: {hull.volume:.2f}")
注意事项
- 旋转中心的正确性:确保
origin是你想要的旋转中心(比如半圆的圆心),否则旋转后的形状会偏移,体积计算也会出错。 - 点云密度:你用了5度的旋转间隔,这个密度足够得到不错的近似值;如果需要更精确的体积,可以缩小角度间隔(比如2度),但计算时间会略有增加。
- 凸包的适用性:因为半球是凸几何体,所以
ConvexHull完全适用;如果你的形状是凹的,凸包体积会比真实体积大,这时候就需要其他方法了,但你的场景没问题。
内容的提问来源于stack exchange,提问作者Colin Monaghan
相关产品推荐
相关产品推荐

