首页 新闻 会员 周边 捐助

请教大神们,C# 通过相机采集图像,连续采集图像并保存的速度很慢的问题

0
悬赏园豆:20 [待解决问题] 浏览: 121次

有一个相机回调函数获取每次相机采集到的图像,然后有两个保存图像的方法,一个是最早写的,用于在识别到物体固定角度时进行拍照的,后来想加一个连续保存采集图像的功能,就放在第一个保存图像方法后面了,但是两个方法运行起来,连续采图每次保存一张tiff格式图像需要几毫秒到几十毫秒不等,并且会影响到识别物体角度的算法,导致其变慢。
我想到的方法是给连续保存采集图像的方法新开一个线程,但是不知道这个线程加在哪里好。
部分源码:
/// <summary>
/// 相机-图像回调
/// </summary>
private void Camera_ImageGrabbed(object sender, CameraImageGrabbedEventArgs e)
{
//生成图像
HOperatorSet.GenImageInterleaved(out image, (HTuple)e.DataPtr, (HTuple)"rgb", (HTuple)e.Width, (HTuple)e.Height, -1, "byte", 0, 0, 0, 0, -1, 0);
//识别物体角度并保存图像方法
GetAngleAndSaveImg( image);
//连续采集图像方法
SaveImageContinuous(image);
}
public void SaveImageContinuous(HObject image)
{
//...省略创建保存路径代码
HOperatorSet.WriteImage(image, "tiff", 0, file);
}
下方是连续保存图像用时和两次识别角度用时,耗时很长,而且应该是连续采图和识别角度共用一个线程的原因,怎么才能将二者分在两个线程呢

xiaozhuBJZ的主页 xiaozhuBJZ | 初学一级 | 园豆:113
提问于:2025-01-20 11:02
< > 人人可用的开源BI工具
分享
所有回答(5)
0

为何不使用异步委托呢?说实话,你的GetAngleAndSaveImgSaveImageContinuous这两个都不要放到这个回调里面,而是直接将图放到某个队列里面,做好同步取用即可。正常的相机回调不要放处理事务耗时长的代码。

寂静的羽夏 | 园豆:2263 (老鸟四级) | 2025-01-20 11:13
0

可以通过两个线程,照片采集放到队列里,处理线程从队列里取值。队列维持一个最大长度,防止无限增长

echo_lovely | 园豆:1584 (小虾三级) | 2025-01-20 13:13
1

在 C# 中,为了提高图像处理的性能并解决你提到的图像保存速度慢的问题,确实可以通过线程来实现并行处理。你可以使用 TaskThread 类来实现异步处理,从而将图像的保存与识别角度的操作分开到不同的线程中。

以下是你可以参考的一个改进代码示例,将 SaveImageContinuous 方法放在一个新的线程或任务中执行,以避免阻塞相机回调的主线程:

using System.Threading.Tasks;

private void Camera_ImageGrabbed(object sender, CameraImageGrabbedEventArgs e)
{
    // 生成图像
    HOperatorSet.GenImageInterleaved(out image, (HTuple)e.DataPtr, (HTuple)"rgb", (HTuple)e.Width, (HTuple)e.Height, -1, "byte", 0, 0, 0, 0, -1, 0);

    // 识别物体角度并保存图像方法
    GetAngleAndSaveImg(image);

    // 启动一个新的任务来保存连续图像
    Task.Run(() => SaveImageContinuous(image));
}

public void SaveImageContinuous(HObject image)
{
    // 省略创建保存路径代码
    HOperatorSet.WriteImage(image, "tiff", 0, file);
}

说明:

  1. 使用 Task.Run: 这样可以创建一个新的任务在后台运行 SaveImageContinuous 方法(保存图像),从而不阻塞主线程。主线程可以继续执行其他操作,如识别物体的角度。

  2. 并发处理: 这种设计允许多个图像在同一时间被处理。确保你处理的图像对象 HObject image 是线程安全的。如果它不是线程安全的,考虑在 SaveImageContinuous 方法中进行复制。

  3. 资源管理: 需要仔细管理图像内存,避免内存泄漏或同时访问可能导致的异常,特别是在快速采集图像的情况下。可以在 SaveImageContinuous 方法中创建独立的图像副本(如果 HObject 支持深复制),以便安全地在多个线程中使用。

其他技巧:

  • 使用异步方法: 有些文件系统操作可以使用异步模式(例如使用 WriteAsync)来提高性能。
  • 调整采集频率: 评估你的图像采集频率和保存策略,可能可以设计出一个动态调整的逻辑,只有在有物品识别时才触发保存,而不是每次都保存。

通过上述改进,你应该能显著提高采集图像和保存图像的速度,减少对图像识别算法的影响。如果有其他特定问题或需求,欢迎继续问我!

Technologyforgood | 园豆:7840 (大侠五级) | 2025-01-21 08:59
0

不加,直接丢到channel里面。然后你另外的地方去处理。
也就是回调过来你什么都不处理,直接丢channel里(当然你要不要设置背压数量你自己看着办)
然后另外的地方消费这个channel,你可以两个无关的task,也可以是2个顺序task,建议是2个无关task,毕竟保存和识别没有必然关联
提示背压数量控制,过多的并行task 会抢cpu和保存IO,所以需要测试一下确定一个背压阈值,在保证连续识别,运行流畅,磁盘io流畅的情况进行并行控制。否则你得找那个一线了,他又得喊你加内存了

gihelo01 | 园豆:206 (菜鸟二级) | 2025-01-21 15:10
0

it问题没有加一层解决不了的,加个队列缓存得到的图片,另外一个线程去保存图片,读写分离就解决了

w0rd | 园豆:463 (菜鸟二级) | 2025-01-25 17:22
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册
Top