有一个相机回调函数获取每次相机采集到的图像,然后有两个保存图像的方法,一个是最早写的,用于在识别到物体固定角度时进行拍照的,后来想加一个连续保存采集图像的功能,就放在第一个保存图像方法后面了,但是两个方法运行起来,连续采图每次保存一张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);
}
下方是连续保存图像用时和两次识别角度用时,耗时很长,而且应该是连续采图和识别角度共用一个线程的原因,怎么才能将二者分在两个线程呢
为何不使用异步委托呢?说实话,你的GetAngleAndSaveImg
和SaveImageContinuous
这两个都不要放到这个回调里面,而是直接将图放到某个队列里面,做好同步取用即可。正常的相机回调不要放处理事务耗时长的代码。
可以通过两个线程,照片采集放到队列里,处理线程从队列里取值。队列维持一个最大长度,防止无限增长
在 C# 中,为了提高图像处理的性能并解决你提到的图像保存速度慢的问题,确实可以通过线程来实现并行处理。你可以使用 Task
或 Thread
类来实现异步处理,从而将图像的保存与识别角度的操作分开到不同的线程中。
以下是你可以参考的一个改进代码示例,将 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);
}
使用 Task.Run
: 这样可以创建一个新的任务在后台运行 SaveImageContinuous
方法(保存图像),从而不阻塞主线程。主线程可以继续执行其他操作,如识别物体的角度。
并发处理: 这种设计允许多个图像在同一时间被处理。确保你处理的图像对象 HObject image
是线程安全的。如果它不是线程安全的,考虑在 SaveImageContinuous
方法中进行复制。
资源管理: 需要仔细管理图像内存,避免内存泄漏或同时访问可能导致的异常,特别是在快速采集图像的情况下。可以在 SaveImageContinuous
方法中创建独立的图像副本(如果 HObject
支持深复制),以便安全地在多个线程中使用。
WriteAsync
)来提高性能。通过上述改进,你应该能显著提高采集图像和保存图像的速度,减少对图像识别算法的影响。如果有其他特定问题或需求,欢迎继续问我!
不加,直接丢到channel里面。然后你另外的地方去处理。
也就是回调过来你什么都不处理,直接丢channel里(当然你要不要设置背压数量你自己看着办)
然后另外的地方消费这个channel,你可以两个无关的task,也可以是2个顺序task,建议是2个无关task,毕竟保存和识别没有必然关联
提示背压数量控制,过多的并行task 会抢cpu和保存IO,所以需要测试一下确定一个背压阈值,在保证连续识别,运行流畅,磁盘io流畅的情况进行并行控制。否则你得找那个一线了,他又得喊你加内存了
it问题没有加一层解决不了的,加个队列缓存得到的图片,另外一个线程去保存图片,读写分离就解决了