You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity调用EmguCV转换Texture2D至Image时崩溃问题求助

Unity崩溃排查:Texture2D转EmguCV Image时无报错直接崩溃

我之前也碰到过类似的非托管内存冲突导致的Unity崩溃,完全懂你这种看不到报错只能瞎猜的痛苦!结合你的代码和描述,这个问题大概率是EmguCV非托管内存和Unity托管内存交互时的访问违规,而且这种错误会绕过.NET的异常捕获,直接让进程挂掉。

先把你的问题场景和代码再明确下:
调用SetTextureDefault函数将Unity的Texture2D转为EmguCV的Image<Bgra, byte>时,Unity编辑器和独立包都会直接弹出崩溃窗口,没有任何报错日志;移除这个函数后程序运行正常。使用的是个人版Unity + 桌面版EmguCV,相关代码如下:

void SetTextureDefault() { 
    try { 
        Texture2D currentTexture = new Texture2D(CameraTexture.width, CameraTexture.height); 
        currentTexture.SetPixels(CameraTexture.GetPixels()); 
        currentTexture.Apply(); 

        // Assuming leftBackground and rightBackground of Image<Bgra, byte> exist 
        if (leftBackground == null || rightBackground == null) { 
            using (var ms = new MemoryStream(currentTexture.EncodeToPNG())) { 
                leftBackground = new Image<Bgra, byte>(new Bitmap(ms)); 
            } 
        } else { 
            rightBackground.Bytes = leftBackground.Bytes = currentTexture.EncodeToPNG(); 
        } 
    } catch (Exception err) { 
        Debug.Log(err.StackTrace); 
    } 
}

问题根源拆解

你的代码里有几个明显的高危操作,直接触发了内存访问违规:

  1. 直接赋值Bytes属性:EmguCV的Image.Bytes背后是指向非托管内存的指针,你直接把Unity生成的托管byte数组赋值给它,会导致非托管内存和托管内存的生命周期脱节——当.NET GC回收这个byte数组时,EmguCV还在尝试访问这块已经被释放的内存,直接触发崩溃。
  2. Bitmap资源未正确释放:通过new Bitmap(ms)创建Bitmap再转EmguCVImage时,Bitmap的非托管内存没有被正确释放,积累下来会导致内存冲突。
  3. Texture2D未销毁:Unity的Texture2D是引擎管理的资源,直接创建后不销毁,会导致内存泄漏,间接引发崩溃。

修复后的完整代码

针对这些问题,我调整了代码,确保内存管理正确:

void SetTextureDefault() { 
    try { 
        // 使用using自动销毁Texture2D,避免Unity内存泄漏
        using (Texture2D currentTexture = new Texture2D(CameraTexture.width, CameraTexture.height, TextureFormat.RGBA32, false)) {
            currentTexture.SetPixels(CameraTexture.GetPixels()); 
            currentTexture.Apply(); 

            byte[] pngBytes = currentTexture.EncodeToPNG();

            if (leftBackground == null || rightBackground == null) {
                // 使用嵌套using确保Bitmap和MemoryStream都被正确释放
                using (var ms = new MemoryStream(pngBytes))
                using (var bmp = new Bitmap(ms)) {
                    leftBackground = Image<Bgra, byte>.FromBitmap(bmp);
                    // 初始化rightBackground为独立的克隆对象,避免共享内存
                    rightBackground = leftBackground.Clone();
                }
            } else {
                // 不要直接赋值Bytes,用FromArray/FromBitmap创建新的Image,让EmguCV管理内存
                using (var ms = new MemoryStream(pngBytes))
                using (var bmp = new Bitmap(ms)) {
                    // 先释放旧的Image资源,避免内存泄漏
                    leftBackground.Dispose();
                    rightBackground.Dispose();

                    leftBackground = Image<Bgra, byte>.FromBitmap(bmp);
                    rightBackground = leftBackground.Clone();
                }
            }
        }
    } catch (Exception err) { 
        // 用Debug.LogError更容易在控制台看到错误
        Debug.LogError($"SetTextureDefault出错: {err.Message}\n{err.StackTrace}");
    } 
}

额外调试建议

  1. 启用Unity Profiler:打开Window > Analysis > Profiler,切换到Memory面板,监测Texture和托管内存的变化,看是否有异常增长。
  2. 关闭EmguCV的OpenCL加速:在初始化EmguCV时添加CvInvoke.UseOpenCL = false;,有时候OpenCL的内存管理会和Unity冲突。
  3. 检查EmguCV日志:可以在代码开头添加CvInvoke.RedirectError(CvErrorHandler);自定义错误回调,捕获底层OpenCV的错误信息。

内容的提问来源于stack exchange,提问作者Frengky Sinaga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:46:36