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# 显示通常有两种方案:

  1. *使用 Windows Forms 和 PictureBox*

最简单的方法是不断创建新的 Bitmap 对象,然后将其赋值给 PictureBox 控件。这种方法实现简单,但性能较差,因为频繁创建和销毁 Bitmap 对象会导致大量的内存分配和释放。

优化的方案是使用 BitmapDataLockBits 方法来直接操作 Bitmap 的内存,从而只写入数据而不重新创建 Bitmap 对象。这种方式类似于 WriteableBitmap,可以显著提高性能。 Windows Forms 主要依赖 CPU 进行图像渲染,缺乏 GPU 加速,在处理复杂图像或高分辨率图像时性能较低。

  1. *使用 WPF 和 Image*

WPF 提供了 WriteableBitmap 类,可以直接操作图像的内存缓冲区。通过锁定和解锁 WriteableBitmap,可以高效地更新图像数据。

WPF 的渲染管线使用 GPU 加速,在图像绘制和缩放时性能更高。这是 WPF 和 Windows Forms 在处理图像时性能差异最大的地方。使用 PictureBox 时,所有的绘制和缩放操作都由 CPU 完成,而 WPF 则利用了 GPU 的强大计算能力。

WPF 默认使用双缓冲机制,减少了屏幕闪烁并提高了渲染效率。这虽然需要额外的内存,但通过 GPU 加速,整体性能更高。