ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

MediaPipe+Unity轻量级动作捕捉实战:从摄像头到3D角色驱动

2026/9/15 17:45:46 拓冰建站 浏览量
MediaPipe+Unity轻量级动作捕捉实战:从摄像头到3D角色驱动 这几年一直在折腾虚拟形象和动作捕捉这摊事试过光学动捕、惯性动捕最后发现日常做原型和轻量级项目最顺手的一套反而是“普通摄像头 MediaPipe Unity”的组合。这个方案没有专业动捕设备的成本压力不需要穿动捕服一台带摄像头的笔记本就能把真人动作映射到3D角色上。这次把这套流程里踩过的坑、绕过的弯、优化过的细节全部整理出来给准备入坑动作捕捉和Unity角色驱动的人一个可以直接落地的参考。1. 整体思路与方案选型为什么选MediaPipe而不是惯性/光学动捕1.1 项目需求拆解先说说这个项目到底要解决什么问题。需求听起来简单用摄像头捕捉人的动作把动作同步到Unity里的3D人物模型上让模型跟着真人动。但真做起来里面有几个核心问题需要回答。第一用什么方式捕捉动作市面上主流有光学动捕比如Vicon、OptiTrack、惯性动捕比如Xsens、诺亦腾、还有基于视觉的动捕OpenPose、MediaPipe、MoveNet。前两种精度高但成本也高光学动捕需要多台红外相机和反光标记点惯性动捕需要穿一身传感器都不是拿来快速做原型的首选。第二数据怎么处理摄像头捕捉到的是2D画面但MediaPipe Pose能直接输出33个关键点的3D坐标包括深度估计。这个输出能不能直接用需不需要转换是驱动Unity模型的关键。第三数据怎么送到Unity常见做法是走网络协议UDP在本地进程间通信Python负责捕捉Unity负责接收和驱动。这个链路要稳定、延迟要低还得处理坐标系不一致的问题。我对这个项目的定位是“轻量级实时动捕原型”目标是能在普通笔记本上跑通延迟控制在100ms以内效果足够用来做虚拟主播、数字人演示、动作风格迁移测试之类的事。MediaPipe正好满足这些要求单目摄像头就能跑CPU也能实时开源免费而且输出的是归一化坐标和三维世界坐标配合Unity做骨骼驱动非常顺手。1.2 方案对比为什么不用现成的动捕插件或硬件设备很多人会问Unity商店里也有不少动捕方案为什么还要自己造轮子我的看法是如果要快速验证效果可以先用现成方案但如果想把动作捕捉和角色驱动这条链路彻底吃透自己组合MediaPipe和Unity是性价比最高的一条路。方案成本精度上手难度适用场景光学动捕很高设备场地高高影视、游戏动画制作惯性动捕中高动捕服中高中现场表演、多人捕捉深度相机方案Azure Kinect中中高中交互装置、体感应用MediaPipe 普通摄像头几乎为零中可接受低原型验证、虚拟主播、轻量交互MediaPipe这条路最大的优势在于“门槛低、链路透明”。门槛低是指只要有一台带摄像头的电脑装好Python和Unity就能开始做链路透明是指整条pipeline都是自己写的从关键点坐标到骨骼旋转出了问题能一步步排查而不是拿着黑盒插件只能干瞪眼。当然它也有短板。单目视觉方案对遮挡很敏感侧身动作、手臂交叉时容易丢失关键点深度估计是相对值不是真实的厘米级距离对于手指级精细化捕捉Pose关键点做不了得配合Hand Landmarks单独做手势识别。这些短处后面会在“常见问题”部分展开讲。1.3 核心链路预览整个项目的数据流可以拆成四个环节摄像头采集视频帧MediaPipe Pose检测每一帧里的人体输出33个关键点的坐标Python端把人体的骨骼关键点整理成结构化数据比如JSON打包后通过UDP发送到UnityUnity使用C#接收数据把关键点坐标转换成骨骼旋转Unity把计算出的旋转应用到角色的骨架上驱动模型动作。这条链路里最关键的技术点有三个MediaPipe的pose landmark数据解读、关键点坐标到骨骼旋转的数学转换、Unity端的平滑与镜像处理。后面的章节会逐个展开。2. 技术原理从摄像头到骨骼旋转2.1 MediaPipe Pose到底输出了什么MediaPipe Pose是Google开源的一个单目姿态估计方案相比OpenPose它在移动端和CPU上有更好的实时性。它通过神经网络检测人体的33个关键点每个关键点包含三类信息x、y归一化后的图像坐标范围是0到1以图像左上角为原点z关键点相对于臀部中心大致是髋关节中点的深度值。这个值是估算的不是绝对深度但能用来计算关节在空间中的相对位置visibility可见度0到1之间表示该关键点被模型“看到”的置信度。除了pose_landmarksMediaPipe还提供world_landmarks。它同样是33个关键点的三维坐标但单位是米坐标原点在人体的臀部中心X轴朝人的左边Y轴朝上Z轴朝人背后。这个world_landmarks对Unity驱动特别重要因为Unity的三维世界也是以米为单位的直接用world_landmarks做比例换算比用归一化坐标省事很多。在代码层面获取这些数据只需要几行import cv2 import mediapipe as mp mp_pose mp.solutions.pose pose mp_pose.Pose( static_image_modeFalse, model_complexity1, min_detection_confidence0.5, min_tracking_confidence0.5 ) cap cv2.VideoCapture(0) while cap.isOpened(): success, frame cap.read() if not success: break frame_rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results pose.process(frame_rgb) if results.pose_landmarks: for idx, lm in enumerate(results.pose_landmarks.landmark): x, y, z lm.x, lm.y, lm.z注意这里传给pose.process()的是RGB格式不是BGR否则检测效果会受影响。后面做方向判断、关节夹角计算时也是基于这33个点。2.2 坐标系和骨骼旋转整个项目最关键的一座桥拿到MediaPipe的坐标后第一件事不是把它们一股脑塞给Unity而是先做坐标系的“翻译”。MediaPipe里的坐标是“右手系”X朝人的左边Y朝上Z朝背后正方向是背离摄像头/指向屏幕外。Unity是世界空间里的“左手系”X朝右Y朝上Z朝屏幕里摄像头方向。如果直接把两个坐标系统硬套角色大概率会左右反转、前后颠倒甚至整个拧成麻花。一个稳妥的转换做法是把Y轴保持不变X和Z取相反方向。对应到代码# 把mediapipe的world_landmark转成unity空间的方向 unity_x -world_x unity_y world_y unity_z -world_z这只是最基础的坐标映射。光有“点”的坐标还不够驱动骨骼需要的是“旋转”。人体骨骼可以看成一条条刚体链大臂是从肩膀到肘部的一段小臂是从肘部到手腕的一段大腿是从髋部到膝盖的段小腿是从膝盖到脚踝的段。每一段都有一个方向向量方向向量可以由两个关键点相减得到shoulder np.array([lx, ly, lz]) elbow np.array([lx, ly, lz]) upper_arm_dir elbow - shoulder # 大臂方向有了方向向量下一步是求四元数旋转。在Unity里有两种典型做法一是Quaternion.FromToRotation。它接收两个向量返回从第一个方向旋转到第二个方向的四元数。如果我们知道骨骼在玩偶或角色模型上的“初始方向”T-Pose下的大臂方向就能用FromToRotation算出目标旋转。二是Quaternion.LookRotation。它根据一个“朝向”和一个“上方向”构造旋转。适合躯干、头部这类需要同时约束朝向和轴向的部位。实际用的时候我会对每个骨骼段定义一个“父节点-子节点”对然后从MediaPipe的关键点数据里构造出目标方向向量。比如// 一个大臂目标的伪代码 Vector3 shoulder GetLandmarkPos(11); // 左肩 Vector3 elbow GetLandmarkPos(13); // 左肘 Vector3 targetDir elbow - shoulder;接下来要把这个方向向量和模型骨骼自带的初始方向做旋转匹配。这一步看似简单但坑不少最关键的问题是MediaPipe的world_landmarks是以人体臀部中心为原点的“世界方向”而Unity模型里每根骨骼的旋转是相对于父骨骼的。直接赋值会带来旋转层级错乱。2.3 为什么是33个点就够了很多人觉得动作捕捉至少得上百个标记点才够精确但MediaPipe只用33个点就能驱动一个完整的类人体角色。这背后的原因是人体关节本身就简化成了33个关键位置其中每个关节的旋转自由度是有限的Joint limits。所以只要关键点位置不出大偏差骨骼方向就能基本还原。33个点的分布大致是脸部区域10个鼻子、眼睛、耳朵等躯干和四肢23个。对动作捕捉来说真正决定姿势的是四肢关节左右肩膀、肘部、手腕、髋部、膝盖、脚踝。其他点大多是辅助判断朝向和稳定识别。这意味着在Unity中我们实际只需要关注大概10到12根骨骼左右大臂、左右小臂、左右大腿、左右小腿、头颈方向、躯干方向。这一简化大幅降低了代码复杂度和计算量。如果连手指都要驱动就得另接Hand Landmarks那就是另一个项目了。3. Python端MediaPipe动作捕捉实现3.1 环境准备Python版本与依赖安装我建议直接用Python 3.8到3.10之间的版本太新的Python版本有时会遇到MediaPipe没有预编译wheel包的问题。安装依赖pip install opencv-python mediapipe numpy做一个快速验证看MediaPipe能不能正常加载模型import mediapipe as mp print(mp.__version__)如果这一步报错大多数情况是Python版本不匹配或者网络问题。换版本后基本能解决。装好之后连接摄像头时注意笔记本内置摄像头一般是0外接摄像头可能是1或2。OpenCV打不开摄像头时可以检查cap.isOpened()返回值而不是盲目往下跑。3.2 动作捕捉脚本的核心逻辑从视频帧到关键点结构捕捉脚本的循环结构大概是这样的import cv2 import mediapipe as mp import json import numpy as np mp_pose mp.solutions.pose pose mp_pose.Pose( static_image_modeFalse, model_complexity1, smooth_landmarksTrue, enable_segmentationFalse, min_detection_confidence0.5, min_tracking_confidence0.5 ) cap cv2.VideoCapture(0) while True: ret, frame cap.read() if not ret: break # 水平翻转让画面变成“镜像”效果操作者看着更自然 frame cv2.flip(frame, 1) rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results pose.process(rgb) if results.pose_landmarks: landmarks results.pose_landmarks.landmark world_landmarks results.pose_world_landmarks.landmark frame_data { timestamp: time.time(), landmarks_2d: [ {x: lm.x, y: lm.y, z: lm.z, visibility: lm.visibility} for lm in landmarks ], landmarks_3d: [ {x: lm.x, y: lm.y, z: lm.z} for lm in world_landmarks ] } # 把frame_data发送出去后面补UDP发送 # 实时可视化 mp_drawing mp.solutions.drawing_utils mp_drawing.draw_landmarks( frame, results.pose_landmarks, mp_pose.POSE_CONNECTIONS ) cv2.imshow(MediaPipe Pose, frame)这里有两个细节值得注意。第一个是cv2.flip(frame, 1)水平翻转之后跟真人左右一致否则你做“抬左手”画面里检测到的是你视觉上的右手模型会跟着乱。第二个是model_complexity参数它影响模型精度和速度默认是1数值越大精度越高但越慢。如果机器性能一般可以降到0速度明显提升精度损失在可接受范围内。3.3 数据发送为什么选UDP而不是TCPPython端和Unity端的通信方案我一开始用的是TCP因为TCP有确认机制不会丢包。但实际跑起来发现延迟不稳定TCP的粘包和重传机制在实时动捕场景里反而碍事。动作捕捉的帧率在20到30帧左右就算偶尔丢一两帧角色只是轻微卡顿无伤大雅但延迟忽高忽低是绝对不能接受的。所以我后来换成了UDP走本机localhost延迟能稳定在几毫秒。发送端代码import socket import json UDP_IP 127.0.0.1 UDP_PORT 9000 sock socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 在每一帧拿到data之后 message json.dumps(frame_data).encode(utf-8) sock.sendto(message, (UDP_IP, UDP_PORT))这里有个大坑数据包大小。一帧33个关键点每个关键点带x/y/z和visibility数据量很小不到2KB。但如果你后面加了Hand Landmarks或Face Mesh数据量会涨到十几KBUDP单个数据报在IPv4下最大只有65507字节超出就得分包Unity接收端也要处理分片。直接用TCP反而省事。所以“用UDP还是TCP”不能一刀切要看实际数据量。做纯Pose捕捉UDP绝对够用。3.4 可视化调试别急着让角色动先看骨架准不准我吃过一个亏一开始没做可视化直接拿着坐标往Unity里灌结果角色肢体扭曲根本分不清是MediaPipe检测错了还是Unity骨骼驱动错了。后来花十分钟在Python端画出骨架问题立刻定位。MediaPipe自带draw_landmarks可以把骨架画在图像上这是第一层验证。第二层验证是在Unity里也用LineRenderer把骨骼画一遍这样能把“捕捉端”和“驱动端”彻底分开排查。只要Python端画出的骨架跟真人动作一致Unity端画出的骨架也一致就能确定驱动逻辑没问题剩下的只是模型骨骼绑定的艺术问题。4. Unity端人物模型驱动实现4.1 接收端与数据协议用C#解析JSONUnity端需要写一个接收脚本。最基础的做法是让MonoBehaviour里的Update()每帧检查UDP接收队列。不要让UDP接收阻塞主线程否则帧率会被拉低。我采用的是在Start()里开一个异步方法或者用async void把接收到的JSON字符串缓存到一个变量里然后主线程在Update()里消费最新的一帧数据舍弃积压的旧数据。这样做能保证角色永远使用最新动作不会越积越卡。数据解析方面JSON用JsonUtility就够了但需要注意JsonUtility不能直接序列化ListVector3所以要先定义对应的数据类[System.Serializable] public class LandmarkData { public float x; public float y; public float z; } [System.Serializable] public class PoseFrame { public double timestamp; public LandmarkData[] landmarks_3d; }收到字符串后反序列化成PoseFrame再转成内部用到的Vector3[]数组。注意Unity的Vector3的Y轴和Z轴需要做一次坐标变换这个在后面的坐标落地部分详细说。4.2 骨骼映射与旋转计算从目标方向到四元数到了这一节就是整个项目最难也最核心的部分把33个点变成模型骨骼的旋转。先说模型准备。我建议用Unity的Humanoid角色模型这样可以用Animator.GetBoneTransform(HumanBodyBones.RightUpperArm)拿到指定骨骼不用手动去层级里找名字。前提是模型必须正确配置了Humanoid Avatar。接着定义关键的骨骼段。每个骨骼段的“起点”和“终点”对应MediaPipe关键点的索引。下面是MediaPipe Pose的常用索引对照MediaPipe索引关节名称说明11Left Shoulder左肩13Left Elbow左肘15Left Wrist左手腕12Right Shoulder右肩14Right Elbow右肘16Right Wrist右手腕23Left Hip左髋25Left Knee左膝27Left Ankle左踝24Right Hip右髋26Right Knee右膝28Right Ankle右踝有了对应关系接下来计算旋转。理论上一根骨骼比如“右上臂”它的方向等于worldLandmark[14] - worldLandmark[12]。但Unity里的骨骼是世界旋转的想设置骨骼旋转不能直接拿这个方向量赋值要算出四元数。我用的方法是在模型处于T-Pose时记录每根骨骼的初始世界方向或者用模型的默认方向。运行时用Quaternion.FromToRotation在“初始方向”和“目标方向”之间求差值旋转然后把差值旋转应用给骨骼。// 假设boneInitialDir是模型T-Pose下该骨骼的世界方向 // targetDir是MediaPipe计算出的目标方向 Quaternion targetRotation Quaternion.FromToRotation(boneInitialDir, targetDir); // 根旋转修正 bone.rotation rootTransform.rotation * targetRotation;这里rootTransform是模型的根Transform通常是人物的骨盆或Hips用来把MediaPipe坐标系里的方向正确映射到Unity世界空间。如果模型初始方向不是标准T-Pose建议先调整好模型姿态否则旋转基准就是错的。大臂旋转搞定后小臂、大腿、小腿都是同一个套路不做赘述。但有一个重要顺序必须从父骨骼往子骨骼更新也就是先设置躯干/颈椎再设置大臂、大腿最后设置小臂、小腿。因为子骨骼的旋转是相对于父骨骼的父骨骼动了子骨骼的世界方向如果不重新计算会被覆盖。4.3 平滑、镜像与偏移处理让动作看起来自然实时动捕里最影响观感的是“抖动”。MediaPipe单帧检测会有噪声直接把原始四元数赋给骨骼角色会像帕金森一样抖。解决抖动有两个思路一是让MediaPipe的smooth_landmarks打开二是在Unity端做时间上的平滑插值。我习惯在Unity端做双保险// 使用Slerp做旋转平滑speed在10~20之间 transform.rotation Quaternion.Slerp( transform.rotation, targetRotation, Time.deltaTime * rotationSmoothSpeed );注意rotationSmoothSpeed要按骨骼不同调参。肘关节扭曲比肩关节小可以设快一点肩关节的抖动更明显就设慢一点。这个值不能全局通用必须逐骨骼调。然后是镜像问题。摄像头画面经过cv2.flip后MediaPipe拿到的关键点已经和真人视觉方向一致但到了Unity里还要做一次符号处理。如果在Unity里看到角色抬的是相反的手最直接的做法是在收到数据后对所有x取反landmark.x -landmark.x;如果你用的是world_landmarks也会遇到同样问题要做Z轴和X轴的手性转换。建议把所有坐标转换统一封装在一个函数里不要让脏数据到处传。最后是偏移处理。MediaPipeworld_landmarks的坐标原点是人体臀部中心而Unity模型根节点位置不一定对齐到原点。为了保证角色不“飞走”要把整个坐标系平移到模型Root的位置。一般做法是在设置骨骼旋转时直接修改animator.bodyPosition或把根骨骼的position设为当前臀部中心位置加一个固定偏移。这里提一个非常基础的注意点如果模型是Generic模式GetBoneTransform配合Humanoid骨骼枚举是不好用的建议统一用Humanoid模式除非你有特殊需求否则不要选Generic。4.4 一个可以直接抄的C#驱动脚本骨架给一个最简版本的C#脚本结构using System; using System.Net; using System.Net.Sockets; using System.Text; using UnityEngine; [System.Serializable] public class LandmarkData { public float x; public float y; public float z; } [System.Serializable] public class PoseFrame { public LandmarkData[] landmarks_3d; } public class MotionCaptureReceiver : MonoBehaviour { public int port 9000; public Animator animator; private UdpClient udpClient; private string latestData; private Vector3[] landmarkPositions new Vector3[33]; void Start() { udpClient new UdpClient(port); udpClient.BeginReceive(ReceiveCallback, null); } private void ReceiveCallback(IAsyncResult ar) { IPEndPoint remoteEndPoint new IPEndPoint(IPAddress.Any, 0); byte[] data udpClient.EndReceive(ar, ref remoteEndPoint); latestData Encoding.UTF8.GetString(data); udpClient.BeginReceive(ReceiveCallback, null); } void Update() { if (string.IsNullOrEmpty(latestData)) return; PoseFrame frame JsonUtility.FromJsonPoseFrame(latestData); if (frame ! null frame.landmarks_3d ! null) { for (int i 0; i frame.landmarks_3d.Length; i) { landmarkPositions[i] new Vector3( -frame.landmarks_3d[i].x, frame.landmarks_3d[i].y, -frame.landmarks_3d[i].z ); } // 把landmarkPositions转成骨骼旋转 ApplyPoseToBones(landmarkPositions); } } private void ApplyPoseToBones(Vector3[] positions) { // 核心旋转计算参考上面“骨骼映射与旋转计算”一节 } void OnDestroy() { udpClient?.Close(); } }这个脚本只负责接收和存储数据真正的旋转计算需要配合具体的模型骨骼定义来做。我建议把“坐标转换”“旋转计算”“平滑”拆成三个独立的类这样后续换模型、换捕捉源时改动最小。5. 常见问题与排查实录5.1 坐标乱飞模型突然转到奇怪的角度症状角色在某个角度下四肢拧成麻花或者大幅旋转。原因大多数情况是坐标系转反了或者用Quaternion.FromToRotation时初始方向不对。MediaPipe的world_landmarks是右手系Unity是左手系我只取反X和Z是不够的有些骨骼段比如肩到肘的方向还依赖模型本身的初始骨骼方向。如果你发现“躺下能对上站起来就乱”多半是初始方向向量没校准。排查顺序先在Python端固定一个T-Pose打印出world_landmarks里的肩、肘、腕坐标再到Unity里打印对应的骨骼世界方向手动比对数值确认转换公式没问题。5.2 角色抖动动作看起来像在“打冷颤”症状骨骼旋转一直在微小抖动。原因MediaPipe单帧检测有噪声加上手部快速移动时关键点置信度下降导致旋转目标值不断跳变。解决办法分三层一是调大min_detection_confidence和min_tracking_confidence过滤掉置信度过低的关键点二是打开smooth_landmarks三是在Unity端调整平滑参数。如果抖动仍然严重可以对3D坐标先做一阶低通滤波再拿去算旋转。值得提醒的是过度平滑会带来动作延迟角色看起来像在“太空步”。调参时要平衡我建议平滑速度常数在10到15之间延迟体感比较小。5.3 Unity收不到数据端口、防火墙和编码的坑症状Python端一直在sendto但Unity端UdpClient收不到任何数据。常见原因端口被占用或被防火墙拦截。本机回环127.0.0.1一般不触发防火墙但如果绑定的IP是局域网地址Win/Mac防火墙会拦。解决只监听127.0.0.1。Python端没有真正执行sendto只是打印了frame_data但没发送。JSON编码问题。JsonUtility.FromJson要求字段名完全匹配大小写都要对上landmarks_3d和LandmarkData[]如果不一致反序列化后数组长度会是0。排查方法先在Unity端写一个测试按钮手工发一段固定JSON看能不能正确解析再把Python端的发送频率降到每秒1帧确认网络链路通不通。5.4 MediaPipe安装与性能问题症状import mediapipe报错或者运行很卡。原因很可能是Python版本和MediaPipe的预编译包不匹配。MediaPipe在不同Python版本下支持的包不一样太新的Python版本往往没有对应wheel。建议使用Python 3.9或3.10如果还报错去PyPI或者官方GitHub看对应版本要求手动下载安装不要死磕pip install。性能方面如果CPU跑不太动优先级调整顺序是把model_complexity降到0、把输入图像缩小用cv2.resize把帧缩到480甚至360宽度、把检测帧率从30帧降到15帧跳帧。注意MediaPipe本身要求传入的图像RGB通道缩放时别把通道顺序改错。6. 进阶扩展方向从“能动”到“好用”这套方案稳定跑通之后能扩展的方向非常多。我列几个亲测有效的方向供你决定下一步怎么走。第一增加手势识别。MediaPipe不仅能做Pose还能做Hand Landmarks。把手势识别结果叠加到角色手上可以让角色做手指动作比如比个心、竖个拇指。但注意Pose和Hands是两个不同模型不能在同一帧里直接复用需要分别推理性能消耗会翻倍。第二结合面部驱动。MediaPipe Face Mesh能输出468个面部关键点可以驱动模型表情。比如提取眼睛睁开程度、嘴角上扬程度映射到Unity的BlendShape上让虚拟角色有表情变化。这样一套摄像头就能同时驱动身体和脸部做虚拟主播够用了。第三模型驱动从“旋转对齐”升级到“IK解算”。我现在做的旋转对齐方案直接把方向向量转成四元数对模型的骨骼长度比例没有要求比较简单。但如果模型比例和真人差异大可以改用Unity的IK系统先把骨盆、手、脚目标点计算出来再用IK解算驱动四肢。IK方案的优点是模型不容易穿模缺点是计算量更大对关节限制处理也更复杂。第四加一点数据后处理。MediaPipe的关键点数据可以做姿态滤波比如卡尔曼滤波或者基于历史帧的平滑能进一步减少抖动。这块做深了就是商业动捕方案的底子了。7. 写在最后一些个人体会做了这个项目之后最大的感受是动作捕捉没有想象中那么遥不可及。专业动捕设备贵但摄像头加开源的MediaPipe再加Unity的骨骼驱动能力一套亲手搭起来的轻量动捕系统足够支撑很多创意原型。如果让我给一个学习路径的建议先不要急着直接驱动一个完整的人形模型先用LineRenderer画骨架把基础验证做通再一步步加上旋转计算、平滑、镜像、模型绑定。每一步都单独验证出问题了也容易定位。这套方案虽然精度比不上专业设备但胜在链路透明、可控性强、成本为零作为原型验证和入门学习的切入点价值很高。后面再想往深了做无非就是换更好的摄像头、多加几个视角、上深度相机而已核心的数据链路和思维模型不会变。