Unity中如何将WebCamTexture帧输入PyTorch模型并执行对应动作?
将PyTorch模型集成到Unity实时摄像头工作流的方案
我之前也做过类似的PyTorch+Unity实时推理项目,你的需求核心是把预训练好的PyTorch模型嵌入Unity的实时摄像头流做推理,再根据输出驱动Unity内的交互动作——ML-Agents确实不适合这个场景,它的定位是在Unity环境中训练强化学习智能体,而不是集成已有的预训练模型做推理。下面给你分步骤拆解可行的实现方案:
一、预处理Unity摄像头帧,匹配PyTorch模型输入格式
首先你需要把WebCamTexture采集到的帧转换成PyTorch模型能接受的输入格式(通常是归一化的张量,通道顺序、尺寸和训练时一致)。在Unity的C#中可以这么处理:
- 从
WebCamTexture中读取像素数据:WebCamTexture webcamTexture = GetComponent<WebCamTexture>(); Color32[] pixels = webcamTexture.GetPixels32(); - 调整通道顺序(Unity默认是RGBA,而PyTorch训练时常用RGB/BGR,且通道在前),并缩放到模型要求的输入尺寸:
你可以用Texture2D来做尺寸缩放,然后把像素数组转换成浮点型,再按训练时的归一化规则处理(比如除以255,或者用均值、标准差归一化)。 - 把处理后的数组转换成模型能接受的张量格式(比如
float32类型,形状为[1, channels, height, width])。
二、Unity与PyTorch模型的交互方案
这里有两种主流的实现路径,你可以根据自己的模型复杂度和性能需求选择:
方案1:导出PyTorch模型为ONNX,用Unity ONNX Runtime推理
这是最常用也是性能最优的方案,步骤如下:
- 在PyTorch中导出模型为ONNX格式:
import torch # 加载你的预训练模型 model = YourTrainedModel() model.load_state_dict(torch.load("your_model_weights.pth")) model.eval() # 构造一个和模型输入尺寸一致的dummy tensor dummy_input = torch.randn(1, 3, 224, 224) # 示例:ResNet输入尺寸 # 导出ONNX模型 torch.onnx.export(model, dummy_input, "your_model.onnx", opset_version=12, input_names=["input"], output_names=["output"]) - 在Unity中导入ONNX Runtime包(可以通过Package Manager安装官方的
com.microsoft.onnxruntime.unity包)。 - 在C#中加载ONNX模型,将预处理后的摄像头帧张量输入模型,获取推理结果:
using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; // 初始化ONNX会话 InferenceSession session = new InferenceSession("Assets/Models/your_model.onnx"); // 把预处理后的像素数据转换成Tensor<float> Tensor<float> inputTensor = new DenseTensor<float>(processedData, new int[] {1, 3, 224, 224}); var inputs = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor("input", inputTensor) }; // 执行推理 using (var outputs = session.Run(inputs)) { var outputTensor = outputs.First().AsTensor<float>(); // 处理输出结果 }
方案2:用Python for Unity插件直接调用PyTorch
如果你的模型有ONNX导出不支持的操作(比如自定义层),可以用这个方案:
- 在Unity中安装Python for Unity插件,配置好和训练模型时一致的Python环境(确保安装了PyTorch、numpy等依赖)。
- 在Unity的C#中把摄像头帧数据传递给Python脚本,调用PyTorch模型推理,再把结果传回Unity:
- C#端负责采集并预处理帧,转成numpy数组格式传递给Python;
- Python端加载模型,执行推理,返回结果;
- C#端根据返回结果执行Unity动作。
注意这种方案的性能会比ONNX差一些,适合对实时性要求不高的场景。
三、根据模型输出执行Unity动作
拿到模型的推理输出后,就可以根据业务逻辑驱动Unity内的动作了:
- 如果是分类任务(比如输出是类别概率):取概率最高的类别,触发对应的动画或交互,比如:
float[] output = outputTensor.ToArray(); int predictedClass = Array.IndexOf(output, output.Max()); if(predictedClass == 0) { // 执行动作:比如播放跳跃动画 GetComponent<Animator>().SetTrigger("Jump"); } else if(predictedClass == 1) { // 执行另一个动作:比如移动物体 transform.Translate(Vector3.forward * Time.deltaTime); } - 如果是检测/分割任务(输出是坐标或掩码):可以用输出的坐标在Unity中绘制框,或者调整物体位置等。
内容的提问来源于stack exchange,提问作者AJ Z.




