多线程调用 opencv 图像处理

背景

调用相机视频进行实时处理,原本是基于c++ 的线程池实现的,后来编译成 dll,转用 c# 的线程池实现,Dll 里面的图像的处理过程还是比较多的,但是经常会出现 dll 中内存地址访问冲突,通常是程序跑了一段时间之后。

通过 dll 的 debug,主要报错在图像的 resize/copyTo/clone 函数中,注释掉就没有报错了。

定位问题

先看下 copyTo 的实现

void GpuMat::copyTo(OutputArray dst, InputArray mask) const
{
    copyTo(dst, mask, Stream::Null());
}

这个直接用vs 跳转的,是 gpu 版本的定义;调用了以下第一个实现,注释中显示是non-blocking call,非阻塞的;不确定这里是不是线程安全的,通过 debug 定位到的问题就是,偶然会访问 image 的 data 出现访问冲突,读取字符出错…

搜索了很多关于 opencv 线程安全的处理方式,有建议用 UMat 的矩阵定义方式,但是更改起来太复杂;而且实现也不完全是跟 Mat 等价的。

最后发现似乎所有的情况都是跟访问 其中一个 Mat 有关,而这个 Mat 是根据 c# 传进来的图转化的,内存可能是跟 c# 是共享的,所以有时候会出错,在函数的入口直接 clone 一份,后面就没有复现这个问题。具体的原因还没完全定位到。

//! copies those GpuMat elements to "m" that are marked with non-zero mask elements (Non-Blocking call)
void copyTo(OutputArray dst, InputArray mask, Stream& stream) const;

//! copies those GpuMat elements to "m" that are marked with non-zero mask elements (Blocking call)    
void copyTo(OutputArray dst, InputArray mask) const;   
补充记录

c# 传图像到 dll 之后,对图像进行修改,然后在 c# 中直接取该图像即是修改后的图像数据,因为要展示到 wpf 的image 组件中,image 组件的 source 必须是 BitmapImage 类型,网上有 Bitmap 转换到 BitmapImage 的方式,但是有一个取内存的操作,目前我使用了 Emgv 的图像处理,所以读进来的图是 Image<Bitmap, byte>格式,提供一个默认的 img.toJpegData() 的方法,用于获取图像的二进制数据;但是后来发现这个步骤耗时很高,本机测试200ms,这个太夸张了。

改用网上的转换方式,将 Bitmap 转换成 byte[];速度为40ms+,至少已经好多了。

// 类似这样
Bitmap b = new Bitmap( "test.bmp "); 
MemoryStream ms = new MemoryStream(); 
b.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); 
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值