2024.08.05
C++我写的不是很好,混合项目的基础代码是我刚开始写C++的时候的遗产,能用也就没有在意。
在C++里计算完成的图像指针,如果直接修改用C#这边传递过来的图像,不合适,如果只是单纯的clone,那么在用opencv跑完之后,指针会因为是局部变量的问题,在函数调用结束之后,生命周期结束,就销毁掉,C#这边拿到图像指针就会出现 AccessViolationException 。
当时经验不足,直接new 一块内存,然后在传出来,用完之后再加一个函数来delete掉这块内存。
在后面接触的项目,主从逻辑就变了,以C++为主体,C#这边不管这个值,只做接收和显示,处理逻辑也和这快不一样。
梳理了一下思路,其实只要把输出的图像指针从局部变量修改为全局即可,也就是一个函数导出,4k*5k的图像我大概会浪费40ms的样子。同时快速内存创建又删除,会产生大量的内存碎片。
在之后我将图像指针拿到,又转换成writebitmap,最后再赋值为image显示的过程,又要创建和销毁大量的writebitmap,频繁触发GC。
其实可以只写数据,而不频繁创建对象,这样会增加对CPU的负担。
一顿操作猛如虎,节约的时间不超过100ms。使用体验上就是一些本来需要频繁滑动计算的值,可以用一个相对可以拖动的视角来看结果。
聊胜于无。
不过因为降低了频繁创建内存,不用就mat不用就 release掉,波动性会小很多
太麻烦了,不如直接让用户关掉软件,重新打开。
目前来说,从 C++ 传入图像数据到 C# 显示通常有两种方案:
- *使用 Windows Forms 和 PictureBox*:
最简单的方法是不断创建新的 Bitmap 对象,然后将其赋值给 PictureBox 控件。这种方法实现简单,但性能较差,因为频繁创建和销毁 Bitmap 对象会导致大量的内存分配和释放。
优化的方案是使用 BitmapData 和 LockBits 方法来直接操作 Bitmap 的内存,从而只写入数据而不重新创建 Bitmap 对象。这种方式类似于 WriteableBitmap,可以显著提高性能。 Windows Forms 主要依赖 CPU 进行图像渲染,缺乏 GPU 加速,在处理复杂图像或高分辨率图像时性能较低。
- *使用 WPF 和 Image*:
WPF 提供了 WriteableBitmap 类,可以直接操作图像的内存缓冲区。通过锁定和解锁 WriteableBitmap,可以高效地更新图像数据。
WPF 的渲染管线使用 GPU 加速,在图像绘制和缩放时性能更高。这是 WPF 和 Windows Forms 在处理图像时性能差异最大的地方。使用 PictureBox 时,所有的绘制和缩放操作都由 CPU 完成,而 WPF 则利用了 GPU 的强大计算能力。
WPF 默认使用双缓冲机制,减少了屏幕闪烁并提高了渲染效率。这虽然需要额外的内存,但通过 GPU 加速,整体性能更高。