目录
[open3d 可以展示](#open3d 可以展示)
[vedo 可以录屏,不能保存](#vedo 可以录屏,不能保存)
open3d 可以展示
python
import pickle
import open3d as o3d
import numpy as np
import time
# 模拟关键点数据:50帧,每帧17个关节
n_frames = 50
n_joints = 17
# keypoints_3d = np.random.rand(n_frames, n_joints, 3)
pkl_path = r"D:\BaiduNetdiskDownload\pkl_mp4\pkl_mp4\0879d197-8b7a-43fc-97dd-f98bc5dc4214_1014.pkl"
video_masks = pickle.load(open(pkl_path, "rb"))
if isinstance(video_masks, tuple):
video_masks = video_masks[0]
object_ids = [1]
video_mask = []
points = []
keypoints_3d=[]
for frame_id in video_masks.keys():
mask_all = None
print('frame_id',frame_id)
object_dict = video_masks[frame_id]
for object_id, object_item in object_dict.items():
if hasattr(object_item, 'smpl') and object_item['smpl'] is not None:
joints3d = object_item['smpl']['joints3d']
keypoints_3d.append(joints3d[0])
keypoints_3d=np.array(keypoints_3d)
# 骨骼连接(按顺序连接,你可以自定义拓扑结构)
lines = [[i, i + 1] for i in range(n_joints - 1)]
# 初始点和线(从第0帧)
pts = keypoints_3d[0]
# 构建点云
points = o3d.geometry.PointCloud()
points.points = o3d.utility.Vector3dVector(pts)
# 构建骨架连线
lineset = o3d.geometry.LineSet()
lineset.points = o3d.utility.Vector3dVector(pts)
lineset.lines = o3d.utility.Vector2iVector(lines)
lineset.colors = o3d.utility.Vector3dVector([[0, 0, 1]] * len(lines)) # 蓝色
# 初始化可视化器
vis = o3d.visualization.Visualizer()
vis.create_window()
vis.add_geometry(points)
vis.add_geometry(lineset)
# 强制第一次渲染
vis.poll_events()
vis.update_renderer()
# 播放动画
for i in range(n_frames):
pts = keypoints_3d[i]
# 更新数据
points.points = o3d.utility.Vector3dVector(pts)
lineset.points = o3d.utility.Vector3dVector(pts)
# 通知渲染器数据已变
vis.update_geometry(points)
vis.update_geometry(lineset)
vis.poll_events()
vis.update_renderer()
time.sleep(0.1) # 控制播放速度
vis.destroy_window()
vedo 可以录屏,不能保存
python
from vedo import Plotter, Points, Line
import numpy as np
# 生成测试数据
n_frames = 100
n_joints = 17
keypoints = np.random.rand(n_frames, n_joints, 3)
# 初始化场景
plt = Plotter(axes=1, interactive=False, offscreen=True)
# 创建初始对象时使用有效数据
initial_points = np.zeros((n_joints, 3)) # 初始化为零点的占位数据
points_obj = Points(initial_points, r=12, c='red') # 重命名避免命名冲突
# 定义骨骼连接关系(COCO格式示例)
bones = [[0, 1], [1, 2], [2, 3], # 头部
[0, 4], [4, 5], [5, 6], # 左臂
[0, 7], [7, 8], [8, 9], # 右臂
[4, 10], [7, 11], # 躯干连接
[10, 11], [10, 12], [11, 13], # 臀部
[12, 14], [13, 15], [14, 16], [15, 16] # 腿部
]
lines_obj = Line(initial_points, bones, lw=3, c='blue')
# 添加对象到场景
plt += [points_obj, lines_obj]
# 生成动画帧
for i in range(n_frames):
current = keypoints[i]
# 正确更新关键点坐标(使用赋值操作)
points_obj.points = current # 直接赋值而非调用方法
# 更新骨骼连线
lines_obj.points = current # 同样使用赋值操作
# 渲染并保存帧
plt.show()
# plt.screenshot(f"frame_{i:03d}.png")
plt.close()
print("视频合成命令: ffmpeg -framerate 30 -i frame_%03d.png -c:v libx264 -pix_fmt yuv420p output.mp4")
mayavi
python
import numpy as np
from mayavi import mlab
# 生成示例数据
n_frames = 20
n_joints = 17
keypoints_3d = np.random.rand(n_frames, n_joints, 3)
# 创建动画
@mlab.animate(delay=100) # 每帧100ms
def animate():
for i in range(n_frames):
mlab.clf() # 清空当前帧
current_frame = keypoints_3d[i]
# 绘制关键点
pts = mlab.points3d(
current_frame[:, 0], current_frame[:, 1], current_frame[:, 2],
color=(1, 0, 0), scale_factor=0.05
)
# 绘制骨骼连线
for j in range(n_joints - 1):
mlab.plot3d(
[current_frame[j, 0], current_frame[j+1, 0]],
[current_frame[j, 1], current_frame[j+1, 1]],
[current_frame[j, 2], current_frame[j+1, 2]],
tube_radius=0.01, color=(0, 0, 1)
)
yield # 切换到下一帧
animate()
mlab.show()