Unity Barracuda加载ONNX模型时PRelu断言错误解决咨询
参考相关仓库实现,在Unity中使用Barracuda进行ONNX模型推理时,调用推理环节出现如下断言错误:
AssertionException: Assertion failure. Value was False Expected: True UnityEngine.Assertions.Assert.Fail (System.String message, System.String userMessage) (at <cb81df0c49c643b1a04d9fc6ccca2433>:0) UnityEngine.Assertions.Assert.IsTrue (System.Boolean condition, System.String message) (at <cb81df0c49c643b1a04d9fc6ccca2433>:0) UnityEngine.Assertions.Assert.IsTrue (System.Boolean condition) (at <cb81df0c49c643b1a04d9fc6ccca2433>:0) Unity.Barracuda.PrecompiledComputeOps.PRelu (Unity.Barracuda.Tensor X, Unity.Barracuda.Tensor S) (at ./Library/PackageCache/com.unity.barracuda@3.0.0/Barracuda/Runtime/Core/Backends/BarracudaPrecompiledCompute.cs:1501) Unity.Barracuda.StatsOps.Unity.Barracuda.IOps.PRelu (Unity.Barracuda.Tensor X, Unity.Barracuda.Tensor S) (at ./Library/PackageCache/com.unity.barracuda@3.0.0/Barracuda/Runtime/Core/Backends/StatsOps.cs:543) Unity.Barracuda.GenericWorker+<StartManualSchedule>d__36.MoveNext () (at ./Library/PackageCache/com.unity.barracuda@3.0.0/Barracuda/Runtime/Core/Backends/GenericWorker.cs:1143) ...
堆栈追踪指向Barracuda的PRelu方法中的断言语句:Assert.IsTrue((X.flatWidth == S.flatWidth) || (S.flatWidth == 1));。
当前图像预处理代码如下:
// 目标:按比例缩放图像,使最大维度为192,targetX和targetY为对应宽高 private Texture2D preprocess(Texture2D texture2D, int targetX, int targetY) { RenderTexture rt = new RenderTexture(targetX, targetY, 24, RenderTextureFormat.ARGB32); RenderTexture.active = rt; Graphics.Blit(texture2D, rt); Texture2D resizedTex = new Texture2D(targetX, targetY, TextureFormat.RGB24, false); resizedTex.ReadPixels(new Rect(0, 0, targetX, targetY), 0, 0); resizedTex.Apply(); // 填充图像为正方形 int offsetX = (192 - resizedTex.width) / 2; int offsetY = (192 - resizedTex.height) / 2; Texture2D paddedTex = new Texture2D(maxSize, maxSize, TextureFormat.RGB24, false); Color[] texPixels = resizedTex.GetPixels(); paddedTex.SetPixels(offsetX, offsetY, resizedTex.width, resizedTex.height, texPixels); paddedTex.Apply(); RenderTexture.active = null; return paddedTex; }
通过Tensor inputTensor = new Tensor(texture, channels: 3);将预处理后的Texture2D转换为张量,模型输入维度应为192×192、3通道。已知Barracuda会自动将ONNX的通道优先布局转换为通道最后布局,但不确定如何应用该信息调整输入张量,使用的Barracuda版本为3.0.0。
1. 确认预处理后的图像尺寸正确
检查预处理代码中maxSize变量是否被正确设置为192。如果maxSize未赋值为192,生成的paddedTex尺寸会不符合模型输入要求,进而导致后续张量维度错误。修改代码:
// 直接指定尺寸为192,或确保maxSize变量已赋值为192 Texture2D paddedTex = new Texture2D(192, 192, TextureFormat.RGB24, false);
2. 验证输入张量的维度
创建输入张量后,打印并确认其形状是否为[1, 192, 192, 3](NHWC布局:Batch=1,高度192,宽度192,3通道):
Tensor inputTensor = new Tensor(texture, channels: 3); Debug.Log($"Input tensor shape: {inputTensor.shape}");
如果形状不符合,说明预处理或张量转换环节存在问题,需进一步排查。
3. 修复PReLU参数维度不匹配问题
断言错误表明PReLU层的输入张量X和参数张量S的维度不满足要求(X.flatWidth == S.flatWidth 或 S.flatWidth == 1),这通常是ONNX模型转换到Barracuda格式时,通道布局转换不彻底导致的:
- ONNX模型中PReLU的参数
S通常是通道维度的(如3通道对应[3]的形状),但Barracuda的PRelu实现要求参数要么与输入张量尺寸完全一致,要么是标量。 - 解决方法:使用Barracuda的
ModelConverter重新转换ONNX模型,确保参数维度适配NHWC布局;或手动修改模型中的PReLU参数,将其形状调整为[1,1,1,3](对应NHWC布局下的通道维度参数),Barracuda会自动将参数广播到输入张量的所有元素。
4. 检查Barracuda版本兼容性
若问题持续,建议升级到Barracuda最新稳定版本,新版本可能修复了此类布局转换的兼容性问题。
内容的提问来源于stack exchange,提问作者Tammy Zeng

